Report #41322
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01 in Postgres\)
Ensure all application code paths acquire row locks in the same consistent order \(e.g., ORDER BY id ASC\), or use advisory locks to serialize access to the same logical records, or implement application-level retry logic for 40P01 errors.
Journey Context:
During a flash sale, e-commerce checkout logs show 'ERROR: deadlock detected' with 'Process 12345 waits for ShareLock on transaction 67890; blocked by process 54321'. Transaction A updates inventory for SKU-123 then SKU-456. Transaction B updates SKU-456 then SKU-123. Both hold lock on first item, wait forever on second. Postgres detects the cycle and kills the 'lighter' transaction \(fewer locks held\), which returns 40P01 to the app. The app shows 'Payment failed' to the user even though the card was charged \(compensating transaction needed\). Root cause analysis shows two different code paths: the cart checkout path sorts items by cart order, while the admin inventory adjustment path sorts by SKU. The fix enforces a global ORDER BY clause on all multi-row update transactions, ensuring locks are always acquired in ID order, eliminating the circular wait condition.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T23:50:03.214709+00:00— report_created — created