如何解决幻读_MySQL如何解决幻读问题

ada6a34b21191d7c4a1f3a85d32fae76.png

527ae571f2679f02a350be284c4623bf.gif//MySQL如何解决幻读问题?//

    先来说说幻读的概念吧,在MySQL中,如果一个事务A根据某种特定条件的SQL查询出来一些记录record_a,此时另外一个事务插入了一些符合这种特定条件的记录record_b,原先的事务再次根据同样的SQL,查询到了record_a和record_b,这种现象就称之为幻读。

    注意,下面两种情况不能称之为幻读:

1、如果查出来数据比record_a的记录要少,

2、或者查出来的数据跟record_a记录一样,但是记录发生了变化。

    幻读强调的是一个事务按照相同的SQL查询了记录之后,后续的结果中出现了之前结果中不存在的值。

在默认RR隔离级别下,当发生了幻读现象之后,MySQL解决这种情况会使用两种方案。

方案一:读操作利用MVCC解决,写操作利用加锁解决

MVCC知识可以查看之前的文章:

《MySQL之MVCC初探(1)》

MVCC其实是借助于Readview(读视图)的概念,对数据库生成Readview时刻的版本做了一个快照。普通的查询语句只能看到生成Readview之前已经提交的事务,在生成Readview之前未提交的事务或者生成Readview之后才开启的事务是看不到的。MVCC情况下读取的都是记录的历史版本,而写操作都是更新的是记录的最新版本,因此,MVCC情况下,读操作和写操作本身并不冲突。

说的更简单一点就是RR隔离级别下,事务在第一次select的时候只生成一次Readview(类似拍了一张照片),后续的查询都复用这个Readview(同样的照片),当然,也就不会出现幻读现象了。

方案二:读写操作都采用加锁的方式

在银行支付等场景下,不允许读取记录的历史版本,只允许看到记录的最新版本,此时读操作和写操作都需要加锁,其实,要解决幻读问题,只添加记录锁于事无补,因为幻读的记录在第一次读取之前是不存在的,即使你给记录上了记录锁,但是不存在的记录上面如果没有锁,还是会造成幻读。

为了解决这个问题,MySQL引入了间隙锁,间隙锁的引入,阻止了其他会话在指定的间隙插入相关记录,也就解决了幻读的问题。

两种方案对比:

如果采用MVCC方式的话,只能解决一致性非锁定读(也称之为快照读)的幻读问题,读-写操作彼此并不冲突,并发性能更高;

如果采用加锁方式的话,可以解决当前读的幻读情况,读-写操作彼此需要排队执行,影响性能;

一般情况下我们当然愿意采用MVCC来解决读-写操作并发执行的问题,但在银行业务等特殊场景下,还是需要锁来解决的。

a8bc52f702e7165af5ce597310e0d7f7.png 828c0f18cb6f9e843d6219a22cfdc62f.png有帮助的话还希望点下再看哈
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值