一个线上死锁问题分析

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

死锁日志如下:

TRANSACTION 48AA4BB9, ACTIVE 0 sec inserting

mysql tables in use 1, locked 1

LOCK WAIT 6 lock struct(s), heap size 1248, 4 row lock(s), undo log entries 2

MySQL thread id 1409173, OS thread handle 0x5659f940, query id 1084083936 10.246.138.197 bop_libra update

insert into deadlock_test

(deadlock_config_id, block_id, type, gmt_create, gmt_modified)

values

(31643, 92354, 1, now(), now());

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48AA4BB9 lock_mode X insert intention waiting

*** (2) TRANSACTION:

TRANSACTION 48AA4BBF, ACTIVE 0 sec inserting, thread declared inside InnoDB 500

mysql tables in use 1, locked 1

5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2

MySQL thread id 1393832, OS thread handle 0x7699f940, query id 1084083946 10.246.138.197 bop_libra update

insert into deadlock_test

(deadlock_config_id, block_id, type, gmt_create, gmt_modified)

values

(31643, 92353, 1, now(), now());

*** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48AA4BBF lock_mode X

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48AA4BBF lock_mode X insert intention waiting

*** WE ROLL BACK TRANSACTION (2)

表上有聚集索引和二级索引,死锁发生在二级索引idx_block_id上。

首先,从死锁信息:
RECORD LOCKS space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48AA4BBF lock_mode X
可以确定,这个x锁不是由于INSERT产生的。
INSERT可能产生的锁包括检查dup key时的s锁,隐式锁转换为显式锁(not gap,要在二级索引上产生lock_mode为X的LOCK_ORDINARY类型的锁(包括记录及记录前面的gap),据我所知一般是根据二级索引扫描进行记录更新导致的。
从5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2
有2个undo entires,而单纯的INSERT一条记录只有一个undo entry,因此可以推断除了INSERT,必然还有别的操作.)
基于以上,事务除了INSERT,可能还存在DELETE/UPDATE,并且这些操作是走的二级索引来查找更新记录。
一个简单但不完全相同的重现步骤:
DROP TABLE t1;
CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`),
  KEY `b` (`b`)
) ENGINE=InnoDB ;
insert into t1(a, b,c) values(1,2,3),(5,4,6),(8, 7,9),(12,12,19),(15,15,11);

session1:

begin;
delete from t1 where b = 12;
//二级索引上lock_mode X、lock_mode X locks gap before rec以及主键上的lock_mode X locks rec but not gap
二级索引:heap_no=5, type_mode=3  (12上的LOCK_ORDINARY类型锁,包括记录和记录前的GAP)
聚集索引:heap_no=5,type_mode=1027
二级索引:heap_no=6,type_mode=547(15上的GAP锁)
session2:
begin;
delete from t1 where b = 7;
//二级索引上lock_mode X、lock_mode X locks gap before rec以及主键上的lock_mode X locks rec but not gap
二级索引:heap_no=4,type_mode=3       (7上的LOCK_ORDINARY类型锁,包括记录和记录前的GAP)
聚集索引:heap_no=4,type_mode=1027
二级索引:heap_no=5,type_mode=547    (记录12上的GAP锁)
session1:
insert into t1 values (NULL, 6,10);
//新插入记录聚集索引无冲突插入成功,二级索引等待插入意向锁(lock_mode X locks gap before rec insert intention waiting)
二级索引,heap_no=4, type_mode=2819 (请求记录7上面的插入意向锁 LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, 需要等待session2
session2:
insert into t1 values (NULL, 7,10);
二级索引:heap_no=5,  type_mode=2819  (请求记录12上的插入意向锁 LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,需要等待session1)
互相等待,导致发生死锁
从打印的死锁信息来看,基本和线上发生的死锁现象是一致的。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8月前
|
Arthas Java 测试技术
【线上问题排查】死锁和僵尸进程排查
【线上问题排查】死锁和僵尸进程排查
147 1
|
7月前
|
存储 NoSQL Redis
记一次线上严重并发bug
记一次线上严重并发bug
|
测试技术 内存技术
|
测试技术
软件测试面试题:什么是并发?在lordrunner中,如何进行并发的测试?集合点失败了会怎么样?
软件测试面试题:什么是并发?在lordrunner中,如何进行并发的测试?集合点失败了会怎么样?
166 0
|
SQL 运维 监控
MySQL死锁系列-线上死锁问题排查思路
本篇文章会讲解一下如果线上发生了死锁异常,如何去排查和处理。除了系列前文讲解的有关加锁和锁冲突的原理还,还需要对 MySQl 死锁日志和 binlog 日志进行分析。
MySQL死锁系列-线上死锁问题排查思路
|
运维 监控 Java
面试官:线上环境 FGC 频繁,如何解决?
前言 这个问题应该是Java 面试中很经常被问到的一个题目,很多人害怕这个题目。 因为大部分人可能在工作中根本遇不到 FGC 频繁的问题,即使从网上背了点答案,心里也不踏实,因为毕竟不是自己亲自接触和解决过。 今天就和大家聊聊面试过程中遇到这个问题,该如何解答。
209 0
|
运维 监控 Oracle
死锁的排查工具有哪些
死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),都在等待对方释放资源,但没有一方提起释放资源,从而造成了一种阻塞的现象就称为死锁
217 1
死锁的排查工具有哪些
记一次并发引起的问题及排查过程
聚合支付系统(第四方支付),协议支付模块一直有个小问题。 商户调用协议支付接口,该模块会调用下层第三方支付渠道的协议支付服务,如果第三方支付渠道没有同步返回支付结果,则协议支付模块会通过定时任务向第三方支付渠道批量第查询支付结果(每查一笔订单就调一次第三方支付渠道,“批量”相当于并发调用第三方支付渠道)
记一次并发引起的问题及排查过程
|
监控 Java
死锁的 4 种排查工具 !(3)
死锁的 4 种排查工具 !(3)
99 0
死锁的 4 种排查工具 !(3)
|
Java Unix Linux
死锁的 4 种排查工具 !(2)
死锁的 4 种排查工具 !(2)
85 0
死锁的 4 种排查工具 !(2)

相关实验场景

更多