MySQL 8.4.0
RR隔离级别
场景复现
分析下面SQL死锁的场景
对于switch表,有主键索引id和唯一索引(uid、type)。
CREATE TABLE `switch` (
`id` int NOT NULL AUTO_INCREMENT COMMENT 'Unique identifier for each switch',
`uid` int NOT NULL COMMENT 'User ID associated with the switch',
`type` tinyint NOT NULL COMMENT 'Type of the switch',
`val` tinyint(1) NOT NULL COMMENT 'Value of the switch, TRUE for on and FALSE for off',
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Table to store switch information for different users'
业务中有这么一个需求,以事务的方式批量插入固定两个开关;
注意,虽然是批量插入,但顺序是固定的!!!
INSERT INTO switch (uid, type, val) VALUES (30001,23,1) ON DUPLICATE KEY UPDATE val = VALUES(val);
INSERT INTO switch (uid, type, val) VALUES (30001,3,0) ON DUPLICATE KEY UPDATE val = VALUES(val);
然后业务上线后一段时间,告警发现事务出现了死锁Deadlock found when trying to get lock; try restarting transaction。

死锁排查
排除乱序插入;当时以为是事务中批量插入的顺序不一致,但重新梳理了下业务,能确定事务插入顺序都是固定的【23、3】;
INSERT INTO switch (uid, type, val) VALUES (30001,23,0) ON DUPLICATE KEY UPDATE val = VALUES(val);
INSERT INTO switch (uid, type, val) VALUES (30001,3,0) ON DUPLICATE KEY UPDATE val = VALUES(val);
唯一索引顺序不一致:后面想到使用了唯一索引,唯一索引的顺序是按照uid、type递增排序的,但我插入的时候是先插入type=23、再插入type=3的记录,因此怀疑是插入的时候,唯一索引上加了间隙锁,锁住了(0~23)的间隙,两个事务都保持间隙锁不释放,就产生了死锁。
定位到问题后,尝试把插入顺

最低0.47元/天 解锁文章
1865

被折叠的 条评论
为什么被折叠?



