先上环境
创建表:
CREATE TABLE `z` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `b` (`b`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
准备数据:
INSERT INTO `jj`.`z`(`id`, `b`) VALUES (1, 2);
INSERT INTO `jj`.`z`(`id`, `b`) VALUES (3, 4);
INSERT INTO `jj`.`z`(`id`, `b`) VALUES (5, 6);
INSERT INTO `jj`.`z`(`id`, `b`) VALUES (7, 8);
INSERT INTO `jj`.`z`(`id`, `b`) VALUES (9, 10);
先开启事务T1 对 b=6 加X锁
BEGIN;
SELECT *FROM z WHERE b = 6 FOR UPDATE;
再开启事务T2 插入 (2,8)
BEGIN;
INSERT INTO z VALUES (2, 8);
测试发现 事务T2 会blocked。
这是为什么呢 ?
下面是我自己对 事务T1 执行的 select for update语句的加锁分析
1 首先会 获取到'z'表的意向排它锁
2 对b=6的数据,二级索引加next-key锁,聚集索引加X锁
3 间隙锁,这也是我最有疑问的地方,我认为间隙的范围是(id =3,b=4)到 (id=7,b=8),也就是b索引锁的范围是 (4, 8], 我事务T2插入(2,8)也不应该 blocked啊~
求教求教 感谢感谢