备份日志中“Deadlock found when trying to get lock”实为MySQL服务端抛出的死锁,错误记录在MySQL error log(如/var/log/mysql/error.log)而非backup.log;需立即执行SHOW ENGINE INNODB STATUS\G捕获最近一次死锁详情,重点比对两个事务的SQL类型、锁持有与等待关系,并结合事务是否含LOCK IN SHARE MODE、一致性快照或备份账号等特征确认是否由备份引发。

备份日志里出现 Deadlock found when trying to get lock,不是备份工具出错,而是备份过程中触发了数据库真实死锁——mysqldump 或 mysqlpump 在读取表时加了 SELECT ... LOCK IN SHARE MODE 或显式 START TRANSACTION WITH CONSISTENT SNAPSHOT,和业务事务撞上了。
为什么备份日志里的死锁不能只看 backup.log?
备份工具(如 mysqldump --single-transaction)本身不报死锁,它只是执行 SQL;真正抛出 Deadlock found when trying to get lock 的是 MySQL 服务端。所以错误实际写在 MySQL 的 error log 里,而非备份脚本 stdout 或 backup.log。常见误判:
- 只翻备份命令的输出或重定向日志,却没查
log_error配置指向的文件(比如/var/log/mysql/error.log) - 看到备份中断就认为是“备份失败”,没意识到这是 InnoDB 主动检测并回滚了一个事务(可能是备份自己,也可能是某个正运行的业务事务)
- 用
SHOW ENGINE INNODB STATUS\G查时已过窗口期——该命令只保留最近一次死锁,而备份通常持续数分钟,中间可能已发生多次覆盖
必须立刻执行的三步现场捕获
一旦备份报错,登录数据库后不做任何其他操作,立即执行:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
SHOW ENGINE INNODB STATUS\G—— 注意带\G,否则锁信息挤成一行难以识别 - 在输出中直接搜索
LATEST DETECTED DEADLOCK,跳过前面 buffer pool、semaphore 等无关块 - 重点比对两个事务块中的:
*** (1) TRANSACTION:和*** (2) TRANSACTION:,尤其看:- 哪条是备份语句(通常是
SELECT ... FROM `t` LOCK IN SHARE MODE或隐式快照读) - 哪条是业务 SQL(比如
UPDATE t SET status=? WHERE id=?) - 双方
HOLDS THE LOCK(S)和WAITING FOR THIS LOCK TO BE GRANTED是否构成循环(例如:备份锁着PRIMARY,业务等这个锁;业务锁着idx_status,备份又等它)
- 哪条是备份语句(通常是
如何确认是不是备份引发的死锁?
关键看事务上下文是否含备份特征:
- 事务中出现
LOCK IN SHARE MODE、SELECT ... FOR UPDATE(某些 dump 模式会用)、或START TRANSACTION WITH CONSISTENT SNAPSHOT—— 这些都是备份工具典型行为 - 事务
MySQL thread id对应的连接用户是备份账号(如backup_user),且query id为空或为 0(预编译语句常见) - 等待锁的
index名称和备份表名一致,且lock_mode是S locks rec but not gap(共享记录锁)或X locks rec but not gap(若备份用了--lock-tables) - 对比备份启动时间与
error log中死锁时间戳是否吻合(误差通常在秒级)
备份场景下最易被忽略的冲突点
不是所有死锁都来自业务更新逻辑。备份特有的风险包括:
-
--single-transaction模式下,长事务会阻塞一致性快照建立,导致备份线程卡在waiting for transaction to start,此时若业务恰好更新同一张表,InnoDB 可能因锁升级或间隙判断产生死锁 - 备份期间执行
ALTER TABLE或OPTIMIZE TABLE,它们需要MDL X锁,与备份的MDL SH锁不兼容,虽不直接报 1213,但可能间接引发行锁等待链断裂 - 使用
--lock-tables时,FLUSH TABLES WITH READ LOCK会阻塞 DML,但若已有长事务未提交,备份会等它结束;这期间业务新事务尝试更新同表,极易因锁顺序混乱触发死锁 - 备份读取大表时,若该表无主键或唯一索引,InnoDB 可能退化为全表扫描加锁,把
gap lock扩散到整段索引空隙,大幅提高与插入事务冲突概率










