案发现场

项目中有一张业务关联表t_biz_ref,最近给该表建立了复合索引,测试阶段并发执行插入操作频繁出现死锁情况。

  • t_biz_ref表结构
CREATE TABLE `t_biz_ref` (`id` varchar(32) NOT NULL COMMENT 'id',`app_key` varchar(64) NOT NULL COMMENT '应用key',`biz_id` varchar(64) NOT NULL COMMENT '业务对象id',`device_code` varchar(50) NOT NULL COMMENT '设备code',`module_code` varchar(50) NOT NULL COMMENT '业务模块编码',`is_delete` char(1) NOT NULL DEFAULT '0' COMMENT '是否删除0未删除1已删除',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`creator` varchar(4) DEFAULT NULL COMMENT '创建人',`creator_id` varchar(36) DEFAULT NULL COMMENT '创建人ID',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',`modifier` varchar(4) DEFAULT NULL COMMENT '修改人',`modifier_id` varchar(36) DEFAULT NULL COMMENT '修改人ID',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='业务关联';
  • 后对表添加索引:
CREATE INDEX UNION_IDX_1 ON t_biz_ref (app_key, module_code, device_code);CREATE INDEX UNION_IDX_2 ON t_biz_ref (app_key, module_code, biz_id);
  • 报错日志
    在mysql终端执行如下语句,可以看到最近一次死锁详细信息
show engine innodb status \G;
------------------------
LATEST DETECTED DEADLOCK
------------------------
2019-07-10 10:12:35 0x7f773116e700
*** (1) TRANSACTION:
TRANSACTION 314618527, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 1
MySQL thread id 296544, OS thread handle 140149888374528, query id 950973010 192.168.109.81 root update
INSERT INTO t_biz_ref  ( id,is_delete,app_key,biz_id,device_code,module_code ) VALUES( 'c88995fc93a54356b799866d79bf80b2','0','2d3c7bf923265e059017ae7c7e5bbc31','b3098940-c7fe-42cb-bd1e-f398f5000815','MX2019132130024989','faceset' )
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 5279 page no 340 n bits 208 index UNION_IDX_1 of table `salmon`.`t_biz_ref` trx id 314618527 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 84 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 30; hex 343137663165633235316163346539303063646661386566616137306237; asc 417f1ec251ac4e900cdfa8efaa70b7; (total 32 bytes);1: len 6; hex 726567696f6e; asc region;;2: len 13; hex 31353438303538343530343834; asc 1548058450484;;3: len 30; hex 343237643863323265373962343466363932303962616262396532633530; asc 427d8c22e79b44f69209babb9e2c50; (total 32 bytes);*** (2) TRANSACTION:
TRANSACTION 314618531, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 296487, OS thread handle 140149901420288, query id 950973038 192.168.109.81 root update
INSERT INTO t_biz_ref  ( id,is_delete,app_key,biz_id,device_code,module_code ) VALUES( 'abd65256b88643698d7c21cbacb8ecae','0','2d3c7bf923265e059017ae7c7e5bbc31','b3098940-c7fe-42cb-bd1e-f398f5000818','MX2019132130024992','faceset' )
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 5279 page no 340 n bits 208 index UNION_IDX_1 of table `salmon`.`t_biz_ref` trx id 314618531 lock_mode X locks gap before rec
Record lock, heap no 84 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 30; hex 343137663165633235316163346539303063646661386566616137306237; asc 417f1ec251ac4e900cdfa8efaa70b7; (total 32 bytes);1: len 6; hex 726567696f6e; asc region;;2: len 13; hex 31353438303538343530343834; asc 1548058450484;;3: len 30; hex 343237643863323265373962343466363932303962616262396532633530; asc 427d8c22e79b44f69209babb9e2c50; (total 32 bytes);*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 5279 page no 340 n bits 208 index UNION_IDX_1 of table `salmon`.`t_biz_ref` trx id 314618531 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 84 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 30; hex 343137663165633235316163346539303063646661386566616137306237; asc 417f1ec251ac4e900cdfa8efaa70b7; (total 32 bytes);1: len 6; hex 726567696f6e; asc region;;2: len 13; hex 31353438303538343530343834; asc 1548058450484;;3: len 30; hex 343237643863323265373962343466363932303962616262396532633530; asc 427d8c22e79b44f69209babb9e2c50; (total 32 bytes);

作案动机

t_biz_ref表使用innodb引擎,在执行插入方法中开启了事务T1。
事务T1包含两个操作:
1.先根据插入对象的app_key+module_ccode+device_code三个字段执行删除;
2.再执行插入对象操作。
添加复合索引UNION_IDX_1是由于项目中app_key+module_ccode+device_code的查询效率有要求,同时事务T1在执行删除时,如果没有UNION_IDX_1索引情况下会进行全表锁,这也会加大死锁概率。但是在加入索引UNION_IDX_1后,相同并发下,死锁现象反而更加频繁了。

破案实录

根据mysql死锁日志,我们将破案点锁定在了此次复合索引UNION_IDX_1上面。

业务方法分两种情况:
1.在执行删除操作时,如果UNION_IDX_1命中到数据则会执行行锁RK,而后续进行插入操作并不会出现锁冲突。
2.在执行删除操作时,如果UNION_IDX_1没有命中任务索引,那么问题就出现了,这时候UNION_IDX_1会执行一个间隙锁GK,而间隙锁的范围大大加大了出现死锁的概率。
找到“真凶”后如何防范于未然呢?解决办法有两个:
1.降低事务级别,间隙锁只在RR(Repeatable Read)和Serializable中存在,而RU(Read Uncommit)和RC(Read Commit)中不启用。
2.修改业务方法,删除方法前先执行查询操作,存在数据再进行删除,这样索引上加的就是行锁,规避使用到间隙锁。

Mysql并发插入引发的死锁相关推荐

  1. mysql并发插入死锁_MySQL: 并发replace into的死锁问题分析-阿里云开发者社区

    测试版本:MySQL5.6.23测试表: create table t1 (a int auto_increment primary key, b int, c int, unique key (b) ...

  2. mysql并发插入死锁_高并发下insert死锁 · Issue #ITUNR · baomidou/mybatis-plus - Gitee.com...

    当前使用版本(必须填写清楚,否则不予处理) springboot版本:2.0.3.RELEASE mybatis版本:3.0.5 jdk:1.8 该问题是怎么引起的?(最新版上已修复的会直接close ...

  3. 由MySQL加锁机制引发的死锁案例分析

    ​ 1.死锁案例 --建表 CREATE TABLE t1(`id` int(11) NOT NULL,`value` int(11) NOT NULLPRIMARY KEY (`id`),KEY ` ...

  4. MySQL自增字段并发插入导致死锁

    MySQL带自增字段的表在并发插入时发生死锁 问题 'int' object has no attribute 'encode'", <class 'mysql.connector.e ...

  5. mysql innodb 并发插入问题_包大量死锁错误_mysql innodb 并发插入问题,包大量死锁错误...

    开了10个并发写线程,没1000条记录批量提交一次,结果mysql包大量死锁错误! "Deadlock found when trying to get lock; try restarti ...

  6. mysql innodb 多线程插入_mysql innodb 并发插入问题,包大量死锁错误

    开了10个并发写线程,没1000条记录批量提交一次,结果mysql包大量死锁错误! "Deadlock found when trying to get lock; try restarti ...

  7. MySQL 唯一索引,并发插入导致死锁

    一日志 ------------------------ LATEST DETECTED DEADLOCK ------------------------ 2020-07-27 16:28:53 0 ...

  8. 记一次Mysql并发死锁,引出的问题及讨论

    这几天,在查看文章时,发现了一个Mysql并发的问题,在一开始仅仅凭借眼睛去查看时,并未发现问题及解决方法,于是我们对其进行了具体实际操作和测试: (想自学习编程的小伙伴请搜索圈T社区,更多行业相关资 ...

  9. MySQL中的锁机制、MyISAM表锁、MyISAM表级锁争用情况、MyISAM并发插入Concurrent Inserts、MyISAM的锁调度

    前言: 关于读锁.写锁.乐观锁.悲观锁.行锁.表锁的理解可以看看以前我写的: 读锁.写锁.乐观锁.悲观锁.行锁.表锁 内部锁:在MySQL服务器内部执行的锁,以管理多个会话对表内容的争用.这种类型的锁 ...

最新文章

  1. 关于iostream的效率问题
  2. VIM配置ActionScript
  3. Boost.MultiIndex 使用序列索引的示例
  4. Newtonsoft.Json(Json.Net)学习笔记
  5. java位宽_Java的数据类型
  6. 解析css之position
  7. 【阿里内推001期】听说你要做中台,阿里中台部门招Java开发
  8. 一文了解下对小微风控策略的优雅调整
  9. c语言代码re通常什么错误,C语言,realloc动态内存申请,出现报错double free or corruption (!prev)...
  10. 正则表达式之子表达式 ‘()’ 中表达式 '[]' 大表达式 '{}'
  11. MFC Windows 程序设计[二十一]之树形控件
  12. Windows XP 启动NetMeeting
  13. Mac-删除自带 ABC 输入法的方法
  14. 读headFirst设计模式 - 装饰者模式
  15. 如何让计算机按图片的顺序打印,如何将电脑中的几张图片打印在一张纸上
  16. 魔方软件测试自学,4 分钟!OpenAI 的机器手学会单手解魔方了,完全自学无需编程...
  17. S9300系列交换机升级系统版本
  18. JS中数组(Array)、Json对象长度(length)获取方法
  19. Spring入门第一讲——Spring框架的快速入门
  20. Swift ——String 与 Array

热门文章

  1. 支付宝个人支付接口 系统综合评估不满足签约条件 解决办法
  2. zip文件加密的几种破解方法
  3. 人工智能自然语言处理在人力资源管理方面的应用
  4. 学习笔记(3):EXCEL VBA编程进阶-2.9 综合应用(多工作表的条件筛选)
  5. 苹果怎么分享无线密码_怎么更改无线路由器密码
  6. Webkit内核探究【2】——Webkit CSS实现
  7. OpenCL入门:Intel核心显卡OpenCL环境搭建)
  8. maya拼图随机打乱工具插件
  9. pb编译机器码不成功的问题
  10. Open3d(三)——网格数据操作