線上出現MySQL死鎖報警,經過show engine innodb status命令查看死鎖日誌,結合異常代碼,還原發生死鎖的事務場景以下:html
環境: mysql5.7,事務隔離級別REPEATABLE-READmysql
表結構sql
CREATE TABLE `ta` ( `id` int AUTO_INCREMENT, `a` int, `b` int , `c` int , PRIMARY KEY (`id`), UNIQUE KEY `ux_a_b` (`a`,`b`) ) ENGINE=InnoDB 數據: mysql> select * from ta; +----+------+------+------+ | id | a | b | c | +----+------+------+------+ | 1 | 1 | 10 | 100 | | 2 | 3 | 20 | 99 | | 3 | 5 | 50 | 80 | +----+------+------+------+
併發事務併發
T1 | T2 |
---|---|
begin; | begin |
delete from ta where a = 4;//ok, 0 rows affected | |
delete from ta where a = 4; //ok, 0 rows affected | |
insert into ta(a,b,c) values(4, 11, 3),(4, 2, 5);//wating,被阻塞 | |
insert into ta(a,b,c) values(4, 11, 3),(4, 2, 5); //ERROR 1213 (40001): Deadlock found when trying to get lock; | |
T1執行完成, 2 rows affected |
從上面能夠看出,併發事務都成功執行delete後(影響行數爲0),執行insert出現死鎖。分佈式
查看死鎖日誌,顯示事務T1的insert語句在等待插入意向鎖,lock_mode X locks gap before rec insert intention waiting
;事務T2持有a=4的gap lock,同時也在等待插入意向鎖。另外,T1能執行delete,說明它也拿到了gap lock,因此,兩個事務都持有gap lock,致使循環等待插入意向鎖而發生死鎖。spa
鎖兼容矩陣:.net
方案以下幾種選擇:日誌
insert加鎖分析,參考文章http://www.aneasystone.com/archives/2017/12/solving-dead-locks-three.htmlcode