Loading learning content...
We've examined the individual components of the Basic Timestamp Protocol: RTS and WTS timestamps, read rules, and write rules. Now it's time to see how these pieces combine into a complete, functioning concurrency control mechanism.
Protocol Execution encompasses everything that happens from when a transaction begins until it commits or aborts. This includes timestamp assignment, operation processing, conflict detection, abort handling, and commit processing. Understanding the complete protocol execution enables you to predict system behavior, diagnose concurrency issues, and make informed design decisions.
By the end of this page, you will understand the complete lifecycle of transactions under timestamp ordering, be able to trace complex multi-transaction schedules, analyze serializability guarantees, and understand the protocol's recovery implications. You'll also see how Basic Timestamp Ordering compares to Two-Phase Locking.
Every transaction under the Basic Timestamp Protocol goes through a defined lifecycle. Understanding this lifecycle is fundamental to understanding protocol execution.
Phase 1: Begin Transaction
When a transaction T begins:
Timestamp sources can be:
| Phase | Actions | Possible Outcomes |
|---|---|---|
| Begin | Assign timestamp, enter ACTIVE state | Transaction starts |
| Execute | Process reads/writes per protocol rules | Operations succeed or transaction aborts |
| Abort (if conflict) | Rollback changes, release resources, restart | New transaction with new timestamp |
| Commit | Make changes durable, complete transaction | Transaction ends successfully |
Phase 2: Execute Operations
During execution, each operation (read or write) is processed according to the rules we've studied:
If any operation fails the timestamp checks, the transaction immediately aborts. There's no waiting, no retry-within-transaction.
Phase 3: Abort or Commit
If all operations succeed:
If any operation fails:
Let's formalize the complete Basic Timestamp Protocol, integrating all components:
Transaction Start:
BEGIN_TRANSACTION(T):
TS(T) := GET_TIMESTAMP() // Assign unique, increasing timestamp
state(T) := ACTIVE
Read Operation:
READ(T, X):
IF TS(T) < WTS(X) THEN
ABORT(T)
RETURN FAILURE
END IF
value := X
IF TS(T) > RTS(X) THEN
RTS(X) := TS(T)
END IF
RETURN value
Write Operation (with Thomas Write Rule):
WRITE(T, X, v):
IF TS(T) < RTS(X) THEN
ABORT(T)
RETURN FAILURE
END IF
IF TS(T) < WTS(X) THEN
// Thomas Write Rule: ignore obsolete write
RETURN SUCCESS
END IF
X := v
WTS(X) := TS(T)
RTS(X) := TS(T)
RETURN SUCCESS
Abort Handling:
ABORT(T):
state(T) := ABORTED
ROLLBACK_CHANGES(T) // Undo all writes by T
RESTART_TRANSACTION(T) // Begin new transaction with new TS
// Note: RTS updates by T may remain (can't be easily undone)
Commit Processing:
COMMIT(T):
IF state(T) = ACTIVE THEN
state(T) := COMMITTED
MAKE_DURABLE(changes(T)) // Write to stable storage
END IF
When T aborts, its writes can be undone, but RTS updates are harder to reverse. If T read X and updated RTS(X), that update typically remains. This is generally safe (a higher RTS just means more restrictive write checks) but can cause unnecessary aborts of other transactions.
Let's trace a complete multi-transaction scenario to see the protocol in action.
Scenario Setup:
| Time | Operation | TS Check | X State | Y State | Result |
|---|---|---|---|---|---|
| t1 | T2: R(Y) | 20 ≥ WTS(0) ✓ | — | RTS=20 | Y=200 |
| t2 | T1: R(X) | 10 ≥ WTS(0) ✓ | RTS=10 | — | X=100 |
| t3 | T3: R(X) | 15 ≥ WTS(0) ✓ | RTS=15 | — | X=100 |
| t4 | T2: W(X, 400) | 20 ≥ RTS(15) ✓, 20 ≥ WTS(0) ✓ | WTS=20, RTS=20, X=400 | — | Success |
| t5 | T1: W(Y, 150) | 10 ≥ RTS(20)? ✗ | — | — | ABORT T1 |
Analysis of the Trace:
T1 aborts because T2, which is "younger," has already read the value T1 wants to modify.
After T1 Restarts as T4 (TS=25):
| Time | Operation | TS Check | State | Result |
|---|---|---|---|---|
| t6 | T3: R(Y) | 15 ≥ WTS(0) ✓ | RTS(Y)=20 (not updated, 15<20) | Y=200 |
| t7 | T4: R(X) | 25 ≥ WTS(20) ✓ | RTS(X)=25 | X=400 (T2's value!) |
| t8 | T4: W(Y, 450) | 25 ≥ RTS(20) ✓, 25 ≥ WTS(0) ✓ | WTS(Y)=25, RTS(Y)=25, Y=450 | Success |
| t9 | All transactions complete | — | — | T2, T3, T4 commit |
Notice that T4 (the restarted T1) reads X=400, not X=100. The restart caused T4 to see T2's modification, changing the computation from Y = 100+50 = 150 to Y = 400+50 = 450. The serialization order is effectively T2 → T3 → T4.
The Basic Timestamp Protocol guarantees conflict serializability. Let's understand why and how to verify this.
The Serializability Theorem:
Any schedule produced by the Basic Timestamp Protocol (with or without Thomas Write Rule) is conflict-equivalent to the serial schedule that orders transactions by their timestamps.
Proof Intuition:
Conflicting operations are ordered by timestamp:
Since all conflicts respect timestamp order, the schedule is equivalent to executing transactions in timestamp order.
| Actual Schedule | Equivalent Serial Schedule |
|---|---|
| T2: R(Y), T1: R(X), T3: R(X), T2: W(X) | T1: R(X) (aborted, becomes T4) |
| T1: W(Y) ABORT, restarts as T4 | T3: R(X), R(Y) |
| T3: R(Y), T4: R(X), T4: W(Y), COMMIT all | T2: R(Y), W(X) |
| — | T4: R(X), W(Y) |
Constructing the Precedence Graph:
To verify serializability, construct a precedence graph where:
For timestamp ordering, the graph always has edges only in the timestamp direction (smaller to larger). A graph with all edges going one direction cannot have cycles, so the schedule is always serializable.
Unlike lock-based protocols where you must analyze the resulting schedule, timestamp ordering guarantees serializability by construction. The protocol's rules ensure the precedence graph is always acyclic. You never need to check after the fact.
While Basic Timestamp Ordering guarantees serializability, it does not guarantee recoverability. This is a critical limitation for practical systems.
The Dirty Read Problem:
Consider:
T2 has committed with a value that was never durable—T1's write was rolled back. This is a dirty read leading to an unrecoverable schedule.
In a recoverable schedule, transactions must not commit until all transactions whose writes they read have committed. Basic Timestamp Ordering doesn't enforce this—it only checks timestamps, not commit status.
Solutions for Recoverability:
1. Strict Timestamp Ordering:
2. Commit Dependencies:
3. Multi-Version Concurrency Control (MVCC):
| Solution | Mechanism | Trade-off |
|---|---|---|
| Strict TSO | Delay reads of uncommitted data | Introduces blocking, loses pure no-wait property |
| Commit Dependencies | Track and cascade aborts | Complex bookkeeping, cascading abort risk |
| MVCC | Multiple versions, read committed | Storage overhead, garbage collection needed |
Basic Timestamp Ordering and Two-Phase Locking (2PL) are two fundamentally different approaches to serializability. Understanding their differences helps in choosing the right protocol for specific workloads.
| Aspect | Timestamp Ordering | Two-Phase Locking |
|---|---|---|
| Mechanism | Compare timestamps, abort on conflict | Acquire locks, wait on conflict |
| Conflict Resolution | Younger wins, older aborts | First holder wins, others wait |
| Deadlocks | Impossible (no waiting) | Possible (requires detection/prevention) |
| Starvation | Possible (repeated aborts) | Possible (long lock waits) |
| Restart Overhead | High (aborts lose all work) | Low (waits preserve work) |
| Overhead per Operation | Timestamp checks + updates | Lock acquire/release |
| Recoverability | Not guaranteed by default | Strict 2PL guarantees it |
| Best for | Read-heavy, low-conflict workloads | Write-heavy, high-conflict workloads |
Most production databases don't use pure timestamp ordering or pure 2PL. They use MVCC (a timestamp-based approach) combined with locks for writes. PostgreSQL, Oracle, and SQL Server all use variations of this hybrid approach.
Implementing Basic Timestamp Ordering in a real system presents several challenges beyond the core algorithm.
Distributed Timestamp Ordering:
In distributed databases, timestamp ordering faces additional challenges:
Clock Skew: Physical clocks on different nodes differ; a transaction on node A might get TS=100 while a later transaction on node B gets TS=95.
Global Timestamp Source: Using a central timestamp server eliminates skew but creates a bottleneck and single point of failure.
Hybrid Logical Clocks (HLC): Combine physical time with logical counters; provide causality guarantees without tight synchronization.
TrueTime (Google Spanner): Uses GPS and atomic clocks to bound clock uncertainty; enables globally serializable transactions.
Although pure Basic Timestamp Ordering is rarely used, understanding it is crucial because: (1) MVCC is directly derived from timestamp concepts, (2) timestamp reasoning appears in many distributed protocols, and (3) the trade-offs inform modern hybrid designs.
We've now covered the complete Basic Timestamp Protocol. Let's consolidate everything:
| Component | Purpose | Key Rule |
|---|---|---|
| RTS(X) | Track youngest reader | RTS(X) = max(RTS(X), TS(T)) on read |
| WTS(X) | Track writer identity | WTS(X) = TS(T) on write |
| Read Rule | Prevent future reads | Allow iff TS(T) ≥ WTS(X) |
| Write Rule 1 | Protect prior reads | Allow iff TS(T) ≥ RTS(X) |
| Write Rule 2 | Respect newer writes | Allow iff TS(T) ≥ WTS(X) (or Thomas Rule) |
| Thomas Rule | Reduce aborts | If TS(T) < WTS(X), skip write, don't abort |
Where We Go From Here:
The Basic Timestamp Protocol establishes fundamental concepts that evolve into more practical protocols:
These topics are covered in subsequent modules of this chapter.
Congratulations! You've mastered the Basic Timestamp Protocol—from individual timestamps (RTS, WTS) through read and write rules to complete protocol execution. You understand how timestamp ordering achieves serializability, its limitations regarding recoverability, and how it compares to locking approaches. This foundation prepares you for understanding MVCC and modern concurrency control mechanisms.