Report #69219
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01\)
Enforce a strict global lock ordering \(e.g., always lock table A before table B\), keep transactions as short as possible, and implement application-level retry logic with exponential backoff specifically for 40P01 errors.
Journey Context:
A developer maintains an e-commerce platform where order processing updates both the \`inventory\` and \`orders\` tables. During Black Friday traffic, logs flood with "deadlock detected" errors. Investigating \`pg\_stat\_activity\` during the incident, they capture two concurrent transactions: Transaction 1 holds a row lock on \`inventory\` \(product\_id=100\) and waits for a lock on \`orders\` \(order\_id=500\); Transaction 2 holds the lock on \`orders\` \(order\_id=500\) and waits for the lock on \`inventory\` \(product\_id=100\). They realize different code paths acquire locks in opposite orders: the checkout API locks inventory then orders, while the refund API locks orders then inventory. They refactor all database access to follow a strict alphabetical order: acquire locks on \`customers\`, then \`inventory\`, then \`orders\` regardless of business logic. They also implement a Python decorator using \`tenacity\` that catches \`psycopg2.errors.DeadlockDetected\` \(40P01\), waits a random 10-100ms, and retries up to 3 times. After deployment, deadlocks still occur statistically but are transparently retried, and the strict ordering prevents the circular wait condition from causing permanent stalls.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T22:40:14.709051+00:00— report_created — created