Error handling for MySQL applications
Retry deadlocks and lock waits; reconnect on gone-away. Design for InnoDB concurrency.
InnoDB will sometimes ask the client to retry. Treating every SQL error as fatal pages humans for concurrency that worked as designed.
Transient errors
| Code | Meaning | Action |
|---|---|---|
| 1213 | Deadlock; transaction rolled back | Retry whole txn |
| 1205 | Lock wait timeout | Retry or shorten txn |
| 2006 / 2013 | Connection gone | Reconnect; retry txn |
| 1040 / 1203 | Too many connections | Back off; fix pooling |
Deadlock victims are chosen by InnoDB; your job is to retry the entire transaction with the same business intent, not to resume mid-statement.
Pattern
for attempt in 1..N:
BEGIN
try work → COMMIT → return
on 1213/1205: ROLLBACK; sleep with jitter
on connection loss: reconnect; retry
Rules:
- Cap attempts (3–5) with jittered exponential backoff
- Log SQLSTATE + truncated SQL for diagnostics
- Never retry non-idempotent side effects without an idempotency key or outbox
- Distinguish “retry forever” from “open a ticket” after N failures
Reduce deadlocks
- Consistent table/row lock order across all code paths
- Short transactions; no remote HTTP while holding locks
- Indexed lookups instead of scans that lock unintended ranges
- Prefer
READ COMMITTEDonly when you understand the trade-offs vs defaultREPEATABLE READ
Put retry policy in one repository or unit-of-work layer so product code cannot forget.