1213 — Deadlock found
MySQL raises error 1213 when two transactions each hold a row lock the other needs, a deadlock, and InnoDB breaks the cycle by rolling one transaction back whole, which the application should retry.
Reproduce it
Two sessions lock the same two rows in opposite order. The -- [A] and -- [B] markers say who runs each statement, top to bottom.
-- [A] lock alice's row
BEGIN;
UPDATE accounts SET balance = balance - 10 WHERE id = 1;
-- [B] lock bob's row
BEGIN;
UPDATE accounts SET balance = balance - 25 WHERE id = 2;
-- [A] now reach for bob's row: B holds it, so A waits
UPDATE accounts SET balance = balance + 10 WHERE id = 2;
-- [B] now reach for alice's row: A holds it, and the cycle closes
UPDATE accounts SET balance = balance + 25 WHERE id = 1;B's last statement fails with ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction. InnoDB spots the cycle the instant it forms and rolls one transaction back, here B, which frees bob's row so A's blocked update completes. The rollback is total: B's earlier UPDATE is gone too, so there's nothing left to ROLLBACK and nothing to fix. You just rerun B's transaction from the top.
Run it yourself
The Deadlocks lesson renders this exact scenario as a verified transcript. Because a deadlock throws away the whole transaction, the retry has to replay every statement. Retrying deadlocks shows the loop that does it, and Lock queues explains why the waits stack up into a cycle.
The PostgreSQL side
This is a true mirror of PostgreSQL's 40P01: the same opposite-order locking, the same abort-one-so-the-other-finishes resolution. The one difference is timing. InnoDB detects the cycle immediately, while PostgreSQL waits out deadlock_timeout (one second by default) before it checks.