The Runtime Theory

MVCC Visibility: xmin, xmax, and Which Version You See

Decode the multiversion visibility check: how xmin and xmax on each tuple decide which row version a transaction snapshot is allowed to see.

The Runtime Theory Team08 stages

trace / request.md

WRITES GET ATRANSACTION IDSNAPSHOT CAPTURESIN-FLIGHT XIDSSCAN MEETS AROW VERSIONCREATOR MUSTBE VISIBLEDELETERMAY HIDE ITMARKERS MEETTHE SNAPSHOTONE VERSION WINSVERSION REACHESTHE QUERY

readyEvery write transaction receives a monotonically increasing transaction ID (xid). Old row versions are not destroyed on update — they are kept so concurrent readers can still see history.

MVCC makes reads lock-free by making them a comparison problem. Every row version carries two transaction IDs — xmin, who created it, and xmax, who deleted it — and the visibility check is a series of comparisons between those markers and the reader's snapshot. This diagram shows the actual decision procedure a scan runs per version: is the creator committed and old enough? Is the deleter committed? Does either match my own transaction?

The elegance is that the snapshot is just data — a list of in-flight transaction IDs captured at one instant — so visibility never requires waiting on anyone. A writer committing mid-scan simply never appears in that snapshot's in-flight set. The cost is version accumulation: old versions linger until no snapshot can see them, which is exactly what vacuum exists to reclaim. Understanding the check in this order — xid, snapshot, xmin, xmax — makes every concurrency question answerable.