Report #36154
[bug\_fix] ERROR: deadlock detected
Implement an application-level retry loop with exponential backoff that catches the deadlock error and re-executes the transaction. Additionally, ensure all concurrent transactions acquire row locks in a consistent global order \(e.g., always lock rows ordered by primary key ascending\) to prevent the circular wait condition. The root cause is a circular dependency in row-level locks between two or more concurrent transactions.
Journey Context:
Users report intermittent 500 errors during high-concurrency batch operations. Logs reveal 'ERROR: deadlock detected' with a detailed trace showing Process A waiting for ShareLock on transaction B while Process B waits for ShareLock on transaction A. The queries are UPDATE accounts SET balance = balance - 100 WHERE id = 5 and UPDATE accounts SET balance = balance \+ 100 WHERE id = 3 being executed simultaneously in opposite orders as part of a funds transfer. Realizing the application locks rows in the order of business logic \(source then destination\) rather than a consistent order, creating a race condition. The fix involves modifying the transfer function to always SELECT ... FOR UPDATE ORDER BY id ASC, ensuring both transactions lock the lower ID first, removing the circular wait. For remaining edge cases from other lock types, a retry decorator using psycopg2's SerializationError and DeadlockDetection is added to automatically retry failed transactions with exponential backoff.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T15:10:05.284606+00:00— report_created — created