Handbooks / DBMS / Chapter 3

Transactions and ACID

7 pages · ~5 min✓ Reviewed

Builds on Indexing and Storage. Next up: Concurrency Control.

DBMSPage 1

Transactions and the ACID Mental Model

1. What a Transaction Is

  • A transaction = a group of statements run as one all-or-nothing unit of work
  • Money transfer = debit + credit, together or not at all
  • Failure midway undoes everything already done
  1. BEGIN
  2. Debit Astatement 1
  3. Credit Bstatement 2
  4. COMMITor undo all

2. The Four Guarantees

GuaranteeDetail
AtomicityAll apply or noneFailure midway undoes all
ConsistencyValid state to valid statePK, FK, CHECK, UNIQUE never violated
IsolationLooks like one at a timeOnly as far as the chosen level allows
DurabilitySurvives crash or power lossAfter COMMIT returns, data is in the log on disk

3. Durability Chain

  1. 1Write log
  2. 2Flush log to disk
  3. 3COMMIT returns
Remember

Isolation is a dial, not a guarantee of full serial behaviour: the level you choose decides what other transactions can interfere with.

DBMSPage 2

Commit, Rollback and Savepoints in Practice

1. Core flow

  1. BEGINopen transaction
  2. Run statements
  3. COMMITmake permanent
  4. ROLLBACKdiscard all changes
  • Transfer: both updates apply together, or neither
sql
BEGIN;
UPDATE accounts SET bal = bal - 100 WHERE id = 1;
UPDATE accounts SET bal = bal + 100 WHERE id = 2;
COMMIT;

debit + credit as one unit

2. Autocommit and savepoints

  • Autocommit: each statement is its own transaction
  • BEGIN (START TRANSACTION) turns it off until COMMIT/ROLLBACK
  • ROLLBACK TO sp1 undoes only work after the savepoint; transaction stays open
sql
SAVEPOINT sp1;
-- more statements
ROLLBACK TO sp1;
COMMIT;

work before sp1 is still committed

3. Gotchas

MySQLPostgreSQL
DDLimplicit committransactional DDL
Postgres error

An error aborts the whole transaction: every statement fails until you ROLLBACK.

DBMSPage 3

Read Anomalies: Dirty, Non-Repeatable and Phantom

1. Three read anomalies

AnomalyWhat you seeOther transaction
Dirty readuncommitted change, wrong if it rolls backnot committed yet
Non-repeatable readsame row, different value on re-readcommitted an UPDATE
Phantom readsame range query, different set of rowscommitted an INSERT or DELETE matching the predicate

2. Lost update

  • Both transactions read the same value, then both write
  • One overwrite is silently lost
  • Fix: lock the row with SELECT ... FOR UPDATE, or use one atomic UPDATE
sql
SELECT bal FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET bal = bal + 1 WHERE id = 1;

either form works; the atomic UPDATE needs no prior read

3. Write skew

  • Two transactions read overlapping data, update different rows
  • Together they break an invariant: two doctors both go off-call
  • Needs SERIALIZABLE or explicit locking
Same row or different rows

Lost update hits the same row: lock it or use an atomic UPDATE. Write skew hits different rows: only SERIALIZABLE or explicit locking stops it.

DBMSPage 4

Isolation Levels Compared

1. The four levels

LevelDirtyNon-rep.PhantomDefault
READ UNCOMMITTEDyesyesyesrarely used
READ COMMITTEDnoyesyesPostgreSQL, Oracle, SQL Server
REPEATABLE READnonoyes (standard)MySQL InnoDB
SERIALIZABLEnonononone

2. How each one behaves

  • READ COMMITTED: each statement sees data committed before it started
  • REPEATABLE READ: one snapshot from the first read
  • InnoDB adds gap locks, blocking most phantoms
  • SERIALIZABLE: outcome equals some serial order, paid in locks or aborts
  • The app must retry serialization failures

3. Setting the level

  • Set it per transaction; the order differs by database, and MySQL gives ERROR 1568 if it is wrong
sql
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

PostgreSQL: after BEGIN, before the first query

sql
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;

MySQL: before START TRANSACTION, applies to the next one

Pick the lowest safe level

Higher isolation means less concurrency and more conflicts.

DBMSPage 5

Write-Ahead Logging and Crash Recovery

1. The WAL Rule

  • WAL rule: the log record is flushed before the data page it describes
  • COMMIT needs only the log flush, a sequential write
  • Data pages are written lazily later, so durability is cheap
Durability chain
  1. 1Write logchange record
  2. 2Flush logsequential
  3. 3Ack COMMITdurable
  4. 4Write pageslater

2. Steal / No-Force and Checkpoints

PolicyDirty page is writtenSo the log needs
Stealbefore commitundo
No-forcenot forced at commitredo
  • Checkpoint: flush dirty pages and record a log position
  • Recovery replays only the log after it, so replay is bounded

3. ARIES Recovery: 3 Passes

  1. Analysisfind dirty pages, active txns
  2. Redoreplay logged changes
  3. Undoroll back uncommitted
After a crash

Redo committed work, undo uncommitted work.

DBMSPage 6

Transactions Cheat Sheet

1. ACID and Commands

  • Atomicity: all or nothing
  • Consistency: valid state to valid state
  • Isolation: no interference
  • Durability: survives a crash
sql
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SAVEPOINT x;
ROLLBACK TO x;
COMMIT;  -- or ROLLBACK;

PostgreSQL order: SET TRANSACTION right after BEGIN

  • MySQL: SET TRANSACTION goes before START TRANSACTION; after it, ERROR 1568

2. Isolation and Locks

LevelNon-repeatablePhantom
READ COMMITTEDallowedallowed
REPEATABLE READpreventedallowed (standard)
SERIALIZABLEpreventedprevented
  • SELECT ... FOR UPDATE locks selected rows: stops lost updates
  • Keep transactions short: fewer lock waits and deadlocks

3. Durability Chain

  1. Write log
  2. Flush log
  3. Ack COMMIT
  4. Data pageswritten later
After a crash

Redo committed work, undo uncommitted work.

DBMSPage 7

Check yourself

PostgreSQL, default level. T1 reads a balance (100). T2 sets it to 50 and commits. T1 reads again. What does T1 see?
  • 50, a non-repeatable read
  • REPEATABLE READ would still show 100 (snapshot)
Two sessions each read bal (100), then write bal = 110 from the app. What is the final balance, and what is the fix?
  • 110, so one +10 is lost (lost update)
  • Use UPDATE SET bal = bal + 10 or SELECT ... FOR UPDATE
PostgreSQL: BEGIN; INSERT ok; INSERT violates UNIQUE; INSERT ok; COMMIT. What persists?
  • Nothing
  • The error aborts the transaction, and later statements fail until ROLLBACK
  • COMMIT then acts as a ROLLBACK
COMMIT returned, then power failed before the data page reached disk. Is the change lost?
  • No
  • The log was flushed first (WAL)
  • Recovery redoes the change from the log