当前位置:首页 > 文章列表 > 数据库 > 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 用户事务死锁,输出中的 TRANSACTION、WAITING FOR THIS LOCK、HOLDS 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_NAME、LOCK_MODE、LOCK_STATUS 与 LOCK_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_NAME 和 LOCK_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;

常见修复是让多个事务按相同顺序访问多张表或多个范围、缩短事务持续时间、为 UPDATE 和 SELECT ... 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 Deadlocks、How 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推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    633次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    670次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    706次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    667次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    506次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码