Introduction
When multiple users try to change data at the same time, conflicts can happen that cause errors or lost updates. Timestamp-based protocols help decide the order of these changes to keep data correct and consistent.
Imagine a busy checkout line where each customer gets a ticket number when they arrive. The cashier serves customers in ticket order, even if someone tries to cut in line. If a customer tries to pay out of turn, they are asked to wait until their number is called.
┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Transaction 1 │──────▶│ Timestamp 1 │──────▶│ Reads/Writes │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Transaction 2 │──────▶│ Timestamp 2 │──────▶│ Reads/Writes │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ ▼ ▼ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ Transaction 3 │──────▶│ Timestamp 3 │──────▶│ Reads/Writes │ └───────────────┘ └───────────────┘ └───────────────┘
class Transaction: _counter = 0 def __init__(self): Transaction._counter += 1 self.timestamp = Transaction._counter self.active = True class TimestampProtocol: def __init__(self): self.data = {} self.read_ts = {} self.write_ts = {} def read(self, transaction, item): if item in self.write_ts and self.write_ts[item] > transaction.timestamp: transaction.active = False # Rollback return None self.read_ts[item] = max(self.read_ts.get(item, 0), transaction.timestamp) return self.data.get(item, None) def write(self, transaction, item, value): if (item in self.read_ts and self.read_ts[item] > transaction.timestamp) or \ (item in self.write_ts and self.write_ts[item] > transaction.timestamp): transaction.active = False # Rollback return False self.data[item] = value self.write_ts[item] = transaction.timestamp return True # Example usage protocol = TimestampProtocol() t1 = Transaction() t2 = Transaction() print(protocol.write(t1, 'x', 10)) # True print(protocol.read(t2, 'x')) # 10 print(protocol.write(t2, 'x', 20)) # True print(t1.active) # True print(t2.active) # True # t1 tries to write after t2 with higher timestamp print(protocol.write(t1, 'x', 30)) # False, rollback print(t1.active) # False