Loading learning content...
Having established what makes schedules correct (serializability), we now tackle how database systems guarantee correctness: lock-based concurrency control.
In interviews, lock analysis problems require you to trace lock acquisition and release, determine if schedules obey locking protocols, predict deadlocks before they occur, and reason about the tradeoffs between different locking strategies.
Locking is the bridge between theory and practice. While serializability tells us whether a schedule is correct, locking protocols tell us how to ensure every schedule a DBMS produces will be correct.
By completing this page, you will be able to: (1) Understand shared and exclusive lock semantics and compatibility; (2) Trace lock acquisition and release through any schedule; (3) Verify Two-Phase Locking (2PL) protocol compliance; (4) Identify the differences between Basic, Strict, and Rigorous 2PL; (5) Recognize lock upgrade/downgrade patterns and conflicts.
A lock is a mechanism that grants a transaction the right to access a data item in a specific mode. Before a transaction can read or write a data item, it must acquire an appropriate lock on that item.
The two fundamental lock types are:
Shared Lock (S-lock): Allows the transaction to READ the data item. Multiple transactions can hold shared locks on the same item simultaneously.
Exclusive Lock (X-lock): Allows the transaction to READ and WRITE the data item. Only one transaction can hold an exclusive lock on an item, and no other transaction can hold any lock on that item.
| Requested \ Held | No Lock | S-Lock | X-Lock |
|---|---|---|---|
| S-Lock | ✓ Grant | ✓ Grant | ✗ Wait |
| X-Lock | ✓ Grant | ✗ Wait | ✗ Wait |
When a transaction requests a lock:
Critical rules:
In many DBMS implementations, a write operation implicitly includes a read (to get the current value for update). Thus, some systems allow direct X-lock acquisition for writes. Interview problems may assume either model—clarify with the interviewer if needed.
Two-Phase Locking (2PL) is the fundamental protocol that guarantees conflict serializability. The protocol divides each transaction's execution into two distinct phases:
Phase 1: Growing Phase (Lock Acquisition)
Phase 2: Shrinking Phase (Lock Release)
The lock point is the moment when the transaction transitions from growing to shrinking—typically when it acquires its last lock.
12345678910111213141516171819
-- Transaction T following 2PL protocol -- GROWING PHASE (acquiring locks)S_lock(A); -- Acquire shared lock on AREAD(A); -- Read A (allowed, have S-lock)X_lock(B); -- Acquire exclusive lock on BREAD(B); -- Read B (allowed, have X-lock)X_lock(C); -- Acquire exclusive lock on CWRITE(B); -- Write B (allowed, have X-lock) -- LOCK POINT (last lock acquired) -- SHRINKING PHASE (releasing locks)WRITE(C); -- Write C (allowed, already have X-lock)unlock(A); -- Release lock on Aunlock(B); -- Release lock on B-- At this point, T cannot acquire any more locks!unlock(C); -- Release lock on CCOMMIT;Theorem: Any schedule of transactions that follow 2PL is conflict serializable.
Proof intuition: The lock point of each transaction represents the moment when it has "captured" all the data items it will ever use. Ordering transactions by their lock points gives a serial schedule that is conflict equivalent to the original.
If T₁'s lock point precedes T₂'s lock point, then:
This ordering property ensures no cycles in the precedence graph.
A transaction violates 2PL if it acquires a lock AFTER releasing any lock. The pattern 'unlock(X) ... lock-S(Y)' or 'unlock(X) ... lock-X(Y)' is always a 2PL violation. Watch for this in interview problems!
Basic 2PL ensures serializability but allows schedules that are not recoverable or cascadeless. To address these issues, stricter variants are used in practice:
Rule: A transaction holds all its exclusive (X) locks until it commits or aborts.
Benefits:
Rule: A transaction holds ALL locks (both S and X) until it commits or aborts.
Benefits:
| Property | Basic 2PL | Strict 2PL | Rigorous 2PL |
|---|---|---|---|
| Serializable | ✓ | ✓ | ✓ |
| Recoverable | Not guaranteed | ✓ | ✓ |
| Cascadeless | Not guaranteed | ✓ | ✓ |
| Strict schedules | Not guaranteed | ✓ | ✓ |
| When S-locks released | Anytime after acquisition | Anytime after acquisition | At commit/abort only |
| When X-locks released | Anytime after acquisition | At commit/abort only | At commit/abort only |
| Concurrency | Highest | Medium | Lowest |
| Common in practice | Rarely | Very common | Occasional |
T₁: X(A) W(A) U(A) S(B) R(B) U(B) C₁
T₂: S(B) R(B) U(B) X(A) W(A) U(A) C₂Analysis:
T₁:
• Acquires X(A), releases U(A), then acquires S(B)
• VIOLATES Basic 2PL (acquires lock after release)
T₂:
• Similar pattern: acquires, releases, acquires
• VIOLATES Basic 2PL
Neither transaction follows any form of 2PL!
This schedule is NOT guaranteed to be serializable.If commits appear at the end and all unlocks happen after the commit (or immediately before), the schedule follows Rigorous 2PL. If only X-locks are held until commit, it's Strict 2PL. This quick pattern match saves time in interviews.
Sometimes a transaction needs to change the mode of an existing lock. This is called lock conversion.
A transaction holding an S-lock on X may need to later write X. Instead of releasing the S-lock and acquiring an X-lock (which would create a gap where another transaction could intervene), the transaction requests an upgrade from S to X.
Upgrade semantics:
A transaction holding an X-lock on X has finished writing but still needs to read. It can downgrade from X to S, allowing other transactions to also hold S-locks.
Downgrade semantics:
| Conversion | Condition for Immediate Grant | 2PL Phase |
|---|---|---|
| S → X (Upgrade) | No other S-lock holders on item | Only during Growing phase |
| X → S (Downgrade) | Always (have exclusive access) | Only during Shrinking phase |
A particularly nasty situation occurs when two transactions each hold S-locks on the same item and both request upgrades:
T₁: S(A) ... upgrade(A) → waiting for T₂ to release S(A)
T₂: S(A) ... upgrade(A) → waiting for T₁ to release S(A)
This is a deadlock! Neither can proceed because each is waiting for the other's S-lock to be released before their upgrade can succeed.
Some systems use update locks (U-locks) to prevent upgrade deadlocks:
This ensures at most one transaction can be "waiting to upgrade," preventing the circular wait.
An upgrade from S to X is acquiring a 'stronger' lock, which counts as acquiring a new lock capability. Therefore, upgrades can ONLY occur during the growing phase of 2PL. Attempting to upgrade after any unlock violates 2PL.
Let's work through a comprehensive lock analysis problem that tests all concepts.
Given the following schedule with locking operations, analyze:
123456789101112131415161718192021
-- Schedule S with three transactions T₁: X(A) R(A) W(A) S(B) R(B) U(A) U(B) C₁T₂: X(B) R(B) W(B) U(B) C₂T₃: S(A) R(A) U(A) C₃ -- Time progression:-- t1: T₁ gets X(A)-- t2: T₁ reads A-- t3: T₁ writes A, T₃ requests S(A) → BLOCKED (T₁ has X(A))-- t4: T₁ gets S(B)-- t5: T₁ reads B, T₂ requests X(B) → BLOCKED (T₁ has S(B))-- t6: T₁ releases A → T₃ UNBLOCKED, gets S(A)-- t7: T₁ releases B → T₂ UNBLOCKED, gets X(B)-- t8: T₃ reads A-- t9: T₁ commits-- t10: T₂ reads B, writes B-- t11: T₂ releases B-- t12: T₂ commits-- t13: T₃ releases A-- t14: T₃ commitsT₁ 2PL Check:
T₂ 2PL Check:
T₃ 2PL Check:
Blocking Analysis:
Serialization Order: Lock points: T₁ first (acquired both locks before T₂ or T₃ acquired theirs) T₂ and T₃ acquired locks only after T₁ released
Equivalent serial order: T₁ → (T₂ or T₃ in either order, they don't conflict)
For complex lock analysis, draw a timeline showing when each transaction holds each lock. This makes blocking situations and lock conflicts visually obvious and helps prevent mistakes.
In real database systems, the question of what to lock is as important as how to lock.
Locks can be acquired at different levels of the data hierarchy:
Fine granularity (row-level):
Coarse granularity (table-level):
| Level | Concurrency | Overhead | Typical Use Case |
|---|---|---|---|
| Database | Minimal | Minimal | DDL operations, backups |
| Table | Low | Low | Bulk loads, schema changes |
| Page | Medium | Medium | Older systems, OLAP |
| Row | High | High | OLTP, modern systems |
Intention locks solve the problem of efficiently checking lock compatibility across granularity levels.
Problem: If T₁ wants to lock table T exclusively, it must check that no row in T is locked. Scanning all rows is expensive!
Solution: Before locking a row, acquire an intention lock on the parent (table). The intention lock signals "some row is locked" without locking the whole table.
Intention Lock Types:
| Requested \ Held | IS | IX | S | SIX | X |
|---|---|---|---|---|---|
| IS | ✓ | ✓ | ✓ | ✓ | ✗ |
| IX | ✓ | ✓ | ✗ | ✗ | ✗ |
| S | ✓ | ✗ | ✓ | ✗ | ✗ |
| SIX | ✓ | ✗ | ✗ | ✗ | ✗ |
| X | ✗ | ✗ | ✗ | ✗ | ✗ |
To lock a node, first acquire appropriate intention locks on all ancestors. For example, to X-lock a row, first IX-lock the table, then X-lock the row. This enables efficient conflict detection at higher levels.
Lock analysis questions in interviews follow predictable patterns. Here's how to recognize and solve each type efficiently.
Pattern: Given a schedule with lock operations, verify if it follows 2PL.
Method:
Example:
T₁: S(A) R(A) X(B) U(A) R(B) W(B) S(C) R(C) U(B) U(C) C₁
↑ ↑
first unlock S(C) after unlock → VIOLATION!
Draw a timeline with lock acquisition as upward arrows and releases as downward arrows. The growing phase should show only upward arrows, then a peak, then only downward arrows. Any upward arrow after a downward arrow is a 2PL violation.
Lock analysis connects abstract serializability theory to practical database implementation. Let's consolidate the essential skills:
What's Next:
With lock analysis mastered, we'll tackle Deadlock Detection—understanding why deadlocks occur, how to detect them through wait-for graphs, and the various strategies for prevention, avoidance, and resolution.
You now have comprehensive knowledge of lock-based concurrency control. You can analyze any schedule for 2PL compliance, identify which variant is being used, predict blocking situations, and understand the trade-offs in lock granularity. This knowledge is directly applicable to real database system design and interview problems.