MySQL 唯一索引范围查询锁下一个记录的理解

来源:这里教程网 时间:2026-03-01 16:50:03 作者:

相信大家研究过锁的同学,都知道在唯一索引的范围查询,会锁下一个记录,在mysql45讲中,作者也提到过,并且认为是个bug,但是官方没有确认,针对这个问题,我也思考了下,下面描述下我的理解,如果不正确,麻烦指正。

mysql> show create table dba_test2\G
*************************** 1. row ***************************
       Table: dba_test2
Create Table: CREATE TABLE `dba_test2` (
  `id` int NOT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `udx_age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
select * from dba_test2;
+-----+------+
| id  | age  |
+-----+------+
|   1 |   11 |
|   2 |   15 |
|   3 |   20 |
session1;
ysql> select * from dba_test2 where age <=15 for update;
+------+------+
| id   | age  |
+------+------+
|    1 |   11 |
|    2 |   15 |
+------+------+
2 rows in set (0.01 sec)
session2 --被阻塞
 delete from dba_test2 where age=20;

我的理解,如果有这样的事务begin;update dba_test2 set age=88 where age=15;select * from dba_test2 where age <=15 for update; 这样select的时候,看到id=15的记录已经没有了,会向后查找定位记录,找到后加锁,那为什么不向前查找定位记录,向前的话加的锁范围就不对了,导致幻读。所以是向后定位一个记录,如果没有20这个记录,那么就会在最大值上加范围锁。   针对这个case,8.0优化了,只是锁了15之前的记录,应该是去查15这条记录是否真实存在了,存在就加15之前的,不存在就向后多加一个范围。8.0针对最大值的范围,查询没有缩小范围,select * from dba_test2 where id <=3.,将最大值这个范围锁上了,这个比较奇怪,按理说都是下一个记录锁,处理的方式应该跟上面的方式一样,看来还是没有彻底解决这个问题。 有兴趣学习源码的加群一起学习啊 QQ:                                                                                                                                                                                                                                                                700072075

相关推荐