Mysql的默认隔离级别加间隙锁解决幻读问题和间隙锁使用的场景

写下这篇博客的原因

写下这篇文章是因为有一次有面试,面试官问到了mysql的默认隔离级别(可重复读)有没有什么方法可以解决SERIALIZABLE(串行化)才能解决的幻读问题,这一下子给我问到了,因为按照mysql的四个隔离级别来讲,只有串行化的这个隔离级别是可以解决幻读的。

下面我们详细看一下什么是间隙锁,mysql的可重复度隔离级别+间隙锁为什么可以解决幻读问题。

什么是间隙锁

间隙锁是mysql默认的存储引擎InnoDB的一个特性,在mysql引入InnoDB作为事务性存储引擎,就可以使用间隙锁了,也就是说在mysql4.0引入InnoDB后,mysql4.0以上的版本间隙锁就可使用。

但是在mysql4.0时,InnoDB还并不是mysql的默认存储引擎,在mysql5.1开始,将InnoDB作为的默认存储引擎。从此开始,间隙锁的使用更加普遍。

间隙锁是对表中数据一个区间的锁定,防止其他事务在这个区间插入新的记录。

举个例子:现在有一张student表,表中有age这个字段,表中数据有3-25岁的数据若干条。

我现在想要查询age大于10的所有记录,我这个查询的操作,称为事务A,这时候事务A间隙锁就会对所有大于10的所有记录进行加锁,同时也会对大于10后的数据,记录之间没有数据的区间,例如:10-20之间,13和15没有14这条数据,那么就会对13和15这个区间进行加锁,这时候如果有事务B尝试插入一个值为14的记录,就会和事务A持有的间隙锁冲突,事务B的这个操作将会阻塞到事务A执行成功,这就是间隙锁。

mysql的可重复读隔离级别+间隙锁为什么可以解决幻读

说白了,幻读就是在一个事务操作中,多次按照相同的where条件进行查询,由于其他的事务在并发事务中插入了符合条件的数据,使得每次查询的结果集不一样,这样做就违反了隔离原则,导致数据不一致,就造成了幻读。

这样看,我们上面说的间隙锁是完全可以解决幻读问题的。

使用间隙锁会造成什么问题?优缺点

优点:让我们可以在不修改mysql的默认隔离级别的情况下,解决了幻读问题。

缺点:

1. 性能问题:间隙锁可能锁定的范围比较大,会增加锁的数量和时间,会对并发性能有影响。

2. 可能导致死锁:多个事务进行并发操作,事务间可能会导致死锁,这需要开发或者数据库相关人员进行关注。

使用的场景

推荐使用的场景:

只推荐在数据一致性要求比较高的情况下使用,还有就是范围查询和多次读区需要的结果集需要一样的sql比较多的时候。

举个例子:有一个在线银行系统,用于执行金融贸易,例如用户转账,支付等,这种项目肯定不能出错,必须保证系统的所有操作一致和正确,不允许出现幻读。

例如,一个用户要转出一笔钱,但账户里不足以支付两倍金额。举例一个简单的场景:

  1. 事务A开始,并准备扣除用户账户的一定数额。
  2. 事务A查询账户余额,并确认余额充足。
  3. 同时,事务B也开始了,并尝试给同一个用户的账户打入一笔钱。
  4. 如果事务A不使用间隙锁,那么事务B可能成功插入一笔记录,影响余额。
  5. 事务A再次查询余额,发现账户里的钱多了,误以为还可以再转一次钱,可能会造成重复扣款。

不推荐使用的场景:

不推荐那种并发插入比较多的情况,单纯的CRUD项目或者对隔离性要求不高的项目。

举个例子:

设想一个在线票务系统,它支持用户购买演唱会门票。在热门活动的开票瞬间,可能有成千上万的用户尝试为同一个事件购买门票。

  1. 事务A开始并查询了剩余票数,这个查询操作涉及一定范围内的记录。
  2. 间隙锁锁住了这个范围的查询,防止其他用户同时插入新的订单。
  3. 事务B、C和D等等都在等待事务A完成以获取它们各自的锁。

在高并发的场景下,间隙锁会导致性能瓶颈

总之:是否使用间隙锁或者其他锁,要根据当前应用的特性和需求场景。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值