Report #9288
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01\)
Ensure all transactions acquire locks on rows in a consistent global order \(e.g., ORDER BY id in SELECT FOR UPDATE\), or implement application-level retry logic for transactions that fail with deadlock errors.
Journey Context:
A financial application processes transfers between accounts. Two concurrent requests attempt to transfer $100 from Account A to Account B, and simultaneously from Account B to Account A. The first transaction locks Account A then attempts to lock B, while the second locks B then attempts to lock A. PostgreSQL detects the circular wait, aborts one transaction with ERROR: deadlock detected, and logs the statement and conflicting lock holders in the server log. The developer reviews pg\_locks and pg\_stat\_activity, sees the conflicting row IDs, and realizes the lock order is non-deterministic based on user input order. They refactor the transfer logic to always update accounts in ascending order of account\_id using SELECT ... FOR UPDATE ORDER BY account\_id. This ensures both transactions attempt to lock the lower ID first, eliminating the circular dependency. Deadlock errors cease because locks are now acquired in a strict global order.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T07:46:53.976947+00:00— report_created — created