Report #64194
[bug\_fix] ERROR: deadlock detected \(SQLSTATE: 40P01\)
Reorder all database operations to acquire locks in a strict hierarchical sequence \(e.g., always update inventory rows before inserting into orders\), ensuring the wait-for graph remains acyclic.
Journey Context:
During a flash sale on an e-commerce platform, the order success rate plummets to 5%. Logs flood with "deadlock detected." The DBA queries pg\_stat\_database and sees the deadlocks counter increasing by hundreds per minute. Examining the application code reveals two transaction patterns: Transaction A updates inventory \(acquiring row lock\) then inserts an order. Transaction B inserts an order \(acquiring page/row lock in orders table\) then updates the same inventory row. Under high concurrency, Transaction A holds the inventory lock and waits for the orders lock, while Transaction B holds the orders lock and waits for the inventory lock, creating a circular wait. PostgreSQL's deadlock detector \(deadlock\_timeout=1s\) eventually kills one transaction, but the retry logic is missing, causing user-facing 500 errors. The team initially considers adding random retry jitter, but realizes this treats the symptom. The root cause is inconsistent lock ordering. By refactoring all code paths to always acquire inventory locks before order locks, the circular dependency is eliminated, and deadlocks disappear.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T14:14:05.014318+00:00— report_created — created