mysql之间隙锁

前言

之前的文章介绍过mysql中的锁,其中有介绍到间隙锁,但是因为篇幅的问题,没有展开来讲,今天我们将详细的介绍一下间隙锁。

幻读

在介绍事务的时候,我们介绍过幻读。幻读就是第一次和第二次读到的数据行数不一样,也就是可能会 多一行。首先我们思考下,为什么会出现这种问题呢。首先,在可重复读的级别下,我们是通过mvvc来实现版本控制的。那接下我们建一个表,字段为(id,c,d),然后执行一些事务,如下图,
在这里插入图片描述
大家可以看到,我将d = 5 这一行给锁住了,但是我每次读到的数据都是不一样的。当然如果你不加for update的话,你读到的肯定都是一样的(这个不在赘述,详细可之前的文章,有介绍可重复读级别的详细介绍和原理)。for update 的作用就是给d= 5 这一行加了锁,同时也将这个读,变为了当前读。但是正常境况下,因为加了锁,所以即使当前读,前后两次读到的数据也是一样的。这里为什么会多了一行数据呢。这个是因为,你在给d=5这一行加锁的时候,(0,0,0)还不是(0,0,5)也就没有被加锁所以不受到影响。那怎么比避免呢,那就需要用到间隙锁了。

间隙锁

间隙锁是什么呢。就是比如你执行了下面的语句

insert into table t (0,0,0)
insert into table t (2,2,2)
insert into table t (4,4,4)
insert into table t (6,6,6)
insert into table t (7,7,7)

这5条记录,存在六个间隙锁,0之前有一个,7之后有一个,0到7中间有四个。
你如果想要避免出现幻读,除了要锁住所有的记录,还需要锁住这6个间隙锁,这样就不会出现幻读的情况。
MySQL还把间隙锁和行锁和在一起形成Next-Key,Next-Key是左闭右开的原则。也就是0到2的Next-Key,就是0这一行被锁住,且0到2之间不允许插入数据。当你给全表加了Next-Key之后,就相当于整个被加了mdl写锁,期间不能进行插入和修改操作,但是Next-Key允许被重复获取,就是大家都可以有间隙锁。间隙锁之和往这个间隙的插入操作有冲突。

听完上面的介绍,大家是不是觉得Next-Key比较无用,直接使用mdl写锁就行了。当前不是,这个没有d字段的索引的情况下,所以你需要全表加Next-Key,但如果d字段有索引的话,你只需要两个Next-Key就可以保证不会出现幻读,比如d上有索引,然后你去读d=4这一行,你只需要,加一个2到4和4到6的Next-Key,就能防止幻读的出现。

总结

间隙锁使用起来往往加锁的范围更大,也更容易导致死锁的出现。所以大家轻易不要使用。而且可重复读虽说是不能避免幻读,但是大部分情况下是不会出现幻读的,除非是上面那种你加锁读的情况下,正常的普通读是不会出现幻读的。而且在可重复读的隔离级别就已经使用到了间隙锁和Next-Key,这个比较影响性能,所以很多公司就会使用读提交加binlog_format=row 的组合(为什么这么用之前的文章有介绍,这里不再赘述)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mark---小鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值