MVCC is a concurrency control mechanism where the database keeps multiple versions of a row, allowing readers and writers to proceed without blocking each other.
Why MVCC exists (one line)
To avoid read locks blocking writes (and vice versa) while preserving transactional isolation.
How MVCC works (PostgreSQL intuition)
- UPDATE / DELETE does not overwrite a row
- A new version is created
- Old versions remain visible to older transactions
- Visibility is decided by a transaction snapshot
So:
- Reader sees a consistent snapshot
- Writer creates a new row version
No read locks.
Simple example
T1: SELECT balance FROM accounts; → sees version V1
T2: UPDATE accounts SET balance=90; → creates version V2
T1: still sees V1
T3: sees V2
What MVCC gives you
✅ Readers don’t block writers
✅ Writers don’t block readers
✅ High concurrency (OLTP-friendly)
✅ Consistent reads inside a transaction
The cost of MVCC (important!)
❌ Dead tuples accumulate
❌ Requires VACUUM / AutoVacuum
❌ Long-running transactions prevent cleanup
❌ Storage bloat if mismanaged
This is why autovacuum is critical.
MVCC & isolation levels (Postgres)
READ COMMITTED→ snapshot per statementREPEATABLE READ→ snapshot per transactionSERIALIZABLE→ MVCC + conflict detection
Interview-ready one-liner
MVCC allows multiple versions of rows so readers and writers don’t block each other, using transaction snapshots to decide which version is visible.