Symptom triage
Production transaction bugs announce themselves as one of five symptoms. Each row maps a symptom to the lesson that proves the mechanism and the lesson that fixes it. This page is the index you paste into the incident channel.
| Symptom | First check | Mechanism | Fix |
|---|---|---|---|
| Updates hang, then finish | Who is blocking whom | lock queues | end the blocker; shorter transactions |
Updates hang, then errno 1205 | Who is blocking whom | lock wait timeout, statement rollback only! | retry after ROLLBACK; find the blocker |
Errno 1213 in the logs | the deadlock counter | deadlocks, gap locks | consistent lock order; retry loop |
| INSERTs stuck with no row conflict | data_locks for GAP / INSERT_INTENTION | gap locks | READ COMMITTED for the writer, or narrower locking reads |
| Numbers wrong, no errors anywhere | the anomaly catalog | lost updates, write skew | the three fixes |
| Disk grows, queries don't slow | history list health | an old read view pins purge | end the long transaction |
| DDL hangs and takes the app with it | processlist: Waiting for table metadata lock | metadata locks | lock_wait_timeout on the DDL session |
Two MySQL-specific reflexes are worth building on top of that table. Start with this one: errors that look alike often aren't. 1205 rolls back a single statement and leaves the transaction open, still holding its locks, while 1213 rolls back the whole transaction. Handling the two identically is pitfall material.
The second reflex: silence isn't health. The costliest failures on this table (lost updates, write skew, purge lag) throw no error at all, so you catch them with counters and invariant checks, never by grepping logs.