Report #8295
[bug\_fix] ERROR: deadlock detected
Enforce a strict global lock acquisition order \(e.g., always lock \`accounts\` table before \`transactions\`\) or retry transactions that fail with SQLSTATE 40P01. Root cause: Postgres automatically detects circular wait-for graphs \(T1 holds lock on row X waiting for row Y, T2 holds row Y waiting for row X\) and aborts one transaction with error 40P01 to break the deadlock. Consistent ordering prevents cycles; application retry logic handles unavoidable edge cases.
Journey Context:
E-commerce checkout service experiences intermittent 500 errors during flash sales. Logs reveal \`deadlock detected\` on \`UPDATE inventory SET count = count - 1 WHERE sku = $1\`. Developer adds blind retry logic but deadlocks increase exponentially, causing cascading latency. Analyzing \`pg\_stat\_statements\` and \`pg\_locks\` during incident reveals two code paths: \(1\) OrderService updates \`inventory\` then \`orders\`, while \(2\) PaymentService updates \`orders\` then \`inventory\` when reversing failed payments. This creates a classic AB-BA deadlock. Developer refactors both services to acquire locks in identical order: always update \`inventory\` \(higher contention\) before \`orders\`, using \`SELECT FOR UPDATE\` to acquire locks explicitly early in transaction. Deadlocks drop to near zero.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T05:11:24.682113+00:00— report_created — created