记一次特殊的Mysql死锁场景

记一次特殊的Mysql死锁场景

题外话

mysql版本为5.7.27,隔离级别为RR。

一、故障现象

Mysql的一个从节点,数据未同步,检查发现SQL线程中断,然后在error.log查到如下信息,而且还比较多

| master_prdxxx001 |         1 |      NULL | OFF           | xxxxdab9-49ed-11e8-b5ee-005056axxx:122598975 |              1213 | Worker 1 failed executing transaction 'e3bedab9-49ed-11e8-b5ee-005056a1a8ba:122598975' at master log mysql-bin.000405, end_log_pos 185432301; Deadlock found when trying to get lock; try restarting transaction | 2020-06-14 01:38:49  |

可以看到是发生了死锁,很奇怪从节点没有写业务,怎么会有死锁产生?
带着问题,写了一个脚本去抓取sql语句,发现了一些可疑的insert和update语句:
a_tmp为临时使用的表,a为需同步主节点数据的表。

insert into a_tmp select * from a;
update a_tmp set xx=.... where ...;

怀疑是上述类型的语句造成的,故进行了模拟测试:

1、创建同样的表tb01和tb02,插入两条数据到tb01。
在这里插入图片描述
在这里插入图片描述
2、模拟update和insert语句加锁
session 1:
在这里插入图片描述
session 2:
在这里插入图片描述
回到session 1:
在这里插入图片描述
此时发生了锁等待,说明tb01的id=2这条记录被其他事务锁住了

回到session 2:
在这里插入图片描述
死锁发生,故可以判断此为发生死锁的原因

二、故障处理

使用innodb引擎,在正常情况下,读和写是不会相互阻塞的,但这里的特殊情况是:
1、不是简单的select xxx from xxx;而是insert into xxx select xxx from xxx;
2、隔离级别为RR;

由于此mysql实例为边缘系统,和相关人员沟通后,了解到有场景是直接在从节点抽数,造成了此情况。

解决方案:把抽数相关的session改为RC级别,不再出现死锁情况。
set session transaction isolation level READ COMMITTED;

三、总结

此次只是遇到了一个特殊的场景,但也提醒了我们,隔离级别不同,相应的锁粒度是不一样的。

哎哟,不错噢! - - - - - - 欢迎指出有误的地方以及补充更好的方法

猜你喜欢

转载自blog.csdn.net/Tah_001/article/details/108626874