死鎖日志如下:
transaction 48aa4bb9, active 0 sec inserting
mysql tables in use 1, locked 1
lock wait 6 lock struct(s), heap size 1248, 4 row lock(s), undo log entries 2
mysql thread id 1409173, os thread handle 0x5659f940, query id 1084083936 10.246.138.197 bop_libra update
insert into deadlock_test
(deadlock_config_id, block_id, type, gmt_create, gmt_modified)
values
(31643, 92354, 1, now(), now());
*** (1) waiting for this lock to be granted:
record locks space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48aa4bb9 lock_mode x insert intention waiting
*** (2) transaction:
transaction 48aa4bbf, active 0 sec inserting, thread declared inside innodb 500
5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2
mysql thread id 1393832, os thread handle 0x7699f940, query id 1084083946 10.246.138.197 bop_libra update
(31643, 92353, 1, now(), now());
*** (2) holds the lock(s):
record locks space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48aa4bbf lock_mode x
*** (2) waiting for this lock to be granted:
record locks space id 17 page no 161 n bits 584 index `idx_block_id` of table `deadlock`.`test_deadlock` trx id 48aa4bbf lock_mode x insert intention waiting
*** we roll back transaction (2)
表上有聚集索引和二級索引,死鎖發生在二級索引idx_block_id上。
首先,從死鎖資訊:
可以确定,這個x鎖不是由于insert産生的。
insert可能産生的鎖包括檢查dup key時的s鎖,隐式鎖轉換為顯式鎖(not gap,要在二級索引上産生lock_mode為x的lock_ordinary類型的鎖(包括記錄及記錄前面的gap),據我所知一般是根據二級索引掃描進行記錄更新導緻的。
從5 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 2
有2個undo entires,而單純的insert一條記錄隻有一個undo entry,是以可以推斷除了insert,必然還有别的操作.)
基于以上,事務除了insert,可能還存在delete/update,并且這些操作是走的二級索引來查找更新記錄。
一個簡單但不完全相同的重制步驟:
drop table t1;
create table `t1` (
`a` int(11) not null auto_increment,
`b` int(11) default null,
`c` int(11) default null,
primary key (`a`),
key `b` (`b`)
) engine=innodb ;
insert into t1(a, b,c) values(1,2,3),(5,4,6),(8, 7,9),(12,12,19),(15,15,11);
session1:
begin;
delete from t1 where b = 12;
//二級索引上lock_mode x、lock_mode x locks gap before rec以及主鍵上的lock_mode x locks rec but not gap
二級索引:heap_no=5, type_mode=3 (12上的lock_ordinary類型鎖,包括記錄和記錄前的gap)
聚集索引:heap_no=5,type_mode=1027
二級索引:heap_no=6,type_mode=547(15上的gap鎖)
session2:
delete from t1 where b = 7;
二級索引:heap_no=4,type_mode=3 (7上的lock_ordinary類型鎖,包括記錄和記錄前的gap)
聚集索引:heap_no=4,type_mode=1027
二級索引:heap_no=5,type_mode=547 (記錄12上的gap鎖)
insert into t1 values (null, 6,10);
//新插入記錄聚集索引無沖突插入成功,二級索引等待插入意向鎖(lock_mode x locks gap before rec insert intention waiting)
二級索引,heap_no=4, type_mode=2819 (請求記錄7上面的插入意向鎖lock_x | lock_gap | lock_insert_intention, 需要等待session2
insert into t1 values (null, 7,10);
二級索引:heap_no=5, type_mode=2819 (請求記錄12上的插入意向鎖lock_x | lock_gap | lock_insert_intention,需要等待session1)
互相等待,導緻發生死鎖
從列印的死鎖資訊來看,基本和線上發生的死鎖現象是一緻的。