0
0
PostgresqlHow-ToBeginner · 4 min read

How MVCC Works in PostgreSQL: Explained Simply

PostgreSQL uses MVCC (Multi-Version Concurrency Control) to allow multiple transactions to access the database concurrently without locking conflicts. It keeps multiple versions of rows so readers see a consistent snapshot while writers create new versions, ensuring high performance and data integrity.
📐

Syntax

MVCC in PostgreSQL is not a command but a built-in mechanism that works automatically with standard SQL commands like SELECT, INSERT, UPDATE, and DELETE. It relies on transaction snapshots and row versioning.

  • BEGIN: starts a transaction snapshot.
  • COMMIT: makes changes visible to others.
  • ROLLBACK: discards changes.
  • Row versions are stored with xmin and xmax system columns to track visibility.
sql
BEGIN;
-- Your SQL commands here
COMMIT;
💻

Example

This example shows how two transactions can read and update the same row without blocking each other using MVCC.

sql
-- Transaction 1
BEGIN;
SELECT * FROM accounts WHERE id = 1;
-- Reads current version

-- Transaction 2 (runs concurrently)
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
COMMIT;

-- Transaction 1 continues
SELECT * FROM accounts WHERE id = 1;
COMMIT;
Output
Transaction 1 first SELECT returns balance before update. Transaction 2 updates balance and commits. Transaction 1 second SELECT still sees old balance due to snapshot isolation. After COMMIT, new transactions see updated balance.
⚠️

Common Pitfalls

Some common mistakes when working with MVCC in PostgreSQL include:

  • Expecting UPDATE to block SELECT queries — readers never block writers and vice versa.
  • Not understanding that long-running transactions can cause table bloat because old row versions are kept until all transactions finish.
  • Ignoring vacuuming, which cleans up old row versions and prevents disk space issues.
sql
/* Wrong: expecting SELECT to block UPDATE */
BEGIN;
SELECT * FROM accounts WHERE id = 1;
-- This does NOT block concurrent UPDATE

/* Right: understand MVCC allows concurrent reads and writes */
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
COMMIT;
📊

Quick Reference

ConceptDescription
MVCCMulti-Version Concurrency Control, manages concurrent access by keeping multiple row versions.
xminTransaction ID that created the row version.
xmaxTransaction ID that deleted or superseded the row version.
SnapshotA view of the database at a point in time for consistent reads.
VacuumProcess that removes obsolete row versions to free space.

Key Takeaways

PostgreSQL MVCC allows concurrent reads and writes without locking conflicts.
Each transaction sees a consistent snapshot of data as of its start time.
Old row versions remain until no transactions need them, requiring vacuuming.
Readers never block writers and writers never block readers in MVCC.
Long-running transactions can cause table bloat by delaying cleanup.