当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 死锁日志里的锁类型和索引名怎么对应到 SQL

MySQL 死锁日志里的锁类型和索引名怎么对应到 SQL

来源:17golang原创 2026-09-08 07:13:03 0浏览 收藏

MySQL 死锁日志里的 index 不是 SQL 文本中的表别名,lock mode 也不是“某条 SQL 的类型”。正确的对应方式是:先用事务 ID 找到正在执行的语句,再用表名和索引名判断 InnoDB 锁住了哪棵索引,最后用 lock_data 对照 WHERE 条件和主键值。这样才能知道是两条 SQL 访问顺序相反,还是范围锁把相邻记录也纳入了等待。

看到 RECORD LOCKS ... index PRIMARY 时,先把它理解为“某张表的聚簇索引记录锁”;看到二级索引名时,要同时考虑该索引记录后附带的主键值。死锁诊断的重点不是逐字翻译日志,而是还原“谁持有什么、谁还要什么”。
要点速览
  • SHOW ENGINE INNODB STATUS 主要看最近一次死锁;频繁问题可打开 innodb_print_all_deadlocks 记录全部事件。
  • INDEX_NAME 指向锁所在索引,LOCK_TYPE 区分 TABLE/RECORD,LOCK_STATUS 区分 GRANTED/WAITING。
  • 二级索引锁的记录值通常还带主键;不要只凭索引名猜 SQL,必须结合事务语句、索引定义和执行条件。

先把日志字段翻译成锁对象

InnoDB 一行死锁记录通常同时出现表、索引、锁模式和记录值。表名回答“锁在哪张表”,索引名回答“通过哪棵索引定位到锁记录”,锁类型和状态回答“这是表级资源还是记录级资源、当前已持有还是正在等待”。例如 index PRIMARY 表示聚簇索引;index idx_account_status 则表示访问路径落在二级索引上。

字段怎么理解回到 SQL 时看什么
TABLE / RECORD表级或记录级锁是否由 DDL、LOCK TABLES 或行修改触发
PRIMARY / 二级索引名锁所在的索引索引列顺序、是否覆盖 WHERE 条件
S、X、IS、IX、GAP共享、排他、意向或间隙相关模式SELECT 加锁方式、UPDATE/DELETE 和范围条件
GRANTED / WAITING已持有或正在等待把等待资源连到另一事务持有的同一资源
LOCK_DATA索引记录值或间隙标识主键、二级索引列和 WHERE 的具体值
MySQL InnoDB 死锁诊断框图将事务、SQL、表、索引、记录和锁状态对应起来
图1:把事务和 SQL 放在请求边界,把表、索引、记录与锁状态放在 InnoDB 资源边界,日志字段才能对应到同一个锁对象。

用最近一次死锁记录锁定两条 SQL

先执行下面的语句。它只展示最近一次 InnoDB 用户事务死锁,输出中的 TRANSACTIONWAITING FOR THIS LOCKHOLDS THE LOCK(S)WE ROLL BACK TRANSACTION 是诊断主线。

-- 读取最近一次 InnoDB 死锁摘要,不修改事务数据
SHOW ENGINE INNODB STATUS\G

把每个事务分成两列记录:已持有的资源、正在等待的资源。若事务 A 持有 orders.PRIMARY 的某条记录,同时等待 payments.PRIMARY;事务 B 的方向相反,就已经得到典型的交叉等待。日志里的 SQL 是当时正在执行的语句,但它不一定包含完整业务参数,所以还要用连接线程、应用日志或请求 ID补全实际值。

如果现场经常发生,临时打开全部死锁记录:

-- 仅在排查期打开,便于从错误日志收集每一次死锁
SET GLOBAL innodb_print_all_deadlocks = ON;

-- 排查结束后关闭,避免长期增加日志噪声
SET GLOBAL innodb_print_all_deadlocks = OFF;

用 data_locks 把索引名和记录值补齐

死锁发生前后,Performance Schema 的锁表更适合看结构化字段。data_locks 同时包含已授予和等待中的数据锁;INDEX_NAMELOCK_MODELOCK_STATUSLOCK_DATA 正好对应日志中最容易误读的部分。

-- 先按事务、表和索引缩小范围,再看记录与状态
SELECT ENGINE_TRANSACTION_ID,
       OBJECT_SCHEMA,
       OBJECT_NAME,
       INDEX_NAME,
       LOCK_TYPE,
       LOCK_MODE,
       LOCK_STATUS,
       LOCK_DATA
FROM performance_schema.data_locks
WHERE OBJECT_SCHEMA = 'shop'
  AND OBJECT_NAME IN ('orders', 'payments')
ORDER BY ENGINE_TRANSACTION_ID, OBJECT_NAME, INDEX_NAME;

-- 查看谁持有锁、谁在等待该锁
SELECT requesting_engine_transaction_id,
       blocking_engine_transaction_id,
       requesting_engine_lock_id,
       blocking_engine_lock_id
FROM performance_schema.data_lock_waits;

这里有三个关键边界。第一,表级意向锁的 INDEX_NAMELOCK_DATA 可能为空,不要把它当成缺失索引。第二,二级索引记录的 LOCK_DATA 通常包含二级索引值并附带主键,用主键回表确认具体行。第三,supremum pseudo-record 表示索引页上的特殊上界记录,常见于范围或间隙相关诊断,不能当成业务主键。

MySQL data_locks 查询结构图展示表名、索引名、锁模式、记录值与等待关系如何回到 SQL 条件
图2:结构化锁表把表、索引、模式、状态和记录值连到等待关系,之后再回到 SQL 的 WHERE 与事务顺序。

从索引记录回到 SQL,修正访问顺序

拿到索引名后先查索引定义,而不是直接改隔离级别。假设日志指向 idx_account_status,就检查它的列顺序是否覆盖了业务条件:

-- 查看索引列顺序,确认日志中的索引如何匹配条件
SHOW CREATE TABLE orders\G

-- 只取需要加锁的行,保持两个事务使用同一访问顺序
START TRANSACTION;
SELECT id, status
FROM orders
WHERE account_id = 42 AND status = 'pending'
FOR UPDATE;
-- 业务更新完成后再提交,避免长时间占锁
COMMIT;

常见修复是让多个事务按相同顺序访问多张表或多个范围、缩短事务持续时间、为 UPDATESELECT ... FOR UPDATE 的条件建立合适索引,并在应用层对死锁回滚做有限次数重试。隔离级别会影响读操作的可见性,但不能把“死锁只靠调低隔离级别解决”当成结论;真正要复查的是锁定范围、索引路径和事务顺序。

常见问题

日志里的索引名就是 SQL 使用的唯一索引吗?

不一定。它表示 InnoDB 记录锁所在的索引;没有显式主键时也可能看到内部聚簇索引。应结合 SHOW CREATE TABLE 和执行计划确认访问路径。

为什么 LOCK_DATA 会是 NULL?

表级锁本来没有记录值;记录页不在缓冲池时,InnoDB 也可能不为诊断重新读盘。NULL 不能单独证明没有锁住具体行。

遇到死锁只要把 innodb_lock_wait_timeout 调大吗?

不建议。死锁检测开启时 InnoDB 会回滚一个事务,应用仍应捕获回滚并有限重试;应先修正事务顺序和锁定范围。

相关依据

字段含义可查阅 MySQL 8.4 的data_locks 表说明Performance Schema 锁表概览;死锁诊断与处理可查阅InnoDB DeadlocksHow to Minimize and Handle Deadlocks。生产环境修改全局变量前,应结合日志保留策略和权限范围安排排查窗口。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go os/exec 执行外部命令时怎么安全传递带空格参数Go os/exec 执行外部命令时怎么安全传递带空格参数
上一篇
Go os/exec 执行外部命令时怎么安全传递带空格参数
Go recover 在 defer 中返回后 named result 如何避免静默成功
下一篇
Go recover 在 defer 中返回后 named result 如何避免静默成功
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    19次使用
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    177次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    111次使用
  • AI Prompt Library:免费AI提示词库,助力ChatGPT高效创作与营销
    AI Prompt Library
    探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
    38次使用
  • Generrated:DALL·E 2/3 AI绘画提示词灵感库与图像对比平台
    Generrated
    Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
    18次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码