The Symptom
Symptom
Root Cause Analysis
Root Cause
The issue stemmed from how MySQL (InnoDB engine) handles row-level locks on tables with Foreign Key constraints. When a user checked out, Transaction A would lock the `users` row to update their loyalty points, and then attempt to insert a row into `orders` (which has a foreign key referencing `users`). Simultaneously, a background webhook (Transaction B) would attempt to insert a receipt into `orders`, and then update the `users` table to mark them as a returning customer. Because Transaction A locked `users` and waited for `orders`, while Transaction B locked `orders` and waited for `users`, a classic circular deadlock occurred. InnoDB detected this and instantly aborted Transaction A to break the cycle.
Resolution
Resolution
// The fatal flaw: Inconsistent locking order
// Webhook Tx: Locks Orders -> Locks Users
// Checkout Tx: Locks Users -> Locks Orders (DEADLOCK!)
// The fix: Global ordered locking convention
// Webhook Tx: Locks Users -> Locks Orders
// Checkout Tx: Locks Users -> Locks Orders
Discussions 0