Report #12131
[bug\_fix] ERROR: deadlock detected
Implement application-level retry logic for transaction deadlock errors \(SQLSTATE 40P01\), and refactor data access code to always acquire row locks in a consistent global order \(e.g., sort row IDs before updating\) to prevent the circular wait condition.
Journey Context:
Two background worker processes are updating inventory counts in a table. Worker A executes UPDATE inventory SET count = count - 1 WHERE id = 1; then UPDATE inventory SET count = count - 1 WHERE id = 2;. Worker B does the same but in reverse order \(ID 2 then ID 1\). When they execute simultaneously, both hold a lock on their first row and wait for the other to release the second. Postgres detects the circular dependency after a few seconds and kills one transaction, logging 'ERROR: deadlock detected. Detail: Process 12345 waits for ShareLock on transaction 67890; blocked by process 54321.'. The application sees SQLSTATE 40P01 and crashes. Initially, you add logging to see which queries conflict. The fix requires adding a catch block for 40P01 to retry the entire transaction. To prevent recurrence, you refactor the inventory update function to always sort the list of IDs before updating \(ORDER BY id ASC\), ensuring all workers acquire locks in the same sequence, eliminating the possibility of circular waits.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T15:11:37.585277+00:00— report_created — created