Transactions & Concurrency
Deadlocks, Contention, and Retries
A deadlock is a cycle of waits; ordinary contention is a queue without a cycle. Engines detect cycles or use timeouts and sacrifice work, so applications need short, consistently ordered transactions and bounded, transaction-level retries.
- A wait-for cycle cannot resolve itself.
- Timeout is not proof of deadlock.
- Deadlocks are normal but rates are diagnostic.
- Retry the whole invalidated unit.
- Backoff needs jitter and bounds.
- Idempotency is not automatic.
Start: A=100, B=100; invariant total=200.
T1 locks A, then requests B. T2 locks B, then requests A.
Wait-for edges T1→T2 and T2→T1 form a cycle.
Engine aborts one victim; survivor commits; victim must restart from its first read.deadline = now + 2s; maxAttempts = 4
for attempt in 1..maxAttempts:
begin; run complete transaction from fresh reads; commit; return
on classified deadlock/serialization failure:
rollback; if deadline exceeded: fail
sleep(random(0, min(25ms * 2^(attempt-1), 250ms)))
Never retry unknown errors or duplicate external effects blindly.| Symptom | Practice |
|---|---|
| Opposite lock order | Sort keys and access tables consistently |
| Many locks | Add selective indexes; shrink scanned set |
| Long holders | Remove remote/user waits; commit promptly |
| Hot row | Partition, batch, or redesign shared counter |
| Retry storm | Jitter, cap, admission control, observability |