Serializable Snapshot Isolation in PostgreSQL
Dan Ports University of Washington MIT Kevin Grittner Wisconsin Supreme Court
Tuesday, August 28, 2012
Serializable Snapshot Isolation in PostgreSQL Dan Ports Kevin - - PowerPoint PPT Presentation
Serializable Snapshot Isolation in PostgreSQL Dan Ports Kevin Grittner University of Washington Wisconsin Supreme Court MIT Tuesday, August 28, 2012 For years, PostgreSQLs SERIALIZABLE mode did not provide true serializability
Dan Ports University of Washington MIT Kevin Grittner Wisconsin Supreme Court
Tuesday, August 28, 2012
For years, PostgreSQL’s “SERIALIZABLE” mode did not provide true serializability
PostgreSQL 9.1: Serializable Snapshot Isolation
& first in a purely-snapshot DB
Tuesday, August 28, 2012
Tuesday, August 28, 2012
Two perspectives:
don’t need to worry about race conditions
use weaker isolation levels instead
Tuesday, August 28, 2012
PostgreSQL offered snapshot isolation instead
“readers don’t block writers, writers don’t block readers”
Snapshot isolation isn’t enough for some users
e.g. Wisconsin Court System
Tuesday, August 28, 2012
PostgreSQL offered snapshot isolation instead
“readers don’t block writers, writers don’t block readers”
Snapshot isolation isn’t enough for some users
e.g. Wisconsin Court System
Serializable Snapshot Isolation
performance benefits of snapshot isolation!
Tuesday, August 28, 2012
abort transactions to prevent anomalies
Appealing for performance reasons
[Cahill et al. Serializable Isolation for Snapshot Databases, SIGMOD ’08]
Tuesday, August 28, 2012
Available in PostgreSQL 9.1; first production implementation Contributions: new implementation techniques
Tuesday, August 28, 2012
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
Tuesday, August 28, 2012
BEGIN SELECT count(*) FROM guards WHERE on-duty = y if > 1 { UPDATE guards SET on-duty = n WHERE guard = x } COMMIT
guard
uty? Alice y Bob y
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2]
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2]
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guards = ‘Bob’ } COMMIT BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guards = ‘Bob’ } COMMIT BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n n
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guards = ‘Bob’ } COMMIT BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n n
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guards = ‘Bob’ } COMMIT BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n n
rw-conflict: T1 didn’t see T2’s UPDATE
Tuesday, August 28, 2012
guard
uty? Alice y Bob y
BEGIN SELECT count(*) FROM guard WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guards = ‘Bob’ } COMMIT BEGIN SELECT count(*) FROM guards WHERE on-duty = y [result = 2] if > 1 { UPDATE guards SET on-duty = n WHERE guard = ‘Alice’ } COMMIT
n n
rw-conflict: T1 didn’t see T2’s UPDATE rw-conflict: T2 didn’t see T1’s UPDATE
Tuesday, August 28, 2012
Tuesday, August 28, 2012
rw-conflict: T1 didn’t see T2’s UPDATE
rw-conflict: T2 didn’t see T1’s UPDATE
Tuesday, August 28, 2012
rw-conflict: T1 didn’t see T2’s UPDATE
rw-conflict: T2 didn’t see T1’s UPDATE
Tuesday, August 28, 2012
rw-conflict: T1 didn’t see T2’s UPDATE
rw-conflict: T2 didn’t see T1’s UPDATE
ERROR: could not serialize access due to read/write dependencies among transactions HINT: The transaction might succeed if retried.
Tuesday, August 28, 2012
Tuesday, August 28, 2012
Tuesday, August 28, 2012
Tuesday, August 28, 2012
=> no deadlocks
Tuesday, August 28, 2012
Tuesday, August 28, 2012
Many long-running transactions are read-only;
Safe snapshots: cases where r/o transactions can never be a part of an anomaly
transactions complete
Deferrable transactions: delay execution to ensure safe snapshot
Tuesday, August 28, 2012
What if we still run out of memory? Don’t want to refuse to accept new transactions Instead: keep less information (tradeoff: more false positives)
transaction”
Tuesday, August 28, 2012
Tuesday, August 28, 2012
Tuesday, August 28, 2012
0.4x 0.5x 0.6x 0.7x 0.8x 0.9x 1.0x 0% 20% 40% 60% 80% 100% SI SSI SSI (no r/o opt.) S2PL
25 warehouses (3 GB), tmpfs
(normalized) Fraction of read-only transactions
Tuesday, August 28, 2012
150 warehouses (19 GB)
(normalized) Fraction of read-only transactions
0.4x 0.5x 0.6x 0.7x 0.8x 0.9x 1.0x 0% 20% 40% 60% 80% 100% SI SSI S2PL
Tuesday, August 28, 2012
Tuesday, August 28, 2012