Date: 2026-05-29
Time: 07:31
DDIA's core insight about snapshot isolation is that you can avoid read-write conflicts entirely by giving each transaction a frozen view of the database at the moment it started. Writers never modify existing data — they append new versions. The MVCCDatabase in this codebase implements exactly that pattern.
Every value in the database exists as a Version object (snapshot-isolation/mvcc_database.py:12-17). A version records *who created it* and *who deleted it*:
class Version:
def __init__(self, key, value, created_by, deleted_by=None):
The database stores these as append-only lists per key (versions: a dict mapping keys to list[Version], line 55). When a transaction writes a key, it doesn't touch the old version — it appends a new Version to the list (lines 143-149). When it deletes, it doesn't remove anything — it stamps deletedby on the existing visible version (lines 157-162). Old versions remain intact for concurrent readers.
This is DDIA's "writers create new versions" principle made concrete: the versions lists grow monotonically, and the only mutations are setting deletedby on a version or updating a version the *same* transaction already created (line 140-141, a self-write optimization).
The snapshot is defined by the visibility function isvisible (lines 77-112). This is the heart of MVCC. A version is visible to transaction tx if and only if:
1. The creating transaction committed before tx started — checked via createdby in self.committed, createdby not in tx.activeatstart, and createdby < tx.tx_id (lines 91-95). This three-part check implements DDIA's snapshot rule: you see committed data from transactions that finished before your snapshot, but not from transactions that were still in-flight.
2. Own writes are always visible — createdby == tx.txid (line 89). A transaction must see its own uncommitted changes.
3. Aborted transactions are invisible — createdby in self.aborted short-circuits to False (lines 83-84).
4. Deletion visibility mirrors creation visibility — lines 98-112 apply the same committed/active/ordering checks to deleted_by. If the deleting transaction isn't yet visible, the version still appears alive.
The activeatstart set (captured at begin_transaction, lines 72-74) is DDIA's snapshot descriptor — it records which transactions were concurrent, so the visibility check can exclude their writes even after they commit.
read() (lines 118-127) iterates through all versions of a key and returns the last visible one. Because visibility is determined entirely by the transaction's starttimestamp and activeatstart snapshot, the result never changes regardless of what other transactions do concurrently. The test at line 22 (testexampleusage) demonstrates this directly: tx2 reads accountA as 1000, then tx3 commits a write changing it to 900, and tx2 *still* reads 1000.
Snapshot isolation doesn't prevent all anomalies — it specifically targets read consistency while detecting write-write conflicts at commit time. The commit() method (lines 168-187) implements first-committer-wins: if another transaction wrote to the same key and committed during our lifetime (was in activeatstart or started after us), we abort. This is tested in test4writewriteconflict (test file lines 68-79).
The ssidatabase.py builds on the same MVCC foundation but adds read-write conflict detection for write skew — the anomaly snapshot isolation alone cannot prevent. It uses visiblevalue (line 59) with timestamp-based version lookup instead of the activeatstart set approach, and adds predicate locks (predicatelocks, line 14) and dependency tracking (dependency_graph, line 47) to detect when concurrent transactions read-then-write in ways that violate serializability.
DDIA notes that keeping old versions forever is impractical. The garbagecollect method (referenced in test9gcremovesunreachable, test file line 147) reclaims versions that no active transaction can see — but test10gcpreserves_active (line 161) confirms it preserves versions still needed by long-running snapshots. This is the operational tension DDIA highlights: immutable snapshots are elegant but require background cleanup.