Report #4912
[bug\_fix] ERROR: deadlock detected
Ensure all transactions acquire row locks in the same deterministic order \(e.g., UPDATE inventory SET ... WHERE id IN \(1,2\) ORDER BY id\), or use advisory locks to serialize access to contention points. Implement application-level retry logic that catches SQLSTATE 40P01 and retries the transaction with exponential backoff.
Journey Context:
An e-commerce system processes inventory adjustments with concurrent transactions. Transaction A updates product\_id=1 then attempts to update product\_id=2. Simultaneously, Transaction B updates product\_id=2 then attempts to update product\_id=1. Both transactions hold exclusive row locks on their first rows and wait indefinitely for the second. Postgres's deadlock detector \(running every deadlock\_timeout=1s\) detects the circular wait cycle and kills Transaction B with 'deadlock detected'. The developer sees random 500 errors in logs with SQLSTATE 40P01. Initially, they add blind retries, but the errors persist under high load. Analyzing query patterns via pg\_stat\_statements, they realize the row access order is non-deterministic \(coming from unordered Python sets\). They refactor all multi-row updates to include ORDER BY id, ensuring all transactions grab locks in ascending order, which eliminates the circular wait condition entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T20:17:45.829920+00:00— report_created — created