手把手教你分析解决MySQL死锁问题( 二 )

1、事务A相关日志1)找到关键词TRANSACTION,事务2554368

手把手教你分析解决MySQL死锁问题

文章插图
 
2)查看事务1正在执行的sql
insert into user values (null, 15, "tianqi")
  1. 查看当前事务已占有的锁和等待其它事务释放的锁

手把手教你分析解决MySQL死锁问题

文章插图
 
2、事务B相关日志1)找到关键词TRANSACTION,事务2554369
手把手教你分析解决MySQL死锁问题

文章插图
 
2)查看事务2正在执行的sql
insert into user values (null, 30, "wangba")
  1. 查看当前事务已占有的锁和等待其它事务释放的锁

手把手教你分析解决MySQL死锁问题

文章插图
 
3、总结这里把一些关键的日志截图了下来
手把手教你分析解决MySQL死锁问题

文章插图
 
我们把这张图换一种方式画下来
手把手教你分析解决MySQL死锁问题

文章插图
 
1)从图中可以很明显地看出,事务1和事务2都在等对方的锁释放,所以导致了死锁问题 。而且最终是事务1进行了回滚 。
2)这个日志提供比较重要的信息就是我们可以看出的是哪两条sql在互相一直等待其它事务的锁释放而产生了死锁,也知道是哪个索引导致产生的死锁,同时也知道最终哪个事务
被回滚了 。
3)如果上面的信息还不能帮你定位解决问题,那可以问数据库DB要详细的binlog日志来分析这段时间这两个事务具体执行的所有sql 。
四、总结分析案例中产生死锁的原因这个分析就需要对MySQL中的各种锁机制有所了解,还不清楚的话可以看我之前写的两篇文章,看完你就清楚我下面所写的了 。
  • 一文详解MySQL的锁机制
  • MySQL记录锁、间隙锁、临键锁小案例演示
1、事务A的SQL产生了哪些锁1) 事务A的update语句产生哪些锁
我们先来看
updateuserset name = 'wangwu' where age= 20;记录锁
因为是等值查询,所以这里会在满足age=20的所有数据请求一个记录锁 。
间隙锁
因为这里是唯一索引的等值查询,所以一样会产生间隙锁(如果是唯一索引的等值查询那就不会产生间隙锁,只会有记录锁),因为这里只有2条记录
所以左边为(10,20),右边因为没有记录了,所以请求间隙锁的范围就是(20,+∞),加一起就是(10,20) +(20,+∞) 。
Next-Key锁
Next-Key锁=记录锁+间隙锁,所以该Update语句就有了(10,+∞)的 Next-Key锁
事务A的install语句产生哪些锁
INSERT INTO user VALUES (NULL, 15, "tianqi");间隙锁
因为age 15(在10和20之间),所以需要请求加入(10,20)的间隙锁
插入意向锁(Insert Intention)
插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,即事务A需要插入意向锁(10,20),这个插入锁的作用就是提高插入效率的,在分析
死锁的时候我们可以不用关心它,只关心上面的间隙锁就好了 。
2、事务B的SQL产生了哪些锁事务B的update语句产生哪些锁
我们先来看
updateuserset name = 'zhaoliu' where age= 10记录锁
因为是等值查询,所以这里会在满足age=10的所有数据请求一个记录锁 。
间隙锁
因为左边没有记录,右边有一个age=20的记录,所以间隙锁的范围是(-∞,10),右边为(10,20),一起就是(-∞,10)+(10,20) 。
Next-Key锁
Next-Key锁=记录锁+间隙锁,所以该Update语句就有了(-∞,20)的 Next-Key锁
事务A的install语句产生哪些锁
INSERT INTO user VALUES (NULL, 30, "wangba")间隙锁
  • 因为age 30(左边是20,右边没有值),所以需要请求加(20,+∞)的间隙锁
插入意向锁(Insert Intention)
  • (20,+∞)
锁都分析清楚了,接下来再来看下是什么地方导致死锁的呢?
手把手教你分析解决MySQL死锁问题

文章插图
 
这样一来产生整个死锁的原因也就清楚了,不过这里再补充两点
1)MySQL的间隙锁虽然有左开右闭的原则,但是其实这个并不完全正确,因为它有可能是左闭右开,也可能是左开右开,它会跟你插入主键值位置有关,具体的可以看我之前写的


推荐阅读