MySQL "Deadlock Found When Trying to Get Lock" — Reading thevictim Trace

Two transactions each hold locks the other needs; InnoDB kills one (the victim). Deadlocks are normal in busy systems — read the LATEST DETECTED DEADLOCK trace and fix the access pattern, don't just retry-blind.

What you'll see

Root causes

Inconsistent row-lock ordering

Transaction A updates rows 1→2 while B updates 2→1. Same statements, same data — opposite order: textbook deadlock. Fix: consistent ordering (e.g. always by ascending primary key) or fewer rows per transaction.

Gap-lock interference from secondary-index updates

Inserts/updates touching the same secondary-index range hold gap locks that collide. Batched updates in one big transaction amplify this.

Fix it

  1. Read the actual deadlock trace
    mysql -e "SHOW ENGINE INNODB STATUS\G" | sed -n '/LATEST DETECTED DEADLOCK/,/^---/p' | head -40
  2. Identify the two conflicting statements and their row order
    # the trace shows both transactions' last statements + lock waits — map them to your code paths
  3. Normalize lock order across code paths
    # sort target ids before updating: UPDATE ... WHERE id IN (...) ORDER BY id, or loop in ascending-id order in every path
  4. Shrink transactions and retry on 1213
    # commit often (shorter lock windows) + code-level retry on ER_LOCK_DEADLOCK for idempotent writes

Field note

Retry-on-deadlock is required regardless — a surviving victim's transaction is rolled back. But retries without fixing order just reshuffle who dies. innodb_lock_wait_timeout is a different error (1205, lock wait timeout): deadlocks are detected instantly; long waits are not deadlocks.

Common questions

Are deadlocks a sign something is broken?

In a busy write-heavy system they're occasional and expected — InnoDB detects them and rolls one side back. Frequent deadlocks indicate an access-pattern problem (inconsistent ordering, giant transactions), not corruption.

Why does the same batch job deadlock only sometimes?

It races whatever else touches those rows: the interleaving matters, so timing decides. Fix the pattern (order + shorter transactions) rather than chasing the specific run.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.