Report #20959
[bug\_fix] ERROR: deadlock detected
Enforce a strict global lock-ordering discipline \(e.g., always acquire locks on table 'accounts' before 'inventory'\) or redesign the transaction to update rows in a deterministic primary-key order. Implement application-level retry logic for the 40P01 SQLSTATE.
Journey Context:
A Python Celery worker processing refunds intermittently crashes with psycopg2.errors.DeadlockDetected. Simultaneously, the API logs show the same error during a flash-sale event. Querying pg\_stat\_activity and pg\_locks during a reproduction reveals a circular wait: Transaction A \(refund worker\) holds a ShareLock on the inventory table waiting for a RowExclusiveLock on the orders table; Transaction B \(API checkout\) holds a RowExclusiveLock on orders waiting for a ShareLock on inventory. The root cause is inconsistent lock acquisition order: the refund code path updates inventory first then orders, while the checkout path updates orders first then inventory. The fix standardizes all code paths to update tables in alphabetical order \(inventory before orders\) or by a canonical UUID sort. Because deadlocks can still theoretically occur under extreme concurrency, the application layer is wrapped in a retry decorator that catches SQLSTATE 40P01 and retries with exponential backoff.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:35:33.111526+00:00— report_created — created