Two-Phase Locking (2PL)
Summary: A pessimistic concurrency control mechanism that provides serializability by requiring writers to block readers and vice versa.
Sources: chapter7
Last updated: 2026-04-17
Two-phase locking (2PL) is a much stronger requirement than row-level locking used in read committed isolation. In 2PL, readers can block other writers, and writers can block other readers (source: chapter7).
Implementation
The blocking is implemented by having a lock on each object in the database. The lock can either be in shared mode or in exclusive mode:
- If a transaction wants to read an object, it must first acquire the lock in shared mode.
- If a transaction wants to write to an object, it must first acquire the lock in exclusive mode.
- If a transaction first reads and then writes an object, it may upgrade its shared lock to an exclusive lock.
- After a transaction has acquired the lock, it must continue to hold the lock until the end of the transaction (commit or abort).
Performance
The big downside of 2PL is its performance: transaction throughput and response times are significantly worse than under weak isolation levels. This is partly due to the overhead of acquiring and releasing locks, but more importantly due to reduced concurrency (source: chapter7).
Predicate and Index-Range Locks
To prevent phantoms (which cause write-skew), 2PL systems often use predicate locks (locking all objects that match a search condition) or index-range locks (a simplified approximation of predicate locks that locks a range of the index) (source: chapter7).