唯一索引插入引发的死锁问题

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)的间隙,两个事务都保持间隙锁不释放,就产生了死锁。

定位到问题后,尝试把插入顺

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高冷小伙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值