MySQL · 错误码速查
MySQL 错误 1213:InnoDB 发现死锁,被选中的那个事务整笔回滚
两个(或更多)InnoDB 事务互相等对方持有的锁,形成环。开启死锁检测时(innodb_deadlock_detect 默认 ON),InnoDB 会立刻选一个事务整笔回滚并报 1213,让另一个继续。应用要重试整个事务,不是只重试最后一条语句。
官方原文
Deadlock found when trying to get lock; try restarting transaction官方说明:InnoDB 在事务遇到死锁并被自动回滚时报这个错,好让应用采取纠正动作;要恢复就重新跑这个事务里的全部操作。死锁来自事务之间加锁顺序不一致。
出处:MySQL 8.4 Error Reference:Server Error Message Reference 最后核对:
| 错误号 / 符号 | 1213 / ER_LOCK_DEADLOCK | 出处 |
|---|---|---|
| SQLSTATE | 40001 | 出处 |
| 回滚范围 | 整个事务(不是单条语句) | 出处 |
| 选谁回滚 | InnoDB 尽量挑「改动行数更少」的小事务回滚 | 出处 |
| 检测开关 | innodb_deadlock_detect:默认 ON,可在线改;关掉后靠 innodb_lock_wait_timeout 超时拆环 | 出处 |
| 相邻错误 | 1205 是锁等待超时(默认只回滚当前语句);1213 是检测到环后立刻整事务回滚 | 出处 |
盈尺实测(测试库,非官方文档):MySQL 8.0.46 测试库复现间隙锁 + 插入意向锁死锁,附 SHOW ENGINE INNODB STATUS 读法、只读巡检 SQL 和演示脚本。 看 1213 间隙锁 / 插入意向锁实测长文 →
报 1213 之后,回滚了什么、怎么重试
- 整事务回滚:官方 InnoDB Error Handling 写明,死锁会让 InnoDB 回滚整个事务;锁等待超时(1205)默认只回滚当前语句。(InnoDB Error Handling)
- 重试整个事务:错误参考原文是 “run all the operations in this transaction again”。被回滚的一方已经释放全部锁,另一方通常能拿到锁;重跑时可能要再等一会儿,但一般不会马上再死锁一次。
- 谁被挑中:死锁检测开启时,InnoDB 尽量挑改动行数更少的事务回滚。(Deadlock Detection)
应用如果只捕获 1213 后重试「最后一条 SQL」,事务前面已经回滚掉的写入不会自动回来。要按业务边界重开整笔事务。
1213 和 1205 怎么区分
| 1213 死锁 | 1205 锁等待超时 | |
|---|---|---|
| 符号 / SQLSTATE | ER_LOCK_DEADLOCK / 40001 | ER_LOCK_WAIT_TIMEOUT / HY000 |
| 触发条件 | InnoDB 检测到循环等待 | 等锁超过 innodb_lock_wait_timeout(默认 50 秒) |
| 默认回滚范围 | 整个事务 | 当前语句 |
| 重试什么 | 整个事务 | 默认重试语句 |
| 发生速度 | 检测开启时几乎立刻 | 至少等满超时秒数 |
innodb_deadlock_detect=ON(默认)时,真正的死锁不会拖到 1205:InnoDB 会先拆环并报 1213。只有关掉死锁检测,死锁里的事务才可能靠锁等待超时结束。(Deadlock Detection、InnoDB 系统变量 innodb_lock_wait_timeout)
先看 LATEST DETECTED DEADLOCK
SHOW ENGINE INNODB STATUS\G这一段会写出参与死锁的事务、各自持有和等待的锁、以及哪一个被选为牺牲者。读法与复现脚本见长文:MySQL 死锁 1213 / 间隙锁实测。
官方还提醒:若出现 TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH,表示 wait-for 列表达到 200 个事务(或需要查看超过 100 万把锁),也会被当作死锁处理并回滚正在检查的事务。(Deadlock Detection)
现场只读:谁在等锁、事务开了多久
SELECT waiting_pid, waiting_query, blocking_pid, blocking_query
FROM sys.innodb_lock_waits;
SELECT trx_id, trx_state, trx_started,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS age_s,
trx_mysql_thread_id, trx_query
FROM information_schema.INNODB_TRX
ORDER BY trx_started;官方建议怎么少死锁
- 让不同事务 / 应用的加锁顺序一致(
LOCK TABLES、SELECT ... FOR UPDATE等)。(错误参考原文) - 事务里从第一次改数据到 COMMIT 之间少做事,锁持有时间尽量短、锁住的行尽量少。(InnoDB Error Handling)
- 高并发下若死锁检测本身成为瓶颈,可以关
innodb_deadlock_detect,改靠innodb_lock_wait_timeout;这是吞吐取舍,不是「一关就没事」。(Deadlock Detection)
常见问题
mysql 1213 错误是什么意思?
1213(ER_LOCK_DEADLOCK,SQLSTATE 40001)表示 InnoDB 检测到事务之间的循环锁等待,并回滚了其中一个事务。被回滚的一方要重试整个事务。
1213 和 1205 有什么区别?
1213 是死锁检测拆环,整事务回滚;1205 是等锁超时,默认只回滚当前语句。检测开启时,真正的死锁通常先变成 1213,不会拖到 1205。
报 1213 后要不要重试?重试哪一段?
要重试。官方要求把这个事务里的全部操作再跑一遍,而不是只重试最后一条 SQL。
怎么查看刚才那次死锁的详情?
执行 SHOW ENGINE INNODB STATUS\G,看 LATEST DETECTED DEADLOCK 段。需要 PROCESS 权限;它只保留最近一次检测到的死锁。
关掉 innodb_deadlock_detect 能消灭 1213 吗?
关掉后 InnoDB 不再主动拆环,死锁会拖到锁等待超时,表现更像 1205。官方把它当成高并发下的性能取舍,不是根治办法;根治仍是统一加锁顺序、缩短事务。
下一步
价格以对应页面当前标价为准。
出处(最后核对 2026-10-28)
- MySQL 8.4 Error Reference:Server Error Message Reference
- MySQL 8.4 Reference Manual:InnoDB Error Handling
- MySQL 8.4 Reference Manual:Deadlock Detection
- MySQL 8.4 Reference Manual:InnoDB Startup Options and System Variables(innodb_lock_wait_timeout / innodb_deadlock_detect)
本页摘录并解读上面列出的官方文档,不是官方页面;官方文档更新后以官方为准。除标明「盈尺实测」的一段外,其余内容都来自官方文档。