Two-Phase Locking (2PL): Protocol, Phases, and a Worked Example

Two-Phase Locking (2PL): Protocol, Phases, and a Worked Example

Verified Sources
Sep 24, 2026

Two-Phase Locking {keywordkeywordkeywordkeywordkeywordkeywordkeyword.

Core idea: Each transaction follows a strict workflow:

  1. Growing phase: acquire locks (read/write locks) as needed; no lock is released.
  2. Shrinking phase: release locks; no new locks are acquired.

This structure prevents a transaction from “first reading/writing safely, then later changing its mind” by acquiring additional locks after it has started releasing, which is a key reason 2PL yields correct ordering. The protocol is widely used because it is simple to enforce and guarantees schedules are conflict-serializable for standard (non-upgrade) 2PL variants.

Two-Phase Locking (2PL) Explained

Why S-locks and X-locks matter

  • A transaction must hold an S-lock before performing a read.
  • A transaction must hold an X-lock before performing a write.
  • Compatibility: multiple S-locks on the same item can coexist, but any X-lock conflicts with both S- and X-locks from other transactions.

[CalloutBlock] type: "tip" title: "Pro Tip" content: "When working examples, write each transaction’s lock actions (S/X + acquire/release) next to each read/write. The moment a transaction releases its first lock, it must stop acquiring any new locks."

Applying 2PL to a simple schedule (worked example)

  1. 1
    Step 1

    Let T1 and T2 operate on data items X and Y. Use the standard lock rule: reads require S-locks; writes require X-locks.

  2. 2
    Step 2

    Assume T1 does: r1(X); w1(Y). Under 2PL it must acquire S-lock on X before r1(X), and acquire X-lock on Y before w1(Y).

  3. 3
    Step 3

    Assume T2 does: r2(Y); w2(X). It must acquire S-lock on Y before r2(Y), and acquire X-lock on X before w2(X).

  4. 4
    Step 4

    A valid schedule is: T1 acquires S(X), T2 acquires S(Y), then each tries to write the other’s item, causing waiting until the conflicting lock is released—while each transaction respects growing-then-shrinking.

  5. 5
    Step 5

    Once T1 releases its first lock, it enters shrinking and cannot acquire more locks. Similarly for T2.

  6. 6
    Step 6

    Verify that the resulting order of conflicting read/write operations corresponds to some serial execution (e.g., T1 then T2 or T2 then T1).

Concrete example schedule (with waits)

Consider two transactions:

  • T1: r1(X)r_1(X); w1(Y)w_1(Y)
  • T2: r2(Y)r_2(Y); w2(X)w_2(X)

Assume the following interleaving (a 2PL-style schedule):

TimeTransactionAction
1T1Acquire S-lock on XX
2T1r1(X)r_1(X)
3T2Acquire S-lock on YY
4T2r2(Y)r_2(Y)
5T1Request X-lock on YY (conflicts with T2’s S-lock) → wait
6T2Request X-lock on XX (conflicts with T1’s S-lock) → wait

This particular interleaving can lead to deadlock (both waiting for the other to release). The important point for 2PL explanation is how the protocol constrains lock behavior:

  • Both T1 and T2 have acquired locks but none has released yet, so both are still in the growing phase.
  • If a transaction were to release a lock to resolve waiting, it would enter the shrinking phase and must stop acquiring additional locks afterward.

To make the example fully “progressive,” consider an alternative schedule that avoids deadlock by releasing before attempting a conflicting write:

Deadlock-free 2PL schedule variant

TimeTransactionAction
1T1Acquire S-lock on XX
2T1r1(X)r_1(X)
3T1Release S-lock on XX (T1 now in shrinking phase)
4T2Acquire S-lock on YY
5T2r2(Y)r_2(Y)
6T2Acquire X-lock on XX (if free)
7T2w2(X)w_2(X)
8T2Acquire X-lock on YY (if no longer held by T1; otherwise wait)
9T2w2(Y)w_2(Y)
10T2Release locks; commit
11T1(No new lock acquisitions allowed after step 3, so T1 cannot attempt w1(Y)w_1(Y) if it would require a new X-lock held later)

What this shows: once T1 releases its first lock, 2PL forbids further lock acquisitions; therefore, if T1 still needs an X-lock on YY for w1(Y)w_1(Y), it must have acquired it earlier (during growing). That’s precisely the “two-phase” constraint.

A cleaner didactic example (shows both phases clearly)

Let the transactions be:

  • T1: r1(X)r_1(X); r1(Y)r_1(Y); w1(X)w_1(X)
  • T2: w2(Y)w_2(Y); r2(X)r_2(X)

A 2PL-compliant schedule:

TimeTransactionAction
1T1Acquire S-lock on XX; r1(X)r_1(X)
2T1Acquire S-lock on YY; r1(Y)r_1(Y)
3T1Acquire X-lock on XX (upgrade-like behavior or X-lock initially; assume allowed by the chosen 2PL variant) ; w1(X)w_1(X)
4T1Release locks on XX and YY (shrinking phase)
5T2Acquire X-lock on YY; w2(Y)w_2(Y)
6T2Acquire S-lock on XX; r2(X)r_2(X)
7T2Release locks; commit

Because T1 releases and stops acquiring before T2 begins conflicting work, the conflicts line up with a serial order: T1 then T2.

[CalloutBlock] type: "warning" title: "Warning" content: "If you release a lock too early in 2PL, you may be unable to perform later reads/writes that require additional locks—because acquiring after releasing is prohibited by the protocol."

2PL lifecycle (for one transaction)

Acquire locks

Phase 1: Growing

Acquire S/X locks for every data item you will access."

First release

Growing ends

The first time you release any lock, you switch to shrinking."

Release locks only

Phase 2: Shrinking

You may release remaining locks but must not acquire new ones."

Common exam pitfalls

Lock actions across phases (per item)

Illustrative: acquiring stops once releasing begins.

2PL Quick Checks

1 / 4
Question · Term

Growing phase rule

Click to reveal
Answer · Definition

You may acquire S/X locks, but you may not release any lock.

Knowledge Check

Question 1 of 4
Q1Single choice

In two-phase locking, once a transaction releases any lock, it is no longer allowed to...