------------------------ LATEST DETECTED DEADLOCK ------------------------ 2019-05-1615:38:170x7f121830f700 *** (1) TRANSACTION: TRANSACTION 161027737922, ACTIVE 0 sec fetching rows mysql tables in use 1, locked 1 LOCK WAIT 88 lock struct(s), heap size 24784, 1412row lock(s), undo log entries 2 MySQL thread id 42610991, OS thread handle 139701841643264, query id 4044655416010.7.23.224 promotio_e0a1 updating /*id:6d7cc9a7*/DELETEFROM `campaignmockqueue` WHERE `campaignid`=52327710and `addtime` <=1557992297 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1975 page no5280 n bits 1272 index idx_campid oftable `promotion`.`campaignmockqueue` trx id 161027737922 lock_mode X waiting *** (2) TRANSACTION: TRANSACTION 161027729748, ACTIVE 31 sec inserting mysql tables in use 1, locked 1 7 lock struct(s), heap size 1136, 7row lock(s), undo log entries 14 MySQL thread id 42610752, OS thread handle 139715692001024, query id 4044655426010.43.174.209 promotio_e0a1 update /*id:dfdc4b66*/INSERTINTO `campaignmockqueue`( `campaignid`, `addtime` ) VALUES (52327709, 1557992297) , (52327709, 1559383140) , (52327709, 1557992296) *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 1975 page no5280 n bits 1272 index idx_campid oftable `promotion`.`campaignmockqueue` trx id 161027729748 lock_mode X locks rec but not gap *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1975 page no5271 n bits 1272 index idx_campid oftable `promotion`.`campaignmockqueue` trx id 161027729748 lock_mode X locks gap before rec insert intention waiting *** WE ROLL BACK TRANSACTION (2)
我们先来看看 事务1 和事务2 分别持有什么锁,又在等待什么锁。由于日志是在事务 1 的角度来打印的,所以我们只能看到事务 2 持有 lock_mode X locks rec but not gap 锁,在等待 lock_mode X locks gap before rec insert intention 锁。
lock_mode X locks rec but not gap 就是写记录锁,只锁了单条记录。
lock_mode X locks gap before rec insert intention 就是一个插入意向锁,目标是在对应的间隙上(不包括记录本身)加锁。
通过事务 2 的锁信息我们可以推测出事务 1 的锁持有信息,因此就有了下面的图。
事务 1 当前拥有的应该是间隙 A 和 记录X 组成的 nexy-key 锁 ,现在正在等待的是间隙 b 的锁。
1
DELETEFROM `campaignmockqueue` WHERE `campaignid`=52327710and `addtime` <=1557992297
事务 2 当前拥有的应该是 记录 Y 的 X锁, 间隙 D 的插入意向锁, 间隙 C 的插入意向锁 ,现在正在等待的是间隙 e 的 间隙插入意向锁(也有可能是 记录 Y 的 record lock)。
------------------------ LATEST DETECTED DEADLOCK ------------------------ 2019-05-16 03:02:36 0x7f11eebd8700 *** (1) TRANSACTION: TRANSACTION 161022641521, ACTIVE 0 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 5 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 2 MySQL thread id 42518313, OS thread handle 139715027216128, query id 40270385508 10.7.224.35 promotio_e0a1 update /*id:dfdc4b66*/INSERT INTO `campaignmockqueue`( `campaignid`, `addtime` ) VALUES
(52247612, 1557946956) , (52247612, 1557936000) , (52247612, 1558022399) *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1975 page no 4904 n bits 1264 index addtime of table `promotion`.`campaignmockqueue` trx id 161022641521 lock_mode X locks gap before rec insert intention waiting *** (2) TRANSACTION: TRANSACTION 161022641523, ACTIVE 0 sec fetching rows mysql tables in use 1, locked 1 4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1 MySQL thread id 42543917, OS thread handle 139714996569856, query id 40270385509 10.7.23.224 promotio_e0a1 updating /*id:6d7cc9a7*/DELETE FROM `campaignmockqueue` WHERE `campaignid`=52247612 and `addtime` <= 1557946956 *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 1975 page no 4904 n bits 1264 index addtime of table `promotion`.`campaignmockqueue` trx id 161022641523 lock_mode X *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 1975 page no 4904 n bits 1264 index addtime of table `promotion`.`campaignmockqueue` trx id 161022641523 lock_mode X waiting *** WE ROLL BACK TRANSACTION (2)
解决方案
DELETE FROM campaignmockqueue 不使用 idx_campid 这个索引加锁,而使用唯一主键来做操作,和 insert 操作使用不同的索引,来避免这个问题。