SQL Transactions - What they are good for and how they work

72
© 2016 by Markus Winand Transactions What they are good for and how they work

Transcript of SQL Transactions - What they are good for and how they work

Page 1: SQL Transactions - What they are good for and how they work

© 2016 by Markus Winand

Transactions

What they are good for and how they work

Page 2: SQL Transactions - What they are good for and how they work

( ) Transactions are Brackets

Starting a transaction:

Explicit: STARTTRANSACTION

Implicit:

INSERT / UPDATE / DELETE

SELECT

CREATE

Terminating a transaction:

Explicit: COMMIT

ROLLBACK

Implementation defined:

Due to errors

CREATE

Variesamongstproducts

Page 3: SQL Transactions - What they are good for and how they work

Transactions have CharacteristicsAccess-Mode:

READ_ONLY

READ_WRITE

Constraint Mode: IMMEDIATE

DEFERRED

Transaction-Isolation-Level: READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

Diagnostic Size:

Archaic

Page 4: SQL Transactions - What they are good for and how they work

Transactions have CharacteristicsAccess-Mode:

READ_ONLY

READ_WRITE

Constraint Mode: IMMEDIATE

DEFERRED

Transaction-Isolation-Level: READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

Diagnostic Size:

Archaic

Not strictly a

transaction

characterist

ic

Page 5: SQL Transactions - What they are good for and how they work

Setting Transaction CharacteristicsWith explicit transaction begin:

STARTTRANSACTIONISOLATIONLEVELSERIALIZABLEREADWRITE

For next (implicitly started) transaction: SETTRANSACTIONISOLATIONLEVELSERIALIZABLEREADWRITE

The standard uses SERIALIZEABLE as default,but most implementations default to READCOMMITTED.

In practice: Use an API if possible.

Page 6: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Page 7: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

When writing

Page 8: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Backing out incomplete changes…

… by the program with rollback

… by the RDBMS in case of crash

When writing

Page 9: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Backing out incomplete changes…

… by the program with rollback

… by the RDBMS in case of crash

When writing

(Boring)

Page 10: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Backing out incomplete changes…

… by the program with rollback

… by the RDBMS in case of crash

When writing When reading

(Boring)

Page 11: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Backing out incomplete changes…

… by the program with rollback

… by the RDBMS in case of crash

When writing When readingSimplify concurrent programs…

… by utilising the right transaction isolation level

(Boring)

Page 12: SQL Transactions - What they are good for and how they work

Use Cases for Transactions

Backing out incomplete changes…

… by the program with rollback

… by the RDBMS in case of crash

When writing When readingSimplify concurrent programs…

… by utilising the right transaction isolation level

(Boring) Amazing!

Page 13: SQL Transactions - What they are good for and how they work

Standard Transaction Isolation LevelsPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

STOP

STOP STOP

STOPSTOPSTOP

Page 14: SQL Transactions - What they are good for and how they work

Standard Transaction Isolation LevelsPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

STOP

STOP STOP

STOPSTOPSTOP

Incomplete,

unfortunately

Page 15: SQL Transactions - What they are good for and how they work

How Comes?

SQL is a declarative language:the standard doesn’t say how to implement it,

it just describes the effects it has.

Unfortunately, SQL-92 was written with locking in mind,and thus only describes the effects in the granularity

in which they appear whey implemented using locking.

Although a commonly known issue, it was never changed.

https://en.wikipedia.org/wiki/Snapshot_isolation

Page 16: SQL Transactions - What they are good for and how they work

Transaction Isolation Using LocksPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

▶ Row (short) ▶ Row (TX) ▶ Row (TX)▶ Predicate (TX)

STOP

STOP STOP

STOPSTOPSTOP

Page 17: SQL Transactions - What they are good for and how they work

Transaction Isolation Using LocksPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

▶ Row (short) ▶ Row (TX) ▶ Row (TX)▶ Predicate (TX)

STOP

STOP STOP

STOPSTOPSTOPLocks preventing

phenomena:What (how long)

Page 18: SQL Transactions - What they are good for and how they work

Transaction Isolation Using LocksPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

▶ Row (short) ▶ Row (TX) ▶ Row (TX)▶ Predicate (TX)

STOP

STOP STOP

STOPSTOPSTOPLocks preventing

phenomena:What (how long)

Page 19: SQL Transactions - What they are good for and how they work

Transaction Isolation Using LocksPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

▶ Row (short) ▶ Row (TX) ▶ Row (TX)▶ Predicate (TX)

STOP

STOP STOP

STOPSTOPSTOPLocks preventing

phenomena:What (how long)

Page 20: SQL Transactions - What they are good for and how they work

Transaction Isolation Using LocksPhenomena covered by the Standard

Dirty Read Non-Repeatable Read Phantom Read

READUNCOMMITTED

READCOMMITTED

REPEATABLEREAD

SERIALIZABLE

▶ Row (short) ▶ Row (TX) ▶ Row (TX)▶ Predicate (TX)

STOP

STOP STOP

STOPSTOPSTOPLocks preventing

phenomena:What (how long)

Page 21: SQL Transactions - What they are good for and how they work

Example: Write SkewMake sure the sum of two rows is positive

(e.g., two bank accounts belonging to the same person)

Code to withdraw from one account (naive schema and not considering concurrency)

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

SELECTSUM(balance)FROMaccountsWHEREaccountIN(1,2)

>= 0 commit<0 rollback

Page 22: SQL Transactions - What they are good for and how they work

Examples: Disclaimer

The following examples just demonstrateone possible way two transactions could interact.

The examples are by no means exhaustive.

Page 23: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

Page 24: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Page 25: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

Page 26: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Page 27: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

-200

Page 28: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

-200

Page 29: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ UNCOMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

-200

-200

Page 30: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTED

Page 31: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

Page 32: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Page 33: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

Page 34: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Blocked

Page 35: SQL Transactions - What they are good for and how they work

Write Skew in Lock-based READ COMMITTEDAccount Balance

1 1002 100

Transaction 1 Transaction 2

▶ 1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

▶ 1 -1002 -100 ◀

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Blocked

Dead lock▶

◀▶ 1 -1002 -100 ◀

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)▶

Page 36: SQL Transactions - What they are good for and how they work

First Write, then Read: ConclusionFor this code, READCOMMITTED is enough to make one of the transactions succeed(assuming a proper deadlock detection).

Page 37: SQL Transactions - What they are good for and how they work

First Write, then Read: ConclusionFor this code, READCOMMITTED is enough to make one of the transactions succeed(assuming a proper deadlock detection).

Exercise: Does this hold true in these cases too?

Page 38: SQL Transactions - What they are good for and how they work

First Write, then Read: ConclusionFor this code, READCOMMITTED is enough to make one of the transactions succeed(assuming a proper deadlock detection).

Exercise: Does this hold true in these cases too?SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

(iff >= 200) UPDATEaccountsSETbalance=balance-200WHEREaccount=:a

Page 39: SQL Transactions - What they are good for and how they work

First Write, then Read: ConclusionFor this code, READCOMMITTED is enough to make one of the transactions succeed(assuming a proper deadlock detection).

Exercise: Does this hold true in these cases too?SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

(iff >= 200) UPDATEaccountsSETbalance=balance-200WHEREaccount=:a

SELECTbalanceFROMaccountsWHEREaccount=:a

UPDATEaccountsSETbalance=:bWHEREaccount=:a

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Page 40: SQL Transactions - What they are good for and how they work

Write-Skew: General Case

When using lock-based isolation

REPEATABLEREAD

covers with write-skew too.

Page 41: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Page 42: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Writers will always need to block writers anyway

Page 43: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Writers will always need to block writers anyway

Readers never block readers

Page 44: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Writers will always need to block writers anyway

Readers never block readersWriters block readers,

readers block writers (except in READUNCOMMITTED)

Page 45: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Writers will always need to block writers anyway

Readers never block readersWriters block readers,

readers block writers (except in READUNCOMMITTED)

Great!

Page 46: SQL Transactions - What they are good for and how they work

What’s Bad About Locking?

Writers will always need to block writers anyway

Readers never block readersWriters block readers,

readers block writers (except in READUNCOMMITTED)

Not so good

Great!

Page 47: SQL Transactions - What they are good for and how they work

Multi Version Concurrency Control (MVCC)

Page 48: SQL Transactions - What they are good for and how they work

Multi Version Concurrency Control (MVCC)Instead of waiting for writers,

just use the previous committed version of the data (pretend the read happened before the write)

Page 49: SQL Transactions - What they are good for and how they work

Multi Version Concurrency Control (MVCC)Instead of waiting for writers,

just use the previous committed version of the data (pretend the read happened before the write)

The reader effectively works on a snapshot

Page 50: SQL Transactions - What they are good for and how they work

Multi Version Concurrency Control (MVCC)Instead of waiting for writers,

just use the previous committed version of the data (pretend the read happened before the write)

The reader effectively works on a snapshot

This prevents all three phenomena mentioned in the standard: dirty read

non-repeatable read phantom read

Page 51: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2Account Balance

1 1002 100

Page 52: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

Page 53: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

Page 54: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

Page 55: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

Page 56: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

1 -1002 100

Page 57: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

1 -1002 100

1 1002 -100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Page 58: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

Account Balance1 -1002 -100

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

1 -1002 100

1 1002 -100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Page 59: SQL Transactions - What they are good for and how they work

Write Skew When Using a SnapshotTransaction 1 Transaction 2

1 1002 -100

UPDATEaccountsSETbalance=balance-200WHEREaccount=2

Account Balance1 -1002 -100

1 -1002 100

UPDATEaccountsSETbalance=balance-200WHEREaccount=1

Account Balance1 1002 100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

1 -1002 100

1 1002 -100

SELECTsum(balance)FROMaccountsWHEREaccountIN(1,2)

Page 60: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?

Page 61: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

Page 62: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

Page 63: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

Page 64: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

READ ONLY transactions

are an important special case

Page 65: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

READ ONLY transactions

are an important special case

InnoDBSQL Server

DB2

Page 66: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

READ ONLY transactions

are an important special case

InnoDBSQL Server

DB2 PostgreSQL

Page 67: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

READ ONLY transactions

are an important special case

InnoDBSQL Server

DB2 PostgreSQL

Oracle?

Page 68: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.

But most transactions arenot vulnerable to write skew anyway.

(e.g., TPC-C is not vulnerable at all)

The only two ways to prevent write skew abnormalities at the database are(1) putting locks when reading and

(2) proofing the serialization graph is acyclic

READ ONLY transactions

are an important special case

InnoDBSQL Server

DB2 PostgreSQL

Page 69: SQL Transactions - What they are good for and how they work

Can Snapshots and Serialisability Coexist?PostgreSQL 9.1+ is the only(?) database that

uses MVCC and detects serialization graph cycles. ➜ Use SERIALIZABLE and you are done

In InnoDB (MySQL, MariaDB) and SQL Server, MVCC and Lock-Based SERIALIZABLE isolation can be

Page 70: SQL Transactions - What they are good for and how they work

How to use Snapshots and Prevent Write SkewTransaction type

READ ONLY READ/WRITE

DB2 LUW REPEATABLEREAD(=SERIALIZABLE)

REPEATABLEREAD(=SERIALIZALBE)

InnoDB(MySQL, MariaDB) REPEATABLEREAD1 SERIALIZABLE

PostgreSQL 9.1+ SERIALIZABLE SERIALIZABLE

Oracle SERIALIZABLE SERIALIZABLE

SQL Server 2005+ SNAPSHOT SERIALIZABLE

1: MySQL’s REPEATABLE READ also protects against phantom reads.

KEYNo shared locks

No write skew issuesShared locks

No write skew issuesNo shared locks

Write skew issues

Page 71: SQL Transactions - What they are good for and how they work

SQL Server is SpecialExcept SQL Server, all MVCC capable databases use it per default.

In SQL Server, it must be enabled: ALTERDATABASE…SETallow_snapshot_isolationon;

This will make write operations keep old versions(needs more space in permanent DB and tempdb)

Then you can use SNAPSHOT isolation (e.g., in read-only transactions).Staying in SERIALISABLE for read/write transactions prevents write skew issues.

Note: Hint remain effective: NOLOCK will still do dirty-read in SNAPSHOT isolation.

Page 72: SQL Transactions - What they are good for and how they work

Keep Transactions FocusedDon’t select data that is irrelevant for the transaction.

(an innocent looking function-call might query something you are not aware of)

Do unrelated stuff in distinct transactions.

Work fast.(Never, ever keep a transaction open waiting for someone)

(In the code, but also not in your ad-hoc SQL session!)

Tune your statements.(That makes your transactions shorter too)