Multiple versions allow non-blocking concurrent access
Multi-Version Concurrency Control (MVCC) tags each row with a version number (transaction ID). When a transaction reads, it sees the version visible at its snapshot time. When writing, a new version is inserted instead of modifying in-place. Readers never block writers because they read old versions; writers never block readers because new writes are separate versions.
This solves the classic problem of blocking locks in transactional systems. Instead of lock contention, concurrent transactions read and write non-overlapping versions. Reads are fast; writes create versions that are visible to future transactions but not retroactively to past ones, providing snapshot isolation.
Garbage collection and phantom row cleanup
As transactions commit and become old, their versions become invisible to all new transactions. These old versions accumulate and must be garbage collected. Databases track the oldest active transaction; any version older than that can be deleted. Aggressive garbage collection keeps disk usage bounded.
A drawback: long-running transactions pin old versions in memory, preventing cleanup and causing bloat. PostgreSQL's autovacuum manages cleanup; if a transaction holds a snapshot for hours, autovacuum stalls and the database fills. In practice, MVCC is essential for OLTP (where short, concurrent transactions are normal) and problematic for OLAP (where long analytical queries block cleanup). Understanding transaction lifecycle is critical for database performance tuning.