Introduction

Locking discovers a serialization order at run time, through the order of lock points. Timestamp ordering fixes the order in advance: every transaction gets a unique timestamp when it starts, and the system allows a conflicting operation only if it respects timestamp order. A transaction that would violate the order is rolled back and restarted with a new timestamp. No transaction ever waits, so there are no deadlocks.

Timestamps are also used with locking, to decide who waits and who is rolled back in the wait-die and wound-wait deadlock-prevention schemes. The tasks are to trace the timestamp-ordering rules on a schedule, to apply the Thomas write rule, and to say what happens under wait-die and wound-wait.

Prerequisites

Core concepts

Timestamps. TS(Ti)TS(T_i) is assigned when TiT_i starts, from a system clock or a counter; if TiT_i starts before TjT_j, then TS(Ti)<TS(Tj)TS(T_i) < TS(T_j). A smaller timestamp means an older transaction.

Item timestamps. For each item XX:

  • W-TS(X)\text{W-TS}(X): the largest timestamp of any transaction that has successfully written XX;
  • R-TS(X)\text{R-TS}(X): the largest timestamp of any transaction that has successfully read XX.

Both start at 0.

Basic timestamp-ordering (TO) protocol.

  • TiT_i issues R(X)R(X):
    • if TS(Ti)<W-TS(X)TS(T_i) < \text{W-TS}(X): TiT_i would read a value written by a younger transaction; reject and roll back TiT_i;
    • otherwise execute, and set R-TS(X)=max⁡(R-TS(X),TS(Ti))\text{R-TS}(X) = \max(\text{R-TS}(X), TS(T_i)).
  • TiT_i issues W(X)W(X):
    • if TS(Ti)<R-TS(X)TS(T_i) < \text{R-TS}(X): a younger transaction has already read the old value; reject and roll back TiT_i;
    • if TS(Ti)<W-TS(X)TS(T_i) < \text{W-TS}(X): TiT_i would overwrite a younger write; reject and roll back TiT_i;
    • otherwise execute, and set W-TS(X)=TS(Ti)\text{W-TS}(X) = TS(T_i).

A rolled-back transaction restarts with a new, larger timestamp.

Thomas write rule. Change only the second write test: if TS(Ti)<W-TS(X)TS(T_i) < \text{W-TS}(X) (and the read test passed), ignore the write instead of rolling back. The write is obsolete: a younger transaction has already written XX, and nobody between them read the value TiT_i would write.

Deadlock prevention with timestamps (used with locking). When TiT_i requests an item held by TjT_j:

  • Wait-die (non-preemptive): if TiT_i is older, it waits; if younger, it dies (rolls back).
  • Wound-wait (preemptive): if TiT_i is older, it wounds TjT_j (TjT_j rolls back); if younger, it waits.

In wait-die only older transactions wait for younger ones; in wound-wait only younger transactions wait for older ones. Waits therefore always point in one direction of age, so no cycle can form. A rolled-back transaction keeps its original timestamp, so it eventually becomes the oldest and cannot starve.

Two by two table for a requester T_i and a holder T_j: under wait-die an older requester waits and a younger requester dies; under wound-wait an older requester wounds the holder and a younger requester waits
Figure 1. Wait-die and wound-wait: what happens when TiT_i requests an item held by TjT_j, by relative age.

How it works: tracing basic TO

For each operation in order: look up the item's R-TS\text{R-TS} and W-TS\text{W-TS}, apply the tests, and either update the timestamps or roll back the transaction. A table with one row per operation and columns for the test, the outcome and the new timestamps keeps the trace honest.

Mathematical explanation

Why TO gives conflict serializability. Every executed pair of conflicting operations is ordered by timestamp: a read is allowed only after writes from older transactions, a write only after reads and writes from older transactions. So every edge Ti→TjT_i \to T_j of the precedence graph has TS(Ti)<TS(Tj)TS(T_i) < TS(T_j), the graph is acyclic, and the schedule is conflict equivalent to the serial schedule in timestamp order.

What the Thomas write rule guarantees. The rule in effect deletes each obsolete write from the transaction that issued it. The operations that are actually executed pass every basic TO test, so they are conflict equivalent to the serial schedule in timestamp order. Read with the ignored writes left in place, the submitted schedule need not be conflict serializable: Example 4 is accepted, is not conflict serializable, and is view serializable. Do not stretch this to "every schedule the rule accepts is view serializable as written": a transaction that reads an item after an ignored write by another transaction can make the as-written schedule fail the view test, although the executed schedule is still serializable. A read after its own obsolete ignored write instead fails the timestamp read check and aborts.

Deadlock and starvation. Basic TO never makes a transaction wait, so it is deadlock-free. A long transaction can, however, be rolled back again and again (each restart gets a new, larger timestamp, which can be invalidated again), so starvation is possible.

Recoverability. Basic TO says nothing about commits, so it can produce schedules that are not recoverable or not cascadeless. Strict TO delays a read or write of XX until the other transaction that last wrote XX has committed or aborted.

TO and 2PL accept different schedules. Neither set contains the other: TO forces the timestamp order, 2PL forces the lock-point order and the no-acquire-after-release rule (Examples 5 and 6).

Worked examples

Example 1: a full trace. TS(T1)=10TS(T_1) = 10, TS(T2)=20TS(T_2) = 20, TS(T3)=30TS(T_3) = 30; S=R1(A) R2(B) W2(A) R3(B) W3(A) W1(B)S = R_1(A)\, R_2(B)\, W_2(A)\, R_3(B)\, W_3(A)\, W_1(B).

OperationTestOutcomeItem timestamps after
R1(A)R_1(A)10≥W-TS(A)=010 \ge \text{W-TS}(A) = 0executeR-TS(A)=10\text{R-TS}(A) = 10
R2(B)R_2(B)20≥020 \ge 0executeR-TS(B)=20\text{R-TS}(B) = 20
W2(A)W_2(A)20≥R-TS(A)=1020 \ge \text{R-TS}(A) = 10, 20≥W-TS(A)=020 \ge \text{W-TS}(A) = 0executeW-TS(A)=20\text{W-TS}(A) = 20
R3(B)R_3(B)30≥W-TS(B)=030 \ge \text{W-TS}(B) = 0executeR-TS(B)=30\text{R-TS}(B) = 30
W3(A)W_3(A)30≥1030 \ge 10, 30≥2030 \ge 20executeW-TS(A)=30\text{W-TS}(A) = 30
W1(B)W_1(B)10<R-TS(B)=3010 < \text{R-TS}(B) = 30roll back T1T_1unchanged

T1T_1 is rolled back at its last operation: younger T2T_2 and T3T_3 have already read the old BB.

Example 2: a read rejected. TS(T1)=5TS(T_1) = 5, TS(T2)=10TS(T_2) = 10, S=W2(A) R1(A)S = W_2(A)\, R_1(A). After W2(A)W_2(A), W-TS(A)=10\text{W-TS}(A) = 10; R1(A)R_1(A) has 5<105 < 10, so T1T_1 is rolled back: it would read a value from its future.

Example 3: the read test also beats the Thomas rule. TS(T1)=5TS(T_1) = 5, TS(T2)=10TS(T_2) = 10, S=R1(A) R2(A) W2(A) W1(A)S = R_1(A)\, R_2(A)\, W_2(A)\, W_1(A). At W1(A)W_1(A), R-TS(A)=10>5\text{R-TS}(A) = 10 > 5, so T1T_1 is rolled back under both basic TO and the Thomas write rule: the Thomas rule relaxes only the write-write test.

Example 4: the Thomas write rule. TS(T1)=1TS(T_1) = 1, TS(T2)=2TS(T_2) = 2, TS(T3)=3TS(T_3) = 3; S=R1(A) W2(A) W1(A) W3(A)S = R_1(A)\, W_2(A)\, W_1(A)\, W_3(A), the view-serializable but not conflict-serializable schedule from Schedules and Serializability. At W1(A)W_1(A): R-TS(A)=1≤1\text{R-TS}(A) = 1 \le 1 passes, but W-TS(A)=2>1\text{W-TS}(A) = 2 > 1. Basic TO rolls T1T_1 back; the Thomas rule ignores W1(A)W_1(A), and the schedule completes, view equivalent to T1T2T3T_1 T_2 T_3.

Example 5: TO accepts a schedule 2PL cannot produce. S=R1(A) W2(A) R3(B) W1(B)S = R_1(A)\, W_2(A)\, R_3(B)\, W_1(B) is not producible by 2PL (lock note, Example 3). With TS(T3)<TS(T1)<TS(T2)TS(T_3) < TS(T_1) < TS(T_2) every test passes, and SS runs under basic TO, equivalent to T3T1T2T_3 T_1 T_2.

Example 6: 2PL accepts a schedule TO rejects. S=R2(A) W1(A)S = R_2(A)\, W_1(A) with TS(T1)<TS(T2)TS(T_1) < TS(T_2). 2PL produces it (T2T_2 releases its S lock, then T1T_1 takes X), serial order T2T1T_2 T_1. Basic TO rolls back T1T_1 at W1(A)W_1(A), because TS(T1)<R-TS(A)=TS(T2)TS(T_1) < \text{R-TS}(A) = TS(T_2).

Example 7: wait-die and wound-wait (Figure 1). TS(T1)=5TS(T_1) = 5 (older), TS(T2)=10TS(T_2) = 10.

  • T1T_1 requests an item held by T2T_2: wait-die, T1T_1 waits; wound-wait, T2T_2 is rolled back and T1T_1 gets the item.
  • T2T_2 requests an item held by T1T_1: wait-die, T2T_2 dies (rolls back, restarts later with timestamp 10); wound-wait, T2T_2 waits.

With the deadlock of the lock note (T1T_1 holds AA and wants BB, T2T_2 holds BB and wants AA), wait-die lets T1T_1 wait and kills T2T_2 when it requests AA; wound-wait rolls back T2T_2 as soon as T1T_1 requests BB. Either way no cycle forms.

Example 8: the Thomas rule can change who is rolled back. TS(T1)=10TS(T_1) = 10, TS(T2)=20TS(T_2) = 20, TS(T3)=30TS(T_3) = 30; S=R1(A) W3(A) W2(A) R2(B) W1(B) W3(B)S = R_1(A)\, W_3(A)\, W_2(A)\, R_2(B)\, W_1(B)\, W_3(B). Convention: a rolled-back transaction's remaining operations are dropped from the trace, and it is not restarted within it.

OperationBasic TOThomas write rule
R1(A)R_1(A)execute; R-TS(A)=10\text{R-TS}(A) = 10execute; R-TS(A)=10\text{R-TS}(A) = 10
W3(A)W_3(A)execute; W-TS(A)=30\text{W-TS}(A) = 30execute; W-TS(A)=30\text{W-TS}(A) = 30
W2(A)W_2(A)20<W-TS(A)=3020 < \text{W-TS}(A) = 30: roll back T2T_220≥R-TS(A)=1020 \ge \text{R-TS}(A) = 10 but 20<3020 < 30: ignore
R2(B)R_2(B)dropped (T2T_2 rolled back)execute; R-TS(B)=20\text{R-TS}(B) = 20
W1(B)W_1(B)10≥R-TS(B)=010 \ge \text{R-TS}(B) = 0, 10≥W-TS(B)=010 \ge \text{W-TS}(B) = 0: execute; W-TS(B)=10\text{W-TS}(B) = 1010<R-TS(B)=2010 < \text{R-TS}(B) = 20: roll back T1T_1
W3(B)W_3(B)execute; W-TS(B)=30\text{W-TS}(B) = 30execute; W-TS(B)=30\text{W-TS}(B) = 30

Basic TO rolls back T2T_2; the Thomas rule saves T2T_2 by ignoring its obsolete write, but T2T_2 then reads BB, and that read is what later forces T1T_1 back. Both runs lose exactly one transaction. The Thomas rule never rejects a write that basic TO accepts, but it does not promise fewer rollbacks overall, because the transactions it saves keep running and change the timestamps.

Important properties and observations

  • Basic TO: conflict serializable in timestamp order, deadlock-free, starvation possible, not necessarily recoverable.
  • Read rule: reject if a younger transaction already wrote the item.
  • Write rule: reject if a younger transaction already read or wrote the item.
  • Thomas write rule: ignore an obsolete write instead of rejecting; the executed operations are serializable in timestamp order, and some accepted schedules (Example 4) are view serializable but not conflict serializable.
  • Restarted transactions get new timestamps in TO but keep old ones in wait-die and wound-wait.
  • Wait-die: older waits, younger dies. Wound-wait: older wounds, younger waits.
  • TO and 2PL each accept schedules the other rejects.

Common misconceptions.

  • "The Thomas write rule ignores any late write." Only when the read test passes; a younger reader still forces a rollback (Example 3).
  • "In wait-die the younger transaction waits." The older one waits; the younger dies.
  • "TO avoids starvation because it avoids deadlock." Repeated restarts can starve a transaction.
  • "A larger timestamp means older." Larger means younger.

GATE examination perspective

  • Trace basic TO. Work on a schedule with given timestamps; find the first rollback.
  • Thomas write rule. Which writes are ignored, and whether the schedule completes.
  • Wait-die versus wound-wait. Who waits and who is rolled back for given timestamps.
  • Properties. Serializability, deadlock freedom, starvation and recoverability of each protocol.
  • Compare. Combine this with 2PL on schedules accepted by one and not the other.

Summary

Sources

  1. A. Silberschatz, H. F. Korth, S. Sudarshan, Database System Concepts, 7th ed., McGraw-Hill, 2019 (2020 copyright), 18.2 Deadlock Handling, 18.5 Timestamp-Based Protocols.
  2. R. Elmasri, S. B. Navathe, Fundamentals of Database Systems, 7th ed., Pearson, 21.1 Two-Phase Locking Techniques for Concurrency Control, 21.2 Concurrency Control Based on Timestamp Ordering.

Next steps