题外话
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;
三、总结
此次只是遇到了一个特殊的场景,但也提醒了我们,隔离级别不同,相应的锁粒度是不一样的。
哎哟,不错噢! - - - - - - 欢迎指出有误的地方以及补充更好的方法