MySQL(十五)】next-key lock

之前介绍过,sql标准中,rr级别并不能解决幻读问题,那么mysql是如何在rr级别解决幻读问题的?

锁协议

在非序列化隔离级别下,普通读数据是快照读,写数据则要加X锁,并且遵循两段式锁协议。也就是申请的锁会一直占用,直到事务提交。

幻读问题

幻读的定义有两点需要注意:

1.幻读只有使用锁定读才可能出现,因为普通读使用的是非锁定读,会通过MVCC机制获取到一致性视图,是看不到新插入的行的;

2.只有读到新增的数据才叫幻读;

幻读的影响:

1.如果只有行锁的话,语义不正确,没有锁住新更新的行;

2.一致性,主库和从库的状态可能不一致;

间隙锁

上面的X锁其实是行锁,即对某一行数据加锁;这个可以防止脏写的发生,即锁住已经存在的行,但是却无法阻止新插入的行。间隙锁是专门用来锁住某一个间隙的,是开区间;

next-key lock

是间隙锁+行锁的组合,间隙锁是行锁key之前的那个间隙。比如行锁要锁住id=5的行,前一个值是id=1的行,那么该行锁对应的间隙就是(1,5),next-key lock就是(1,5]。

在rr级别下,默认的加锁类型就是next-key lock。这样可以防止新插入的数据导致的幻读问题。因为加的是next-key lock,所以锁定的范围变大了,相应得,并发性能也会降低,这需要权衡。

在其他级别下加的是行锁。比如我们在rc级别下,就可以用锁定读复现幻读问题:

事务一:

先执行一条锁定读,因为是在rc级别,只给已经存在的id=1这一行加了行X锁;

事务二:

也插入了一条gender=1的数据,因为是新插入的,所以不受事务一加的行锁阻塞;

事务一:

紧接着,事务一再执行一条锁定读,可以看到,读到了新插入的数据,发生了幻读;

所以,仅仅在rr级别下才会加next-key lock,在rc级别仍然是行锁,是会有幻读问题的;

next-key lock加锁规则

这个比较复杂,需要结合具体的场景分析了:

访问到的对象加next-key lock,直到不满足条件的第一个值,这个值的锁退化为间隙锁;如果是索引上的等值查询,退化为行锁;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章