Report #11597
[bug\_fix] ERROR: deadlock detected \(40P01\)
Retry the transaction on SQLSTATE 40P01, and enforce consistent lock acquisition order \(e.g., UPDATE rows sorted by primary key\). Root cause: Postgres detects a circular wait \(A waits for B, B waits for A\) and kills the 'victim' transaction to break the deadlock.
Journey Context:
You have a job queue processing bank transfers between accounts. Each job debits one account and credits another. Suddenly logs show 'ERROR: deadlock detected'. You query pg\_stat\_activity and pg\_locks and see two queries: UPDATE accounts SET balance = balance - 100 WHERE id = 5 \(waiting on lock for id=10\) and UPDATE accounts SET balance = balance \+ 100 WHERE id = 10 \(waiting on lock for id=5\). You realize the jobs are updating accounts in arbitrary order. Job A locks 5 then wants 10; Job B locks 10 then wants 5. You refactor the transfer logic to always acquire locks in ascending order of account\_id: sort the debit/credit pair, then do two separate UPDATES in that sorted order. Now both jobs try to lock account 5 first; one waits, the other proceeds, then locks 10. No cycle forms. You also add a try/catch block that catches 40P01 and retries the job, handling any residual edge cases.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T13:45:38.623502+00:00— report_created — created