MySQL 死锁日志怎样还原等待关系
MySQL 死锁日志还原等待关系,关键是把每个事务的“已经持有”和“正在请求”分开,再按锁资源及不兼容的锁模式配对。等待方请求的资源被另一事务持有,才构成一条等待依赖;依赖闭合成环才解释了死锁。不能仅凭两条 SQL 操作同一张表,就认定它们相互阻塞。
下面以 MySQL 8.4 的 InnoDB 文档为基线。SQL 是供读者使用的只读诊断示例,未在本文运行;事务 A、B 和资源 RA、RB 是教学符号,不是真实生产日志。
官方说明:https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks-handling.html
先保留完整报告,再填三类信息
最小操作是取得 SHOW ENGINE INNODB STATUS 中的 LATEST DETECTED DEADLOCK 部分。需要同时保存报告时间、事务段、持有锁、等待锁和回滚选择,不能只截取最后一句错误。
-- 读取最近一次被记录的 InnoDB 死锁,注意报告时间不一定是当前故障。 SHOW ENGINE INNODB STATUS; -- 查看是否开启全部死锁记录,不在排查脚本中擅自修改全局配置。 SHOW GLOBAL VARIABLES LIKE 'innodb_print_all_deadlocks';
最近一次报告可能被后来的死锁覆盖。频繁发生时,可由有权限的运维人员评估开启 innodb_print_all_deadlocks,将每次死锁写到错误日志,完成定位后恢复配置。日志可能含 SQL 和业务值,应限制读取和保留范围,不能把未脱敏原始日志随意发到公共渠道。
先为每个事务填三项:事务标识与线程线索、已持有的锁资源和模式、等待获得的锁资源和模式。报告中的 (1)、(2) 是该报告内的段落编号,不是持久的事务 ID,也不表示谁先执行。当前 SQL 往往只是等待时的语句,之前获取锁的语句需要应用事务记录补全。
按资源与锁模式配对持有方和请求方
把 HOLDS THE LOCK(S) 当作持有信息,把 WAITING FOR THIS LOCK TO BE GRANTED 当作请求信息。对于记录锁,比较表、索引、space id、page no 和 heap no 等信息,并确认锁模式冲突。不能只比较 page no:同一页包含多条索引记录,同号页在不同表空间也不是同一资源。
假定教学报告明确给出下面四项,且 RA 与 RB 都是确定的索引记录,持有与请求均为不兼容的排他记录锁:
| 事务 | 已持有 | 正在请求 | 等待谁 |
|---|---|---|---|
| A | RA 的 X 记录锁 | RB 的 X 记录锁 | B,因 B 持有 RB |
| B | RB 的 X 记录锁 | RA 的 X 记录锁 | A,因 A 持有 RA |
于是等待关系是 A 等待 B,B 等待 A。这里的“请求 RB”不能误写成“A 已持有 RB”。报告的回滚选择表示引擎用来打破环的牺牲事务,不是业务责任认定;被回滚的一方也可能遵循了合理逻辑,根因在两条事务路径的组合。
实际关系可能包含更多事务或锁转换。对每一条依赖写清“请求方、阻塞方、资源、请求模式、持有模式”,无法对应的部分标为未确定,不要补猜。原始段落能证明一个等待环,不一定能证明完整的业务访问顺序。

当前等待用 Performance Schema 补充
若问题仍在发生,可查询 data_lock_waits,REQUESTING_ENGINE_TRANSACTION_ID 对应请求方,BLOCKING_ENGINE_TRANSACTION_ID 对应阻塞方。再用锁 ID 和 ENGINE 连接 data_locks,读取索引与锁模式。下面的 LEFT JOIN 保留等待关系行,即使采样期间部分锁明细已变化,也能看出对应信息为空。
-- 读取当前 InnoDB 数据锁等待;不是历史死锁回放。
SELECT
w.REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx,
w.BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx,
r.OBJECT_SCHEMA AS waiting_schema,
r.OBJECT_NAME AS waiting_table,
r.INDEX_NAME AS waiting_index,
r.LOCK_TYPE AS requested_type,
r.LOCK_MODE AS requested_mode,
r.LOCK_DATA AS requested_data,
b.LOCK_MODE AS blocking_mode,
b.LOCK_DATA AS blocking_data
FROM performance_schema.data_lock_waits AS w
LEFT JOIN performance_schema.data_locks AS r
ON r.ENGINE = w.ENGINE
AND r.ENGINE_LOCK_ID = w.REQUESTING_ENGINE_LOCK_ID
LEFT JOIN performance_schema.data_locks AS b
ON b.ENGINE = w.ENGINE
AND b.ENGINE_LOCK_ID = w.BLOCKING_ENGINE_LOCK_ID
WHERE w.ENGINE = 'INNODB';
一项请求可能被多个持有者阻塞,不能强制当作一对一关系。Performance Schema 的线程 ID 也不能直接等同于客户端连接 ID;关联会话时需要正确映射线程信息。LOCK_DATA 只是一项资源线索,可能包含索引键或为空,不是所有场景都提供完整业务行。
死锁处理后,相关等待通常已经消失,因此查询为空不能否定历史死锁。反过来,看到锁等待也不能单独证明死锁环。实时等待、历史死锁报告和应用事务日志要分别注明采样时间,不能拼成同一个瞬间的完整现场。字段文档:https://dev.mysql.com/doc/refman/8.4/en/performance-schema-data-lock-waits-table.html。

记录锁、间隙锁不能混成一个行号
InnoDB 的记录锁锁定索引记录。locks rec but not gap 表示该锁不覆盖前方间隙;gap before rec 描述的是记录前方的间隙;next-key 则涉及记录及其前方间隙。insert intention 又有自己的等待含义。资源名字看似相近,冲突规则并不相同。
特别是纯间隙锁之间可以共存,不能仅因两个事务都显示 gap,就画出相互阻塞。需要结合插入意向、记录锁以及请求模式判断。遇到 supremum 这类标记,也不能把它解释成业务表里名叫 supremum 的一条真实行。
PHYSICAL RECORD 的字段数、十六进制值和 heap no 不是可直接照搬的业务列。聚簇索引可能包含内部字段,二级索引记录也有不同结构;需要结合建表定义、索引组成和记录格式解释。heap no 尤其不是主键 ID。锁类型细节可查 https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html。
把等待关系转成修复清单
还原后先检查两条业务路径是否反向访问同一组资源。若 A 路径先锁 RA 后锁 RB,B 路径反过来,可评估统一访问顺序;但 SQL 书写顺序不是访问路径的全部,索引选择、触发器、外键与批量扫描也需要考虑。缩短事务、减少无关扫描、避免持锁等待外部服务,通常比盲目延长超时时间更针对问题。
收到死锁回滚后,应用应按完整事务边界重试,而不是只重新执行最后一条 SQL。重试需要次数上限、退避和幂等保护;事务外的付款、消息等副作用不能不加判断地再执行。锁等待超时的回滚范围与死锁并不总相同,不能共用一个粗略的错误处理假设。
| 现有证据 | 可得结论 | 仍需补充 |
|---|---|---|
| 匹配资源和不兼容锁模式 | 确定等待依赖 | 此前如何获得锁 |
| 回滚事务标记 | 确定引擎选择的牺牲方 | 业务根因与影响 |
| 当前等待表有记录 | 存在当前数据锁阻塞 | 是否形成环及其历史 |
| 只看到当前 SQL | 知道等待时在做什么 | 完整事务路径与索引资源 |
两个事务访问不同业务行为何也会死锁?
业务行不等于完整锁资源。二级索引、范围间隙、约束检查等也可能参与冲突;应以报告实际索引及锁模式为线索。
把隔离级别改成 READ COMMITTED 就没事吗?
不能保证。它可能改变部分锁行为,但死锁不只来自间隙锁。应评估业务一致性要求,不能把降低隔离级别当作默认修复。
为什么日志只给出一部分持有锁?
死锁报告用于说明相关冲突,并不是完整事务历史或全部持锁清单。缺少先前语句时,需要关联应用日志;不能从缺失信息推断“事务没有其他锁”。
最小可复用配方就是:保存同一份完整报告,列事务,分持有与请求,匹配资源及锁模式,再把请求方与阻塞方逐条记录。没有证据的边保留空白,通常比一张看似完整但方向错误的等待图更有用。
MySQL 事务隔离级别怎样影响一致性读
- 上一篇
- MySQL 事务隔离级别怎样影响一致性读
- 下一篇
- MySQL 在线 DDL 怎样评估元数据锁风险
-
- 数据库 · MySQL | 1小时前 |
- MySQL Performance Schema 怎样找最慢摘要
- 150浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL GTID 迁移怎样避免跳过事务
- 285浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 连接池耗尽怎样从线程状态定位
- 369浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 复制延迟怎样区分 IO 线程和 SQL 线程
- 254浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 分区表怎样选择分区键
- 495浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 在线 DDL 怎样评估元数据锁风险
- 216浏览 收藏
-
- 数据库 · MySQL | 1小时前 | MySQL · 事务 · InnoDB · Serializable READ COMMITTED REPEATABLE READ MySQL事务隔离级别 一致性读 InnoDB快照
- MySQL 事务隔离级别怎样影响一致性读
- 317浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL JSON_TABLE 的 EXISTS PATH 怎么区分字段缺失和 JSON null
- 124浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL 窗口函数怎样取每组最新一条
- 275浏览 收藏
-
- 数据库 · MySQL | 1小时前 |
- MySQL JSON_TABLE 展开嵌套数组的列定义与空值处理
- 335浏览 收藏
-
- 数据库 · MySQL | 10小时前 | MySQL ·
- MySQL NDB管理节点怎么查看数据节点状态
- 474浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 466次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 529次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 546次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 497次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 317次使用
-
- MySQL JSON_TABLE 展开数组时如何保留缺失字段
- 2026-09-10 501浏览
-
- MySQL 分区表怎么处理跨分区唯一键:分区列约束与建表取舍
- 2026-08-30 501浏览
-
- MySQL权限管理设置全攻略
- 2026-03-29 501浏览
-
- MySQL分片实现方法及常见方案解析
- 2025-06-24 501浏览
-
- MySQL表空间碎片怎么清理?超详细优化教程
- 2025-06-13 501浏览

