MySQL优化index merge引起的死锁怎么解决

背景

生产环境出现死锁流水,通过查看死锁日志,看到造成死锁的是两条一样的update语句(只有where条件中的值不同),

如下:

UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0;UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0;

一开始比较费解,通过大量查询跟学习后,分析出了死锁形成的具体原理,特分享给大家,希望能帮助到遇到同样问题的朋友。

因为MySQL知识点较多,这里对很多名词不进行过多介绍,有兴趣的朋友,可以后续进行专项深入学习。

死锁日志

*** (1) TRANSACTION:TRANSACTION 791913819, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999mysql tables in use 3, locked 3LOCK WAIT 4 lock struct(s), heap size 1184, 3 row lock(s)MySQL thread id 462005230, OS thread handle 0x7f55d5da3700, query id 2621313306 x.x.x.x test_user Searching rows for updateUPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0;*** (1) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913819 lock_mode X waitingRecord lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0*** (2) TRANSACTION:TRANSACTION 791913818, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999mysql tables in use 3, locked 35 lock struct(s), heap size 1184, 4 row lock(s)MySQL thread id 462005231, OS thread handle 0x7f55cee63700, query id 2621313305 x.x.x.x test_user Searching rows for updateUPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0;*** (2) HOLDS THE LOCK(S):RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913818 lock_mode XRecord lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0*** (2) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 110 page no 41569 n bits 88 index `PRIMARY` of table `test`.`test_table` trx id 791913818 lock_mode X locks rec but not gap waitingRecord lock, heap no 14 PHYSICAL RECORD: n_fields 30; compact format; info bits 0*** WE ROLL BACK TRANSACTION (1)

简要分析下上边的死锁日志:

1、第一块内容(第1行到第9行)中,第6行为事务(1)执行的SQL语句,第7和第8行意思为事务(1)在等待 idx_status 索引上的X锁;

2、第二块内容(第11行到第19行)中,第16行为事务(2)执行的SQL语句,第17和第18行意思为事务(2)持有 idx_status 索引上的X锁;

意思为:事务(2)正在等待在 PRIMARY 索引上获取 X 锁。(but not gap指不是间隙锁)

4、最后一句的意思即为,MySQL将事务(1)进行了回滚操作。

表结构

CREATE TABLE `test_table` (`id` int(11) NOT NULL AUTO_INCREMENT,`trans_id` varchar(21) NOT NULL,`status` int(11) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uniq_trans_id` (`trans_id`) USING BTREE,KEY `idx_status` (`status`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

通过表结构可以看出,trans_id 列上有一个唯一索引uniq_trans_id status 列上有一个普通索引idx_status ,id列为主键索引 PRIMARY

InnoDB引擎中有两种索引:

聚簇索引: 将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。

辅助索引: 辅助索引叶子节点存储的是主键值,也就是聚簇索引的键值。

主键索引 PRIMARY 就是聚簇索引,叶子节点中会保存行数据。uniq_trans_id 索引和idx_status 索引为辅助索引,叶子节点中保存的是主键值,也就是id列值。

当我们通过辅助索引查找行数据时,先通过辅助索引找到主键id,再通过主键索引进行二次查找(也叫回表),最终找到行数据。

执行计划

MySQL优化index merge引起的死锁怎么解决

通过看执行计划,可以发现,update语句用到了索引合并,也就是这条语句既用到了 uniq_trans_id 索引,又用到了 idx_status 索引,Using intersect(uniq_trans_id,idx_status)的意思是通过两个索引获取交集。

为什么会用 index_merge(索引合并)

MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。

如执行计划中的语句:

UPDATE test_table SET `status` = 1 WHERE `trans_id` = '38' AND `status` = 0 ;

MySQL会根据 trans_id = ‘38’这个条件,利用 uniq_trans_id 索引找到叶子节点中保存的id值;同时会根据 status = 0这个条件,利用 idx_status 索引找到叶子节点中保存的id值;然后将找到的两组id值取交集,最终通过交集后的id回表,也就是通过 PRIMARY 索引找到叶子节点中保存的行数据。

这里可能很多人会有疑问了,uniq_trans_id 已经是一个唯一索引了,通过这个索引最终只能找到最多一条数据,那MySQL优化器为啥还要用两个索引取交集,再回表进行查询呢,这样不是多了一次 idx_status 索引查找的过程么。我们来分析一下这两种情况执行过程。

第一种 只用uniq_trans_id索引 :

根据 trans_id = ‘38’查询条件,利用uniq_trans_id 索引找到叶子节点中保存的id值;

通过找到的id值,利用PRIMARY索引找到叶子节点中保存的行数据;

再通过 status = 0 条件对找到的行数据进行过滤。

第二种 用到索引合并 Using intersect(uniq_trans_id,idx_status)

根据 trans_id = ‘38’ 查询条件,利用 uniq_trans_id 索引找到叶子节点中保存的id值;

根据 status = 0 查询条件,利用 idx_status 索引找到叶子节点中保存的id值;

将1/2中找到的id值取交集,然后利用PRIMARY索引找到叶子节点中保存的行数据

上边两种情况,主要区别在于,第一种是先通过一个索引把数据找到后,再用其它查询条件进行过滤;第二种是先通过两个索引查出的id值取交集,如果取交集后还存在id值,则再去回表将数据取出来。

当优化器认为第二种情况执行成本比第一种要小时,就会出现索引合并。(生产环境流水表中 status = 0 的数据非常少,这也是优化器考虑用第二种情况的原因之一)。

为什么用了 index_merge 就死锁了

MySQL优化index merge引起的死锁怎么解决

上面简要画了一下两个update事务加锁的过程,从图中可以看到,在idx_status 索引和 PRIMARY (聚簇索引) 上都存在重合交叉的部分,这样就为死锁造成了条件。

如,当遇到以下时序时,就会出现死锁:

MySQL优化index merge引起的死锁怎么解决

事务1等待事务2释放锁,事务2等待事务1释放锁,这样就造成了死锁。

MySQL检测到死锁后,会自动回滚代价更低的那个事务,如上边的时序图中,事务1持有的锁比事务2少,则MySQL就将事务1进行了回滚。

解决方案

一、从代码层面

where 查询条件中,只传 trans_id ,将数据查询出来后,在代码层面判断 status 状态是否为0;

使用 force index(uniq_trans_id) 强制查询语句使用 uniq_trans_id 索引;

where 查询条件后边直接用 id 字段,通过主键去更新。

二、从MySQL层面

删除 idx_status 索引或者建一个包含这俩列的联合索引;

将MySQL优化器的index merge优化关闭。

以上就是MySQL优化index merge引起的死锁怎么解决的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/159219.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
win10怎么开启存储感知功能_win10开启存储感知功能设置教程
上一篇 2025年12月5日 08:07:52
无锡半导体装备与关键零部件创新中心启用
下一篇 2025年12月5日 08:09:56

相关推荐

  • MySQL如何实现数据的实时备份_有哪些高效工具和方法?

    mysql 实时备份主要依赖主从复制、二进制日志(binlog)配合增量备份,以及借助专业工具实现自动化监控与恢复。一、主从复制通过将主库数据变更同步到从库实现“准实时”备份,但存在延迟风险,建议开启 gtid 模式提升一致性;二、结合 binlog 与定时归档实现可回溯的增量备份,配合全量备份可恢…

    2026年9月21日
    000
  • SpringBoot的定时任务

    SpringBoot的定时任务SpringBoot的定时任务SpringBoot的定时任务SpringBoot的定时任务

    大家好,我是你们的老朋友全栈君。我们又见面了。 一、基于注解(@Scheduled)的定时任务 使用SpringBoot的@Scheduled注解来创建定时任务非常简单,只需几行代码就能实现。然而,@Scheduled默认是单线程运行,这意味着当启动多个任务时,一个任务的执行时间可能会影响到下一个任…

    2026年9月21日 用户投稿
    400
  • MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    mysql原生全文搜索功能存在明显局限,需结合外部搜索引擎才能满足复杂需求。1. mysql全文搜索适用于小数据量、简单查询场景,但分词能力弱,尤其对中文支持差,查询功能有限,无法实现模糊查询、纠错等高级功能,且性能随数据量增长显著下降。2. 外部搜索引擎如elasticsearch(es)和sph…

    2026年9月21日 用户投稿
    000
  • MySQL慢查询到底是什么_怎样快速定位并修复它?

    MySQL慢查询到底是什么_怎样快速定位并修复它?MySQL慢查询到底是什么_怎样快速定位并修复它?MySQL慢查询到底是什么_怎样快速定位并修复它?MySQL慢查询到底是什么_怎样快速定位并修复它?

    mysql慢查询可通过开启日志、分析日志和针对性优化快速定位修复。具体步骤:1. 修改配置文件或使用命令开启慢查询日志并设置阈值;2. 利用mysqldumpslow或pt-query-digest工具分析日志内容,找出耗时sql;3. 针对常见原因如缺少索引、sql写法不合理、数据量过大、锁竞争及…

    2026年9月21日 用户投稿
    000
  • MySQL如何处理长时间运行的查询_避免数据库阻塞?

    MySQL如何处理长时间运行的查询_避免数据库阻塞?MySQL如何处理长时间运行的查询_避免数据库阻塞?MySQL如何处理长时间运行的查询_避免数据库阻塞?MySQL如何处理长时间运行的查询_避免数据库阻塞?

    诊断mysql慢查询需1.开启慢查询日志并设置long_query_time;2.使用explain分析sql执行情况;3.借助工具如pt-query-digest分析日志。优化涉及1.确保join字段有索引;2.优化join顺序及减少join表数;3.使用临时表、批量处理和数据分区。防止阻塞应1.…

    2026年9月21日 用户投稿
    000
  • PHP/MySQL:高效合并订单商品并按日期分组显示

    本教程将指导如何在PHP/MySQL应用中,将同一日期的订单商品合并显示在同一行,以提高数据展示的清晰度。核心解决方案是利用MySQL的GROUP_CONCAT函数在数据库层面进行高效聚合,避免复杂的PHP逻辑处理,从而简化代码并优化性能。 订单数据展示的常见挑战 在开发在线购物平台时,通常需要向用…

    2026年9月21日
    100
  • MySQL数据库如何支持多租户业务_设计策略与实现?

    MySQL数据库如何支持多租户业务_设计策略与实现?MySQL数据库如何支持多租户业务_设计策略与实现?MySQL数据库如何支持多租户业务_设计策略与实现?MySQL数据库如何支持多租户业务_设计策略与实现?

    mysql 支持多租户架构的关键在于选择合适的数据隔离策略,并兼顾性能与运维管理。1. 常见方式包括共享数据库共享表(资源利用率高但隔离性差)、共享数据库独立表(平衡隔离性与维护成本)和独立数据库(隔离性强但管理复杂)。2. 租户识别需在请求前确定租户id,并自动附加到sql查询中,可通过视图或中间…

    2026年9月21日 用户投稿
    000
  • MySQL 大型历史数据表结构设计与优化指南

    本文旨在为处理大量客户历史交易数据的MySQL数据库设计提供专业指导。我们将探讨如何构建高效、可扩展的表结构,重点关注主键设计、数据分区、实时数据摄入以及性能优化策略,以确保系统能够稳定支持百万级乃至亿级数据量的查询需求。 MySQL大型历史数据表结构设计与优化 在处理大量历史数据,特别是涉及到多用…

    2026年9月21日
    000
  • MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录

    MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录MySQL重复数据检测与清理逻辑_Sublime脚本批量处理历史冗余记录

    处理mysql重复数据的核心步骤是识别并清理,可使用group by或窗口函数定位重复项,再通过分批删除或倒腾法安全清理;sublime text可用于高效生成和编辑sql语句。1. 识别重复数据常用group by+having或row_number()窗口函数;2. 清理策略包括分批删除、使用临…

    2026年9月21日 用户投稿
    100
  • MySQL自动化性能测试方案_MySQL持续监控调优数据库效率

    MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率MySQL自动化性能测试方案_MySQL持续监控调优数据库效率

    mysql自动化性能测试和持续监控的核心在于构建闭环反馈系统,包含模拟真实负载、全面数据采集、自动化执行与分析、数据驱动的持续调优四大环节。①测试环境需与生产一致并隔离,使用docker、虚拟机或云沙盒,解决数据同步与脱敏问题;②负载生成工具如sysbench、jmeter、locust或自定义脚本…

    2026年9月21日 用户投稿
    200
  • MySQL数据库如何设计适合大数据量的表结构_案例分析?

    MySQL数据库如何设计适合大数据量的表结构_案例分析?MySQL数据库如何设计适合大数据量的表结构_案例分析?MySQL数据库如何设计适合大数据量的表结构_案例分析?MySQL数据库如何设计适合大数据量的表结构_案例分析?

    设计适合大数据量的mysql表结构,核心在于数据类型选对、索引用好、适当拆分。1. 合理选择字段类型,如根据数据范围选用tinyint/smallint代替bigint,固定值字段用enum类型,大文本字段单独拆表;2. 精准建立索引,高频查询字段建联合索引并遵循最左前缀原则,避免低区分度字段建索引…

    2026年9月21日 用户投稿
    100
  • Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担

    Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担Sublime开发MySQL存储过程教程实战_封装重复逻辑减少前端负担

    在web开发中使用mysql存储过程能有效封装逻辑并减少前端负担,本文介绍了其优势、环境配置及实战技巧。一、存储过程的优势包括减少网络传输、提高性能、统一业务逻辑;二、sublime text配置步骤为安装package control、sublimerepl插件、sql语法高亮插件,并建议新建.s…

    2026年9月21日 用户投稿
    900
  • mysql如何排查排序异常

    排查MySQL排序异常需先确认ORDER BY是否生效,检查子查询、UNION及应用层逻辑是否覆盖排序;通过EXPLAIN分析是否使用索引排序,避免Using filesort;确保字段类型、字符集和排序规则(collation)符合预期,处理NULL值和大小写敏感性;关注sort_buffer_s…

    2026年9月21日
    000
  • avg计算平均值在mysql中如何使用

    AVG()是MySQL中计算列平均值的聚合函数,忽略NULL值。基本语法为SELECT AVG(列名) FROM 表名;可结合WHERE筛选条件,如SELECT AVG(score) FROM students WHERE subject = ‘math’ AND score…

    2026年9月21日
    000
  • Flyway配置中安全使用环境变量的实践指南

    flyway配置中直接暴露数据库连接参数存在安全隐患。本文详细阐述了如何通过命令行参数和api调用两种主要方式,将环境变量安全地集成到flyway配置流程中。通过外部化管理敏感信息,可以有效提升数据库迁移配置的安全性、灵活性和可维护性,避免将凭证硬编码到配置文件中。 在数据库迁移实践中,将敏感的数据…

    2026年9月21日
    200
  • MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案MySQL缓存机制对性能提升的作用_MySQL缓存配置及调优方案

    mysql的缓存机制主要包括innodb缓冲池、查询缓存和操作系统文件系统缓存等,其中innodb缓冲池是性能优化的核心。1. innodb缓冲池缓存表数据和索引页,减少磁盘i/o,提升读写效率;2. 查询缓存因失效频繁及锁竞争问题,在高并发场景下易成瓶颈,已在mysql 8.0中移除;3. 操作系…

    2026年9月21日 用户投稿
    200
  • MySQL全文搜索如何与外部引擎结合_提升搜索体验?

    MySQL全文搜索如何与外部引擎结合_提升搜索体验?MySQL全文搜索如何与外部引擎结合_提升搜索体验?MySQL全文搜索如何与外部引擎结合_提升搜索体验?MySQL全文搜索如何与外部引擎结合_提升搜索体验?

    mysql 的全文搜索在中文分词和复杂查询上存在局限,常结合外部引擎提升性能。1. 使用 elasticsearch,通过 logstash 或 canal 同步数据,安装中文分词插件并利用布尔查询等优化搜索。2. 利用 sphinx,从 mysql 直接构建索引,通过 sql-like 接口和中文…

    2026年9月21日 用户投稿
    100
  • 如何在Java中配置与数据库连接环境

    答案:Java中配置数据库连接需引入JDBC驱动,如MySQL在Maven中添加对应依赖;通过DriverManager或连接池(如HikariCP)获取Connection,使用try-with-resources管理资源;建议将连接参数存入properties文件,并处理常见问题如驱动加载、权限…

    2026年9月21日
    000
  • MySQL的binlog格式有哪些类型_它们有什么区别和影响?

    MySQL的binlog格式有哪些类型_它们有什么区别和影响?MySQL的binlog格式有哪些类型_它们有什么区别和影响?MySQL的binlog格式有哪些类型_它们有什么区别和影响?MySQL的binlog格式有哪些类型_它们有什么区别和影响?

    mysql的binlog有三种格式:statement-based(sbl)、row-based(rbl)和mixed-based(mbl),它们分别记录sql语句、行变更和智能混合方式。1. sbl记录执行的sql,优点是日志小、可读性强,但存在不确定性导致主从不一致;2. rbl记录每行的具体变…

    2026年9月21日 用户投稿
    400
  • MySQL性能模式监控资源_MySQL瓶颈定位精确工具

    MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具MySQL性能模式监控资源_MySQL瓶颈定位精确工具

    mysql性能模式通过事件记录精准定位瓶颈,核心步骤包括:1.启用并配置performance schema,选择性开启消费者和仪器;2.监控等待事件、sql语句、阶段、i/o、内存及锁等关键指标;3.分析events_waits_summary_global_by_event_name等表识别资源…

    2026年9月21日 用户投稿
    000

发表回复

登录后才能评论
关注微信