Report #46935
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01\)
Root cause: Two concurrent transactions acquired locks on rows in opposite order \(e.g., Transaction A locks row 1 then tries row 2; Transaction B locks row 2 then tries row 1\), creating a cycle. Postgres automatically detects this cycle and aborts one transaction to break the deadlock. The fix is application-level: catch SQLSTATE 40P01 and retry the entire transaction with exponential backoff. Alternatively, prevent the cycle by always acquiring locks in a consistent global order \(e.g., ORDER BY primary\_key ASC FOR UPDATE\).
Journey Context:
A microservice processing inventory updates starts logging intermittent ERROR: deadlock detected. Two goroutines handle concurrent orders for SKU-123 and SKU-456. Goroutine A updates SKU-123 then SKU-456; Goroutine B updates SKU-456 then SKU-123. The Postgres logs show Process 12345 waits for ShareLock on transaction 67890; blocked by process 54321. The application was not catching 40P01, causing the request to fail. The fix adds a retry loop: BEGIN; ... COMMIT; If SQLException has code 40P01, rollback and retry up to 3 times with jitter. Deadlocks still occur but are handled transparently; alternatively, refactoring to sort SKUs before update eliminates them entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T09:15:07.357749+00:00— report_created — created