Loading

[MySQL]一次死锁排查

字节面试题

image
在可重复隔离级别下,这种情况会发生什么?

答案:死锁

下面我们用一个具体的例子来展示:
首先我们有一张这样的表
image
下面我们来执行一些语句,

image

可以看到结果输出了,检测到发生了死锁

Deadlock found when trying to get lock; try restarting transaction

下面具体分析,首先给出执行流程

事务A 事务B
1 begin; begin;
2 update user set age = 30 where id = 25;
3 update user set age = 30 where id = 26;
4 insert into user(id,name,age,email) values(25,"dcf",30,"123@qq.com");
5 insert into user(id,name,age,email) values(26,"dcf",30,"123@qq.com");

下面分析每个阶段的加锁情况

  1. 阶段2 update user set age = 30 where id = 25;

通过select * from performance_schema.data_locks\G;来查看加锁的情况:

image

可以看到加了两种锁,一种是表锁,意向排他锁,可以看到成功获取了这把锁,

LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL

另一种是记录锁,排他锁,间隙锁,锁住的范围是(20,30),可以看到成功获取到了这把锁,

LOCK_TYPE: RECORD
LOCK_MODE: X,GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 30
  1. 阶段3 update user set age = 30 where id = 26;

通过select * from performance_schema.data_locks\G;来查看加锁的情况:

image

可以看到加了两种锁,一种是表锁,意向排他锁,可以看到成功获取了这把锁,

LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL

另一种是记录锁,排他锁,间隙锁,锁住的范围是(20,30),可以看到成功获取到了这把锁,

LOCK_TYPE: RECORD
LOCK_MODE: X,GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 30
  1. 阶段4 insert into user(id,name,age,email) values(25,"dcf",30,"123@qq.com");

image

  1. 阶段5 insert into user(id,name,age,email) values(26,"dcf",30,"123@qq.com");

image

可以看到第3,4阶段双方都在等待锁,产生了死锁现象,
这个死锁的产生是由于,在阶段1,2双方持有了(20,30)区间的间隙锁,阶段3,4的插入操作会产生插入意向锁,这两个插入意向锁都被对方的间隙锁所阻塞,从而产生了死锁。

插入意向锁介绍
本文使用了间隙锁会阻塞插入意向锁这个特点

ps:当前事务的间隙锁不会阻止当前事务在这个间隙上的插入操作,间隙锁只是为了阻止其他事务在这个间隙上的插入操作,从而产生幻读问题。

posted @ 2024-09-09 22:24  Duancf  阅读(17)  评论(0)    收藏  举报