MySQL的index merge(索引合并)导致数据库死锁分析与解决方案 | 京东云技术团队
背景
在DBS-集群列表-更多-连接查询-死锁中,看到9月22日有数据库死锁日志,后排查发现是因为mysql的优化-index merge(索引合并)导致数据库死锁。
定义
index merge(索引合并):该数据库查询优化的一种技术,在mysql 5.1之后进行引入,它可以在多个索引上进行查询,并将结果合并返回。
mysql数据库的锁机制
在排查问题之前,首先讲一下mysql数据库的锁机制:
1 加锁的基本单位是 next-key lock(记录锁+间隙锁),当记录锁或者间隙锁能够解决幻读的问题,就会退化为记录锁(行锁),间隙锁。
2 加锁是将锁加在了索引之上,而不是数据之上。
3 对于当前读,索引进行加锁,当前读语句包括了(select … from. … for update,select…from … lock in share mode,update…,delete…)。
4 加锁根据唯一性索引、非唯一性索引进行了区分,根据查询条件分为了等值查询、范围查询,根据是否能够查到数据又分为了记录存在和不存在的情况。
本次死锁问题使用的索引是非唯一性索引的等值查询中记录存在的情况,因此本文仅仅详细介绍这种情况,其它情况可以查看最下面的参考文档1:
加锁情况是:会依次扫描,首先扫描到条件匹配的数据,加一个next-key lock,然后接下来扫描到第一个记录不匹配的数据,增加一个间隙锁,最后对查到记录的主键增加一个记录锁,
针对以上情况加了三种锁,加锁的目的是为了防止幻读的发生。
针对二级索引的锁进行分析:
表结构:
CREATE TABLE `jdi_roster_apply_detail` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`apply_id` varchar(100) NOT NULL COMMENT '申请单号',`status` tinyint(10) NOT NULL COMMENT '状态',PRIMARY KEY (`id`),KEY `idx_status` (`status`),KEY `idx_apply_id` (`apply_id`)
) ENGINE=InnoDB AUTO_INCREMENT=984483 DEFAULT CHARSET=utf8 COMMENT='黑白名单申请单明细'
表数据:
| id | apply_id | status |
|---|---|---|
| 959651 | 1695369220522068998 | 1 |
| 960738 | 1695369227576173690 | 1 |
| 961319 | 1695373047673903326 | 1 |
| 961365 | 1695373122447865228 | 1 |
通过 idx_apply_id建立的b+树:

因为索引是二级索引,所以叶子节点存储的数据是主键值。
执行sql:
select * from jdi_roster_apply_detail where apply_id='1695369227576173690' for update
执行数据扫描过程
1 查到符合条件的记录,增加next-key 锁,因此锁是(1695369220522068998,1695369227576173690]
2 找到第一个不符合记录的数据增加间隙锁,因此锁是 (1695369227576173690,1695373047673903326)
3 对符合条件的主键索引增加记录锁,因此对 id=960738,增加记录锁。
针对三种锁解决的幻读:
1 如果没有第一条的next-key锁, 另一个事务增加一个apply_id=1695369227576173690, id<960738 时,该事务在进行查询时,会多一条记录,因此会造成幻读。
2 如果没有第二条的 间隙锁,另一个事务增加一个apply_id=1695369227576173690, id>960738是,该事务在进行查询时,会多一条记录,因此会造成幻读。
3 如果没有第三条的记录锁,另一条事务删除一条 id=960738的记录,该事务进行查询时,会少一条数据,因此会造成幻读。
实际问题分析
数据库死锁日志

以上日志两个事务分别执行了update语句:
#事务1
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369220522068998'
#事务2
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369227576173690'
这个sql是用于将某个申请单id待审批的数据改为已审批。
因为在泰山里不能执行update语句 ,因此执行了select语句查看用的索引情况:
explain select * from jdi_roster_apply_detail where `status` = 1 and apply_id = '1695369220522068998'
执行的结果:

通过结果可以看出两个update语句都使用了两个索引,分别是idx_status,idx_apply_id,然后将查到的结果进行合并,因此在模拟的过程中,可以将其拆成两个查询语句。
死锁模拟
| 事务1 | 事务2 | 锁的范围 |
|---|---|---|
| begin | begin | |
| select * from jdi_roster_apply_detail where apply_id = ‘1695369220522068998’ for update | idx_apply_id所以锁住了(-∞,1695369220522068998],(1695369220522068998,1695369227576173690) 主键id索引锁住了 id=959651 | |
| select * from jdi_roster_apply_detail where apply_id = ‘1695369227576173690’ for update | idx_apply_id所以锁住了(1695369220522068998,1695369227576173690],(1695369227576173690,1695373047673903326) 主键id索引锁住了 id=960738 | |
| select * from jdi_roster_apply_detail where status = 1 for update | 会对idx_status上加next-key锁和间隙锁,但是在对主键959651,960738,961319,961365进行加记录锁时,其中事务2 对960738已经加了记录锁,所以该事务1进行了阻塞。 | |
| select * from jdi_roster_apply_detail where status = 1 for update | 会对idx_status上加next-key锁和间隙锁,但是在对主键959651,960738,961319,961365进行加记录锁时,其中事务1对959651已经加了记录锁,所以该事务2进行了阻塞。 | |
| deadlock |
两个事务分别想要两个主键id的记录锁,造成相互等待,形成了死锁。
以上是先执行idx_apply_id的索引查询再执行idx_status索引查询,如果先执行idx_status索引查询,再执行idx_apply_id的索引查询,也会因为主键的记录锁造成死锁。
解决方案
1 利用force index(idx_apply_id)强制走某个索引,这样InnoDB就会忽略index merge,避免多个索引同时加锁的情况。
2 禁用Index Merge,用命令禁用Index Merge:SET GLOBAL optimizer_switch=‘index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off’;
3 Index Merge同时使用了2个独立索引,因此新建一个包含这两个索引所有字段的联合索引,这样InnoDB就只会走这个单独的联合索引。
第三种方案相较于第一种查询性能更好,相对于第二种仅仅作用于该表,影响范围小,因此本次也是采用了该方案。
总结
该死锁问题是因为优化器使用了合并索引问题导致的,最终通过新建一个联合索引来解决这个问题。
参考文档:
1 https://www.xiaolincoding.com/mysql/lock/how_to_lock.html
作者:京东工业 李小辉
来源:京东云开发者社区 转载请注明来源
相关文章:
MySQL的index merge(索引合并)导致数据库死锁分析与解决方案 | 京东云技术团队
背景 在DBS-集群列表-更多-连接查询-死锁中,看到9月22日有数据库死锁日志,后排查发现是因为mysql的优化-index merge(索引合并)导致数据库死锁。 定义 index merge(索引合并):该数据库查询优化的一种技术࿰…...
第四章 网络层 | 计算机网络(谢希仁 第八版)
文章目录 第四章 网络层4.1 网络层提供的两种服务4.2 网际协议IP4.2.1 虚拟互连网络4.2.2 分类的IP地址4.2.3 IP地址与硬件地址4.2.4 地址解析协议ARP4.2.5 IP数据报的格式4.2.6 IP层转发分组的流程 4.3 划分子网和构造超网4.3.1 划分子网4.3.2 使用子网时分组的转发4.3.3 无分…...
课题学习(八)----卡尔曼滤波动态求解倾角、方位角
一、 卡尔曼滤波 卡尔曼滤波的应用要求系统和底层过程的测量模型都是线性的。离散时间线性状态空间系统的描述为: x k Φ k , k − 1 x k − 1 G k − 1 w k − 1 x_k\Phi_{k,k-1}x_{k-1}G_{k-1}w_{k-1} xkΦk,k−1xk−1Gk−1wk−1 式中 Φ k , k − 1 \Phi_{…...
仿真软件Proteus8.9 SP2 Pro 下载、安装、汉化详细图文教程
Proteus8.9 安装教程 视频教程一、安装软件解压二、软件安装常见问题及解决方法:三、汉化 Proteus8.9 SP2 Pro 安装教程 本破解教程仅供个人及 proteus 8.9粉丝们交流学习之用,请勿用于商业用途, 谢谢支持。此版本为Proteus8.9 SP2 Pro。其他…...
振弦传感器和无线振弦采集仪在隧道安全监测的解决方案
振弦传感器和无线振弦采集仪在隧道安全监测的解决方案 隧道作为交通工程的重要组成部分,具有极高的安全风险,因此隧道安全监测是必不可少的。振弦传感器和无线振弦采集仪作为隧道安全监测的两种重要设备,能够有效地监测隧道的振动情况&#…...
c# xml 参数读取的复杂使用
完整使用2 生产厂家里面包含很多规格型号,一个规格型号里面包含很多出厂序列号,点击下一步如果检测到填充的和保存的不一样 就新增一条(如检测到生产厂家相同,但是规格型号不同,就新增一组规格型号)。 界面一:新增界面 界面2 删除界面 界面一:新增界面 load 其中…...
在Mac中使用 brew services start redis 命令启动、停止Redis服务报错
一、问题现象 启动Redis服务命令: brew services start redis异常信息如下: Error: uninitialized constant Homebrew::Service::System /opt/homebrew/Library/Homebrew/macos_version.rb:150:in const_missing /opt/homebrew/Library/Taps/homebrew…...
iapp源码-----比较经典
2.0底部菜单导航栏.rar: https://url18.ctfile.com/f/7715018-958700751-6096bd?p6511 (访问密码: 6511) 2.0涟漪_拖动条控制音乐播放.rar: https://url18.ctfile.com/f/7715018-958700754-4cec13?p6511 (访问密码: 6511) 2.0手电筒.rar: https://url18.ctfile.com/f/7715018…...
为什么手机会莫名多出许多软件?
许多手机用户都曾遭遇过这样的问题,他们在使用手机的过程中,突然发现手机屏幕上出现了一些未知的软件。这些软件并非他们主动下载的,但它们却显现在屏幕上。这些软件从何而来? 其实,这些软件往往是在浏览网页、阅读小…...
测试自动化的边缘:DevTestOps 和 DevSecOps
什么是 DevOps? DevOps 允许企业通过自动化基础设施、工作流程和持续测量应用程序的性能来提高开发人员和运营团队之间的协作和生产力。通过 DevOps,开发人员可以以小块的形式编写代码,以便在几个小时内集成、测试、监控和部署代码ÿ…...
fatal:Could not read from remote repository解决方法
Linux服务器如何连接GitHub? 生成SSH密钥 ssh-keygen -C “邮箱” -t rsa 存放位置一般是/root/.ssh/id_rsa 登录个人github,添加客户端生成的公钥 打开Settings,点击SSH and GPG keys,点击New SSH Key。Key中粘贴id_rsa.pub…...
数学基础
线性代数 关键词:线性方程组、矩阵、增广矩阵(系数矩阵、常数项矩阵)、阶梯型矩阵、行最简矩阵、最简形矩阵、向量系统、向量加法、向量空间、基本单位向量、线性相关、线性无关、Span张成空间、 向量乘法(点积、内积、外积、叉积…...
【Python】Python语言基础(上)
第一章 前言 1. Python简介 Python语言并不是新的语言,它早于HTTP 1.0协议5年,早于Java语言 4年。 Python是由荷兰人Guido van Rossum(吉多范罗苏姆)于1989年圣诞节期间在阿姆斯特丹休假时为了打发无聊的假期而编写的一个脚本…...
C#设计模式六大原则之依赖倒置原则
C#设计模式六大原则是单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则。它们不是要我们刻板的遵守,而是根据实际需要灵活运用。只要对它们的遵守程度在一个合理的范围内,努为做到一个良好的设计。以下介绍C#依赖倒置原则…...
IDEA的使用(二)快捷键 (IntelliJ IDEA 2022.1.3版本)
1. IDEA中的常用快捷键 1.1 通用型快捷键 1.2 提高编写速度 ctrl shift ↑或↓ 只能在方法里面移动代码。 alt shift ↑或↓ 可以向方法外移动代码。 设置过自动导包,所以不用批量导包啦。 1.3 类结构、查找和查看源码 1.4 查找、替换和关闭 1.5 调整格式 1.6 De…...
微信小程序个人账号申请和配置详细教程
一、注册小程序管理账号 1、注册方法 在微信公众平台官网首页(mp.weixin.qq.com),点击右上角的“立即注册”按钮。 2、选择注册的账号类型 选择“小程序”,点击“查看类型区别”可查看不同类型账号的区别和优势。 3、填写邮箱和…...
opencv定位图片中的图案?
import cv2 as cv2def find_positions(image_path, small_image_path):# 读取大图和小图large_image cv2.imread(image_path)small_image cv2.imread(small_image_path)# 小图规格small_image_h, small_image_w small_image.shape[:2]# 对比大图与小图# 匹配模板res cv2.ma…...
高防CDN:网络安全的不可或缺之选
在当今数字化时代,网络攻击已经成为互联网上的一种不可避免的风险。为了应对不断升级的网络威胁,许多企业和组织正在采用高防御CDN(Content Delivery Network)技术,以确保他们的在线资产得到保护,用户体验得…...
flutter 常用组件:文本、图片和按钮
文章目录 文本控件富文本控件图片本地图片网络图片按钮文本控件 ##一’码’当先 Text(这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本这是一段文本,textAlign:TextAlign.center,style: TextStyle(fontWeight: FontWeight.bold, font…...
BI工具:让数据分析井然有序一望而知
BI(Business Intelligence)工具是一类专门用于数据分析和决策支持的软件工具。 它们能够将企业内部和外部的数据进行整合、处理和可视化,帮助用户从海量数据中获取有价值的见解和洞察,并以直观、易懂的方式展示给决策者和相关人员…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
