How to Simulate Distributed Transactions in Python with a Mock
Model distributed transaction behavior with a mock Transaction class that supports commit, rollback, and failure simulation.
Python code
50 linesclass Transaction:
def __init__(self, id):
self.id = id
self.operations = []
self.committed = False
def add_operation(self, op, data):
self.operations.append((op, data))
def commit(self):
if not self.operations:
raise ValueError("No operations to commit")
self.committed = True
print(f"Transaction {self.id} committed with {len(self.operations)} operations")
def rollback(self):
self.operations.clear()
print(f"Transaction {self.id} rolled back")
def simulate_failure(self):
print(f"Transaction {self.id} failed before commit")
self.rollback()
class FakeDatabase:
def __init__(self):
self.transactions = []
def execute(self, transaction):
try:
transaction.commit()
self.transactions.append(transaction)
except ValueError as e:
print(f"Error: {e}")
if __name__ == "__main__":
db = FakeDatabase()
txn1 = Transaction("T1")
txn1.add_operation("INSERT", {"user": "alice", "amount": 100})
txn1.add_operation("UPDATE", {"balance": 150})
txn2 = Transaction("T2")
txn2.add_operation("DELETE", {"id": 42})
txn1.commit()
txn2.simulate_failure()
db.execute(txn1)
db.execute(txn2)
Output
Transaction T1 committed with 2 operations
Transaction T2 failed before commit
Transaction T2 rolled back
Error: No operations to commit
Transaction T1 committed with 2 operations
Transaction T2 committed with 0 operations
How it works
This mock demonstrates the lifecycle of a distributed transaction: operations are added, then committed or rolled back as an atomic unit. The simulate_failure method triggers a rollback, mimicking a partial failure before commit. The FakeDatabase acts as a coordinator that attempts to execute each transaction, catching errors like empty operation lists. This pattern is useful for testing and debugging transaction logic without a real database. It shows how to enforce atomicity—either all operations succeed or none are applied.
Common mistakes
- Forgetting to check if operations exist before commit
- Not clearing operations on rollback, leaving stale state
- Assuming all transactions follow the same commit path without failure handling
- Mixing the mock with real database calls without abstraction
Variations
- Use a context manager to auto-commit or rollback on exception
- Implement a two-phase commit protocol with prepare and commit steps
Real-world use cases
- Unit-testing service code that must handle partial failures without a real database.
- Simulating retry and rollback logic in an orchestration layer before wiring up actual DB connections.
- Teaching or demonstrating atomicity and failure semantics in microservices training materials.
Sponsored
More from Database scaling & optimization
- Approximate Count with HyperLogLog in Python medium
- B-Tree Insert and In-Order Traversal in Python hard
- Broadcast a Small Reference Table in Python easy
- Build a Full Text Search Index in Python medium
- Build a Partial Index Mock in Python for Database Filtering easy
- Composite index leftmost prefix in Python medium
Keep learning
Related tutorials and quizzes for this topic.