关于MySQL临键锁区间的疑问!

数据库版本:MySQL5.7.33 Innodb RR隔离级别

CREATE TABLE `tests` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `number` int(11) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `number` (`number`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=latin1;

数据

开始测试

  1. 第一步:事务1:select * from tests where number = 25 for update; 这里按照几乎所有的教程都说会锁住(20,30]的区间
  2. 第二步:事务2:insert into tests set number=20;会阻塞
  3. 第三步:事务3:insert into tests set number=30;不会阻塞

疑问

(20,30]不就是20 < x <= 30的意思吗?不是应该插入number=30阻塞,number=20不阻塞才对吗?为啥我测试正好反过来?

阅读 2.2k
2 个回答

它其实是加的的是间隙锁gap锁(左开右开),我理解是因为没有查询到记录,不是临建锁next-key(左开右闭),因为20也算是(20,30)范围内的数据所以会被阻塞,而30可能是(30,+无穷)的数据,可以简单做个实验,

mysql> update tests set number=100 where number=20;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

上面的内容是可以更新成功的,所以说明20这条记录并没有加锁,只是在30上加了间隙锁。

间隙锁Gap Lock,二级索引叶子节点id=20到id=30,插入其中就会锁住

INSERT INTO `tests`(`id`, `number`) VALUES(15, 20); # 不锁

INSERT INTO `tests`(`id`, `number`) VALUES(25, 20); # 锁

INSERT INTO `tests`(`id`, `number`) VALUES(26, 30); # 锁

INSERT INTO `tests`(`id`, `number`) VALUES(35, 30); # 不锁
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题