DBMS slides 📂 Transactions and Concurrency · 5 of 5 36 min read

Concurrency Control in DBMS: Locking and Two-Phase Locking (2PL)

Lock-based concurrency control keeps parallel transactions isolated. This tutorial covers shared and exclusive locks, the compatibility matrix, and Two-Phase Locking — the growing/shrinking "hill" that guarantees conflict serializability. It walks through the four 2PL variants (Basic, Strict, Rigorous, Conservative), deadlocks and the wait-for graph, and Wait-Die/Wound-Wait prevention, with two solved numericals.

Locking & Two-Phase Locking

How a DBMS keeps concurrent transactions from stepping on each other — shared & exclusive locks, the 2PL "hill," its four variants, and the deadlocks locking can create.
Shared & Exclusive Growing / Shrinking 2PL Variants Deadlock

Press Next → or use ← → arrow keys

Section 01

The Story — The Library Reserve Room

Many may read; only one may annotate
A rare manuscript sits in a library vault. Many scholars can read it at once — no conflict. But the moment someone wants to annotate (write), they must lock the vault exclusively; everyone else waits. That's exactly how a database behaves: shared locks coexist, an exclusive lock demands sole access — and when the lock is released is governed by Two-Phase Locking.
🎛️
What Concurrency Control Is

The DBMS subsystem that keeps parallel transactions from violating isolation. The most widely used mechanism is lock-based concurrency control.

Section 02

Two Lock Types & When They Clash

👀
Shared lock — S / read lock
Lets a transaction read an item. Many transactions may hold an S-lock on the same item at once. lock-S(X).
✍️
Exclusive lock — X / write lock
Lets a transaction read AND write. Only one transaction may hold it — no sharing. lock-X(X).
Lock compatibility matrix
Tj requests ↓ · Ti holds →S-lockX-lock
S-lock✓ GRANTED✗ WAIT
X-lock✗ WAIT✗ WAIT
🧠
The Memory Hook

"Readers share, writers are exclusive." Only S–S is compatible; every other pair forces the requester to wait.

Section 03

Why "Unlock When Done" Isn't Enough

The naive rule — lock before access, unlock when finished — breaks if you release too early.

tT1T2
t1lock-X(A)
t2R(A)=100
t3W(A)=150
t4unlock(A)
t5lock-X(A)
t6R(A)=150
t7W(A)=200
t9ABORT!
💥
Cascading Abort

T1 unlocked at t4 before committing. T2 read the uncommitted 150 and built on it. When T1 aborts, A must revert to 100 — so T2 must abort too. Early release broke isolation.

🛠️
The Fix

A disciplined lock lifecycle — Two-Phase Locking — that forbids acquiring any new lock once you've started releasing.

Section 04

Two-Phase Locking — The Hill

locks held time → Lock point GROWING — only acquire SHRINKING — only release
⛰️
Two Phases, One Peak

Growing: acquire locks, release none — the set only grows. Lock point: the instant the last lock is acquired (the peak). Shrinking: release locks, acquire none — the set only shrinks. Once you release any lock, you may never acquire another.

Section 04 · Theorem

Why 2PL Works

📐
The Guarantee

If every transaction in a schedule follows 2PL, the schedule is conflict serializable. And the equivalent serial order is simply the order of the transactions' lock points.

🔗
Serializability for free
No precedence graph needed at runtime — the protocol constructs only serializable schedules by design.
🏔️
Lock points = serial order
Sort the transactions by when they hit their peak, and that's an equivalent serial schedule.
⚠️
But Basic 2PL Isn't Perfect

It guarantees serializability — but still allows cascading aborts and deadlocks. That's why stricter variants exist.

Numerical 1

Does This Transaction Follow 2PL?

✅
Sequence A — follows 2PL
lock-S(A) · lock-X(B) · lock-S(C) · unlock(A) · unlock(B) · unlock(C)

Growing: the three locks. Lock point: after lock-S(C). Shrinking: the three unlocks. No lock acquired after the first unlock.
❌
Sequence B — violates 2PL
lock-S(A) · lock-X(B) · unlock(A) · lock-S(C) · unlock(B) · unlock(C)

unlock(A) starts shrinking — but then lock-S(C) acquires a new lock. A lock was taken after a release.
🔍
The One-Line Test

Scan left to right: the moment you see the first unlock, there must be no lock after it. One late lock breaks 2PL.

Section 05

Four Variants of 2PL

🔓
Basic 2PL
Release locks as soon as the growing phase ends. Serializable — but risks cascading aborts & deadlock.
🔒
Strict 2PL
Hold all X-locks until commit; S-locks may release earlier. Adds cascadeless.
🛡️
Rigorous 2PL
Hold all locks until commit. Shrinking collapses to one instant → strict schedules.
🏗️
Conservative 2PL
Acquire all locks before starting. The only deadlock-free variant — but limits concurrency.
VariantConflict serializableCascadelessStrictDeadlock-free
Basic 2PL✓✗✗✗
Strict 2PL✓✓✗✗
Rigorous 2PL✓✓✓✗
Conservative 2PL✓✓✓✓
Section 05 · Visual

When Does Each Variant Release Locks?

BEGIN COMMIT Basic 2PLreleases early, throughout Strict 2PLX to commit RigorousALL to commit Conservativeall locked at BEGIN → commit
📏
Reading the Timeline

The bar shows how long locks are held. Basic releases as soon as it can; Strict holds X-locks to commit; Rigorous holds everything to commit; Conservative grabs everything up front. Longer bars = safer recovery, less concurrency.

Numerical 2

Strict 2PL in Action

T1 transfers ₹500 from A to B; T2 reads A + B — under Strict 2PL.

tT1T2Locks held
t1lock-X(A)T1: X(A)
t2–3R(A)=1000 · W(A)=500
t4lock-X(B)T1: X(A), X(B)
t5lock-S(A) — WAITT2 blocked by T1's X(A)
t7–8R(B)=2000 · W(B)=2500waiting…
t9Commit → unlock allT1 releases X(A), X(B)
t10–11lock-S(A) GRANTED · R(A)=500T2: S(A)
t12–13lock-S(B) · R(B)=2500T2: S(A), S(B)
t14Commit → unlock allclean
✅
Why It's Correct

T1 holds its X-locks until commit (t9), so T2's read at t5 must wait. T2 then reads only committed values: 500 + 2500 = 3000, the original total. No cascading abort, no lost update.

Section 06

The Dark Side — Deadlock

Two cars meet on a one-lane bridge from opposite ends. Neither will back up; neither can pass. Two transactions, each holding a lock the other needs — both wait forever.
tT1T2
t1lock-X(A)
t2lock-X(B)
t3lock-X(B) — WAIT
t4lock-X(A) — WAIT
T1 T2 waits for B waits for A CYCLE
🔁
Wait-For Graph

A cycle in the wait-for graph means deadlock. The DBMS breaks it by aborting a victim (the cheapest transaction).

Section 06 · Handling

Four Ways to Handle Deadlock

🔎
Detect
Periodically check the wait-for graph for cycles; abort the cheapest victim. Used by PostgreSQL, MySQL/InnoDB.
🚧
Prevent
Wait-Die / Wound-Wait use timestamps to decide who waits and who aborts — no deadlock ever forms.
⏱️
Timeout
Wait longer than a threshold → assume deadlock and abort. Simple but imprecise.
🏗️
Avoid
Conservative 2PL locks everything up front, so circular waits are impossible.
⏳
Wait-Die vs Wound-Wait — older = higher priority

Wait-Die: older requests younger's lock → older waits; younger requests older's → younger dies. Wound-Wait: older requests younger's → older wounds (kills younger); younger requests older's → younger waits. In both, the younger aborts and retries with its original timestamp.

Section 10

Academic vs Industry Lenses

🎓
Academic lens
Prove 2PL ⇒ conflict serializable. Exam skills: read lock sequences, spot 2PL violations, draw deadlock graphs. Know the variant hierarchy: Basic ⊂ Strict ⊂ Rigorous ⊂ Conservative.
🏭
Industry lens
Most engines use Strict or Rigorous 2PL. Deadlocks detected via wait-for graph; victim = least work done. Granularity: row-level (InnoDB) for more concurrency. Advice: keep transactions short; lock items in a consistent order.
🔀
Modern Reality — Locks + MVCC Together

PostgreSQL, MySQL/InnoDB, SQL Server combine both: reads use MVCC snapshots (no read locks, so readers never block writers), while writes take row-level X-locks held until commit — i.e. Strict 2PL.

Section 11

Rapid-Fire Concept Check

QuestionAnswer
The two lock typesShared (S) and Exclusive (X)
The only compatible pairS–S (all others block)
What 2PL guaranteesConflict serializability
The two phasesGrowing (acquire) then Shrinking (release)
The lock pointInstant the last lock is acquired
What Strict 2PL addsHold X-locks to commit → cascadeless
What Rigorous 2PL addsHold ALL locks to commit → strict
Which variant is deadlock-free?Conservative 2PL
Cycle in wait-for graph meansDeadlock
Most common engine approach todayStrict 2PL + MVCC hybrid
Section 12

Golden Rules of Locking & 2PL

🏆 NON-NEGOTIABLE PRINCIPLES
1
Exactly one compatible pair: S–S. Every other combination (S-X, X-S, X-X) forces a wait.
2
Once you release any lock, never acquire another. The lock-count graph is always a single-peaked hill.
3
2PL ⇒ conflict serializable, and the equivalent serial order is the order of lock points.
4
Basic 2PL doesn't stop cascading aborts or deadlock. Strict 2PL (hold X-locks to commit) eliminates cascading aborts.
5
A cycle in the wait-for graph = deadlock. Detect & abort a victim, or prevent with Wait-Die / Wound-Wait.
6
In real systems, keep transactions short and access items in a consistent global order to cut deadlocks and waits.
FINAL

Grow, Peak, Shrink

S · XTwo lock types
2Phases, one peak
42PL variants
Cycle= deadlock
🎯
The Whole Idea

Locks enforce isolation: readers share, writers are exclusive. Two-Phase Locking disciplines when they're released — grow, hit the lock point, then only shrink — which guarantees conflict serializability. Strict and Rigorous variants hold write (or all) locks to commit for clean recovery; the price is deadlocks, which the DBMS detects and breaks by aborting a victim.

🧠
One Sentence to Remember

Once a transaction gives up its first lock, it can never take another — that single rule is what makes 2PL serializable. Real engines use Strict 2PL for writes and MVCC for reads.

🔒 End of tutorial · Press ← to review, or click Restart

You have completed Transactions and Concurrency. View all sections →