Basic Timestamp Protocol
Protocol Execution
Read aloud is unavailable in this browser.
The Complete Protocol in Action
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.
Transaction Lifecycle
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:
- A unique timestamp TS(T) is assigned from a monotonically increasing source
- The transaction enters the ACTIVE state
- No other initialization is required—no locks to acquire, no resources to reserve
Timestamp sources can be:
- System clock: Physical time with sub-millisecond resolution
- Logical counter: Atomic counter incremented on each new transaction
- Hybrid: Combination of physical time and logical sequence number
| 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:
- Read(X): Check WTS(X), return value or abort, update RTS(X)
- Write(X, v): Check RTS(X) and WTS(X), write or abort, update WTS(X)
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:
- Transaction can commit
- Changes become durable
- Transaction's effects are permanent
If any operation fails:
- Transaction aborts
- All changes are rolled back
- Transaction may restart with a new (larger) timestamp
Complete Protocol Algorithm
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.
Detailed Execution Trace
Let's trace a complete multi-transaction scenario to see the protocol in action.
Scenario Setup:
- Data items: X (initial value = 100), Y (initial value = 200)
- Initial timestamps: WTS(X) = 0, RTS(X) = 0, WTS(Y) = 0, RTS(Y) = 0
- Transactions:
- T1 (TS=10): R(X), W(Y, X+50)
- T2 (TS=20): R(Y), W(X, Y*2)
- T3 (TS=15): R(X), R(Y)
| 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-t3: All reads succeed because WTS = 0 for both items initially
- t4: T2's write to X succeeds because TS(T2)=20 ≥ RTS(X)=15 and ≥ WTS(X)=0
- t5: T1's write to Y fails because TS(T1)=10 < RTS(Y)=20 (T2 already read Y)
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.
Serializability Analysis
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:
- If T1 reads X before T2 writes X, then TS(T1) < TS(T2) (enforced by write's RTS check)
- If T1 writes X before T2 reads X, then TS(T1) < TS(T2) (enforced by read's WTS check)
- If T1 writes X before T2 writes X, then TS(T1) < TS(T2) (enforced by write's WTS check)
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:
- Nodes = committed transactions
- Edges = T1 → T2 if T1 and T2 conflict and T1's conflicting operation precedes T2's
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.
Recoverability Considerations
While Basic Timestamp Ordering guarantees serializability, it does not guarantee recoverability. This is a critical limitation for practical systems.
The Dirty Read Problem:
Consider:
- T1 (TS=10) writes X = 50
- T2 (TS=20) reads X (gets 50, check passes: 20 ≥ WTS(10))
- T2 uses value 50 in computation, commits
- T1 aborts (for unrelated reasons)
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:
- Delay reads of uncommitted data
- When T wants to read X written by T', and T' hasn't committed:
- Option A: T waits for T' to commit (introduces blocking)
- Option B: T aborts and retries later
2. Commit Dependencies:
- Allow the read, but track that T depends on T'
- T cannot commit until T' commits
- If T' aborts, T must also abort (cascading abort)
3. Multi-Version Concurrency Control (MVCC):
- Keep multiple versions of each data item
- Readers access the most recent committed version
- Writers create new versions without affecting readers
- This is the approach used by most modern databases
| 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 |
Comparison with Two-Phase Locking
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 |
- •Workload is mostly reads
- •Conflicts are rare
- •Deadlock handling is costly
- •Bounded response time needed
- •Simple implementation preferred
- •Workload has many writes
- •Conflicts are frequent
- •Restart cost is high (long TXNs)
- •Strict recoverability needed
- •Predictable behavior preferred
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.
Practical Implementation Issues
Implementing Basic Timestamp Ordering in a real system presents several challenges beyond the core algorithm.
- •Timestamp Generation: Monotonically increasing, unique timestamps across distributed nodes require clock synchronization or global counters (bottleneck risk)
- •Timestamp Storage: Every data item needs WTS and RTS (16+ bytes overhead per row in row-level granularity)
- •Read Amplification: RTS updates turn reads into writes, causing cache invalidation and increased I/O
- •Abort Recovery: When T aborts, its writes must be undone; this requires either logging or deferred writes
- •Timestamp Metadata Durability: For crash recovery, timestamps must be logged or rebuilt
- •Hot Spot Handling: High-RTS items cause many write aborts; need special handling
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.
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.