SQL Transactions - What they are good for and how they work
-
Upload
markus-winand -
Category
Technology
-
view
10.441 -
download
1
Transcript of 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
( ) 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
Transactions have CharacteristicsAccess-Mode:
READ_ONLY
READ_WRITE
Constraint Mode: IMMEDIATE
DEFERRED
Transaction-Isolation-Level: READUNCOMMITTED
READCOMMITTED
REPEATABLEREAD
SERIALIZABLE
Diagnostic Size:
Archaic
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
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.
Use Cases for Transactions
Use Cases for Transactions
When writing
Use Cases for Transactions
Backing out incomplete changes…
… by the program with rollback
… by the RDBMS in case of crash
When writing
Use Cases for Transactions
Backing out incomplete changes…
… by the program with rollback
… by the RDBMS in case of crash
When writing
(Boring)
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)
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)
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!
Standard Transaction Isolation LevelsPhenomena covered by the Standard
Dirty Read Non-Repeatable Read Phantom Read
READUNCOMMITTED
READCOMMITTED
REPEATABLEREAD
SERIALIZABLE
STOP
STOP STOP
STOPSTOPSTOP
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
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
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
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)
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)
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)
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)
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
Examples: Disclaimer
The following examples just demonstrateone possible way two transactions could interact.
The examples are by no means exhaustive.
Write Skew in Lock-based READ UNCOMMITTEDAccount Balance
1 1002 100
Transaction 1 Transaction 2
Write Skew in Lock-based READ UNCOMMITTEDAccount Balance
1 1002 100
Transaction 1 Transaction 2
▶ 1 -1002 100
UPDATEaccountsSETbalance=balance-200WHEREaccount=1
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
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)
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
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
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
Write Skew in Lock-based READ COMMITTED
Write Skew in Lock-based READ COMMITTEDAccount Balance
1 1002 100
Transaction 1 Transaction 2
Write Skew in Lock-based READ COMMITTEDAccount Balance
1 1002 100
Transaction 1 Transaction 2
▶ 1 -1002 100
UPDATEaccountsSETbalance=balance-200WHEREaccount=1
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
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
▶
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)▶
First Write, then Read: ConclusionFor this code, READCOMMITTED is enough to make one of the transactions succeed(assuming a proper deadlock detection).
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?
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
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)
Write-Skew: General Case
When using lock-based isolation
REPEATABLEREAD
covers with write-skew too.
What’s Bad About Locking?
What’s Bad About Locking?
Writers will always need to block writers anyway
What’s Bad About Locking?
Writers will always need to block writers anyway
Readers never block readers
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)
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!
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!
Multi Version Concurrency Control (MVCC)
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)
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
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
Write Skew When Using a SnapshotTransaction 1 Transaction 2Account Balance
1 1002 100
Write Skew When Using a SnapshotTransaction 1 Transaction 2
1 -1002 100
UPDATEaccountsSETbalance=balance-200WHEREaccount=1
Account Balance1 1002 100
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
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
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
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
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)
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)
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)
Can Snapshots and Serialisability Coexist?
Can Snapshots and Serialisability Coexist?Simple snapshots cannot prevent write skew abnormalities.
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)
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
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
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
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
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?
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
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
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
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.
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)