Two customers were both sold the last box of strawberries, and nothing errored. Six topics explain why that is the documented behaviour of the default isolation level, fix it three ways with three different costs, and show what an open transaction costs the rest of the cluster.
6 topics
Chapter 5 opened the file and showed what a row physically is: a header, a set of column values, a line pointer, and after an update a second complete copy of the same row sitting on the page beside the first. This chapter is about the other half of that picture — which of those copies a given transaction is allowed to see, and who decides.
The answer is a snapshot, and it is small: three numbers that every row version on every page is judged against. Everything people find surprising about concurrency in Postgres falls out of that structure and of when it is taken. Two identical queries in one transaction returning different counts, a report that disagrees with the dashboard, an UPDATE that affects zero rows, a serialization failure at three in the morning, and an idle connection that stops a 900 MB table from ever shrinking — five symptoms, one mechanism.
One of Cartwheel's two open wounds closes here. On a Saturday in March, two checkouts read on_hand = 1 for the same box of strawberries, both decided the sale was fine, and both wrote zero. Topic 30 fixes it three ways: a single guarded statement at the default isolation level, an explicit row lock, and Serializable with a retry loop — with a recommendation and the reasoning behind it, rather than three options and a shrug. The Saturday-morning slowdown stays open; that one is a planner problem and belongs to Chapter 9.