mysql幻读与加锁规则

说明,在mysql的可重复读级别下,是很难模拟出幻读的情况的。幻读是指在一个事务的多次查询时,查到了之前没有出现过的行(指新增的行)。由于一般的select查询是“快照读”,自然是不可能出现这种事情的,所以幻读指的是“当前读”(例如 select *** for update)。


有一表m,有三列如下。

字段 说明
id 主键
c 普通索引
d 普通列

初始数据有6行,分别是(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25)

案例1

mysql幻读与加锁规则

  1. sessionA对c处于 (0,5]和(5,10]之间的数据记录加上了next-key锁。
  2. sessionB的前3条update语句都可以执行成功,但是第4条update语句会阻塞。因为第四条语句可以理解为 要在索引c上插入一个(c=5,id=0)这一行,但是其落在(0,5]和(5,10]之间,所以阻塞

注意,锁是加在索引上的。

案例2

mysql幻读与加锁规则

  1. 因为id=9的记录不存在,所以sessionA加上了间隙锁(5,10)
  2. 因为间隙锁之间不会发生冲突,所以sessionB的select *** for update也可以执行成功
  3. 因为sessionA的间隙锁,所以sessionB的insert插入会阻塞
  4. 因为sessionB的间隙锁,所以sessionA的insert插入会阻塞

mysql会发现死锁的存在,sessionA的insert语句会报错返回。

加锁的几个规则,如下:
mysql幻读与加锁规则

  • 访问到的对象那个才会加锁,比如 select id from m where c=5 lock in share mode;因为查询使用到了覆盖索引,所以主键索引上不会加锁。也就是锁,另外一个事务执行 update m set d =5 where id =5是不会阻塞的。