深刻死锁回忆 X LOCK + XI LOCK顺序并发
由于有一些INNODB死锁解决经验,看到死锁日志时脑子立即想到了这样这种场景。但之前类似场景是先根据二级索引删除后插入,这次是发生在主键索引上,只锁了1行,心里就有点犯难了。所以在未了解到实际的业务场景时,不敢妄下结论。通宵分析了general log后,通过实验还原了业务场景。
场景回顾:
表结构:
CREATE TABLE `test` (
`id` int(10) unsigned NOT NULL,
`name` varchar(8) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `age` (`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
MYSQL INNODB REPEATABLE READ事物隔离级别
表数据:
id name age
------ ------ --------
9 a 1
12 a 2
1 b 1
5 b 2
ID PK:
1
5
9
12
序号 session 1: session 2:
1 SET autocommit = 0;
UPDATE test SET NAME='b',age=13 WHERE id=13;
(持有ID=13的RECORD行级排他锁RX)
2 SET autocommit = 0;
UPDATE test SET NAME='b',age=3 WHERE id=14;
(同样持有ID=14的RECORD行级排他锁RX)
3 INSERT INTO test VALUE (13,'b',13);
(为了防止幻读申请GAP间隙X锁(12到无穷大),因为session2持有14的RX锁,所以seesion1等待session2释放)
4 INSERT INTO test VALUE (14,'b',3);
(同样session 2也去申请间隙锁发生等待,这时候就形成死锁了,INNODB监测到死锁立即选择回滚)
死锁日志: