25,560 words, 5 top-level sections, 10 exercises. The longest chapter in the book and the one where the most people come away confidently wrong. This is a map of how to read it — what to read closely, what to skim, where to stop and run something, and which passages get misread.
tools/verify_quotes.py (14/14 at publish time). Everything else — read-weights, misreads, cross-chapter threads — is my editorial judgment. Words in [grey brackets] inside a quote are also mine, supplying a referent the excerpt leaves dangling; the checker enforces that the text around them is the book's. Trust the quotes; argue with the rest.
This chapter assumes three things from earlier. Ch. 6 — leaderless and multi-leader replication, and last-write-wins conflict resolution; the §"Conflict resolution and replication" subsection here is unreadable without it. Ch. 7 — sharding, because cross-shard coordination is the whole cost story of serial execution and distributed transactions. Ch. 4 — the write-ahead log, which is the mechanism under both single-node durability and the 2PC commit point.
Transactions are an abstraction layer that allows an application to pretend that certain concurrency problems and certain kinds of hardware and software faults don't exist. A large class of errors is reduced to a simple transaction abort, and the application just needs to try again.
Everything else is the price list for that pretending. The chapter's real argument is that the abstraction leaks at every isolation level below serializable, and it spends 25,000 words showing you exactly where.
| Section | Words | Read | What it's for | Then run |
|---|---|---|---|---|
| What Exactly Is a Transaction? — 4,004 | ||||
| The Meaning of ACID | 2,008 | Close | The vocabulary the rest of the book uses. Note that C is the odd one out — it's the application's job, not the database's. | — |
| Single-Object and Multi-Object Operations | 1,683 | Skim | Motivating examples. One idea: multi-object writes need a way to say which writes belong together. | — |
| Weak Isolation Levels — 7,435 · the core of the chapter | ||||
| (intro) | 587 | Close | Short, and sets the stakes — race conditions at this level bankrupted a Bitcoin exchange. | — |
| Read Committed | 1,117 | Close | The two guarantees everything else is defined against. | dirty-read-impossible |
| Snapshot Isolation and Repeatable Read | 2,277 | Close | The densest pages in the chapter: MVCC, visibility rules, and the naming disaster. | read-skew, mvcc-no-blocking, update-bloat-mvcc |
| Preventing Lost Updates | 1,608 | Close | A menu of five fixes. Know which ones your database does for you. | lost-update, compare-and-set |
| Write Skew and Phantoms | 1,850 | Close | The hardest idea in the chapter, and the one interviews ask about. | write-skew-doctors, phantom-write-skew |
| Serializability — 5,660 | ||||
| (intro) | 365 | Close | Names the three implementations. Read it as the section's table of contents. | — |
| Actual Serial Execution | 1,628 | Skim | Real but niche (VoltDB, Redis). Keep the why it became viable argument, drop the details. | — |
| Two-Phase Locking | 1,804 | Close → Ref | Close through §"Predicate locks" and §"Index-range locks"; the performance subsection is reference. | deadlock-detection |
| Serializable Snapshot Isolation | 1,866 | Close | The payoff of the chapter — how you get serializability without the 2PL tax. | — |
| Distributed Transactions — 4,986 | ||||
| (intro) + Two-Phase Commit | 2,261 | Close | The system of promises, and why the coordinator's disk is the commit point. | prepared-transaction-locks |
| Distributed Transactions Across Different Systems | 1,855 | Skim | XA is a 1991 C API you probably won't touch. Do read §"Holding locks while in doubt." | — |
| Database-Internal Distributed Transactions | 323 | Close | Tiny and important: why CockroachDB/Spanner escape XA's problems. | — |
| Exactly-Once Message Processing Revisited | 551 | Close | The most directly usable pattern in the chapter. | — |
| Summary | 3,475 | Ref | Table 8-1 is the single artifact worth memorizing. The prose recap is skippable if the exercises landed. | — |
1. "ACID" tells you almost nothing. The chapter demolishes its own title concept early, and everything after depends on you having accepted this:
Today, when a system claims to be "ACID compliant," it's unclear what guarantees you can actually expect. "ACID" has unfortunately become mostly a marketing term.
2. Weak isolation is the default, not the exception. The section opens with real money lost to weak-isolation race conditions — a bankrupted Bitcoin exchange, an investigation by financial auditors, corrupted customer data — and then closes the escape hatch you'd reach for, which is "use a proper ACID database":
Even many popular relational database systems (which are usually considered ACID) use weak isolation, so they wouldn't necessarily have prevented these bugs from occurring.
That is the sentence that should make you check what isolation level your production database is actually running.
3. Write skew is the anomaly that only serializability closes. Every other race in the chapter has a cheaper fix; this one doesn't. Tested directly by write-skew-doctors, where Postgres's REPEATABLE READ lets both doctors leave:
Automatically preventing write skew requires true serializable isolation
4. The MVCC/2PL divide is one sentence. Snapshot isolation's design principle is that readers never block writers, and writers never block readers
— and 2PL is precisely the negation of it. Confirm with mvcc-no-blocking:
In 2PL, writers don't just block other writers; they also block readers, and vice versa.
5. SSI's trick is that its locks don't lock. When a transaction writes, SSI looks in the indexes for other transactions that recently read that data — the same bookkeeping 2PL uses to take a write lock, but with the waiting taken out:
rather than blocking until the readers have committed, the lock acts as a tripwire; it simply notifies the transactions that the data they read may no longer be up-to-date.
The abort still happens, just at commit time instead of read time — which is why long read-only transactions stay cheap under SSI.
6. 2PC's failure mode is held locks, not lost data. The reason distributed transactions have the reputation they do — and what prepared-transaction-locks makes you watch survive a full server restart:
If the coordinator's log is entirely lost for some reason, those locks [the row locks every in-doubt participant took before voting yes] will be held forever—or at least until the situation is manually resolved by an administrator.
"Repeatable read means repeatable read." It doesn't mean anything reliable. In PostgreSQL it's snapshot isolation; in MySQL it's weaker than snapshot isolation; in Db2 it's serializability. The book's verdict is blunt:
nobody really knows what repeatable read isolation means
If you read one thing closely in this chapter, make it this subsection. Every "but my database prevents that" argument dies here.
"Atomicity protects me from concurrent writers." It doesn't — that's isolation. The A and the I get conflated constantly because "atomic" means something different in multithreaded programming:
in the context of ACID, atomicity is not about concurrency
The book even concedes the name is bad: Perhaps abortability would have been a better term than atomicity
.
"Snapshot isolation prevents lost updates, so I'm fine." Sometimes — and which "sometimes" is a per-database fact you have to look up. PostgreSQL's repeatable read detects them; MySQL's does not:
MySQL/InnoDB's repeatable read isolation level does not detect lost updates
lost-update is worth running precisely because the answer depends on the engine, not the standard.
"Serializable is too slow to consider." True of 2PL, and that reputation outlived its cause by about fifteen years. SSI changed the trade:
an algorithm called serializable snapshot isolation (SSI) provides full serializability with only a small performance penalty compared to snapshot isolation
"2PL and 2PC are two halves of one thing." They share nothing but a number. The book puts a box in the middle of the chapter to say so — 2PL is single-node isolation, 2PC is distributed atomic commit.
"Exactly-once delivery requires distributed transactions." The last section quietly dismantles this, and it's the most practically useful paragraph in the chapter:
achieving exactly-once processing requires only transactions within the database—atomicity across database and message broker is not necessary for this use case [acknowledging a broker message exactly when the writes that processed it commit]
Back: Ch. 6 — lost updates reappear as LWW conflict resolution, and this chapter's locks assume the single up-to-date copy that leaderless replication denies you. Ch. 7 — cross-shard transactions are why serial execution stops scaling.
Forward: Ch. 9 is the direct sequel — 3PC fails here because networks have unbounded delay, which is exactly what Ch. 9 formalizes. Ch. 10 supplies the fix this chapter defers: replace the single-node coordinator with consensus. Note also that serializability (this chapter) and linearizability (Ch. 10) are different guarantees that both get called "consistency"; the book flags the overloading here but doesn't resolve it until Ch. 10. Ch. 12 revisits exactly-once semantics in stream processing.