d3dcompiler47dll丢失怎么解决_Mysql RR级别依然可能丢失更新数据

上篇推文中,我们了解到Mysql MVCC的相关知识:一文理解Mysql MVCC。今天我们就用学到的相关知识,解决一个问题。

我们都知道,Mysql Innodb引擎的默认事务隔离级别是RR可重复读,也就是在同一个事务中,多次读取相同的数据结果相同。而其底层就是通过:“排它锁+MVCC”来实现的。

话不多说,我们来看看下面的这个问题:

9607e0c9b8276a28ca2be7782352c85d.png

我们可以看到,上面的事务A在更新数据之前,数据已经被事务B所修改,但是事务A最终提交的时候,将事务B的提交覆盖掉了,导致了事务B的更新丢失。

用我们之前学过的MVCC来理解一下为什么这个问题会发生:

首先由于事务A开启的时候,事务B还没提交,此时A事务进行了一次select操作,导致生成ReadView。根据这张图的原理:

ae4575af77629a218961ad1df4874da7.png

B事务处于trx_ids的事务中,所以A事务无法看到B事务的数据处理过程,即B事务对数据的操作,对A事务不可见。这也正是可重复读的实现的原理。

而恰恰是因为A事务看不到B事务对数据的更新,而A事务本地无论如何都是读到该数据的1000元可重复读的版本,导致A事务后面的更新操作直接在1000元这个版本上对数据添加100,将B事务的更新完全覆盖。

那么如何解决上面的这个问题呢?

我们来看看上面问题的本质,其实就是在事务B操作数据之前,我们就调用了select,导致生成了ReadView,而我们又拿着这个select的数据去做后面的处理,最终导致了B数据的丢失。

看到这里可能有人会想,那等B事务的操作commit了之后再去做A事务的select操作不就不会有这个问题了吗?说的确实没错,按这么操作,B事务确实处在A事务可见区内,最终不会导致B事务的更新丢失。可是在并发情况下,你怎么知道什么时候会突然有个B事务来更新呢?

于是我们最好的做法就是在A事务的查询时,添加一个锁,mysql中的语句如下:

select * from demo where id = 1 for update;

这样在A操作事务前,B事务就无法获取到锁,也就无法进行更新操作了。从而避免了更新丢失。

其实上面的更新丢失情况,术语叫做:第二类更新丢失问题。而解决办法也有多种角度,如上面的加悲观锁方式,或者乐观锁方式(类似CAS)也可以处理此类问题。

不过强哥还是比较喜欢上面悲观锁的方式,方便且简单有效,其他的解决办法有兴趣的同学可以去网上找找我就不在这里说明了。

相信大家还有一个疑问,既然有第二类更新丢失问题,那么肯定也有第一类吧,没错,第一类更新丢失又叫回滚丢失:

bd5064f9d63f0ed412d641a0f4dab353.png

不过,各种数据库的各种隔离级别都不允许此类问题的产生,所以就不在这里赘述了。至于数据库是如何避免这种问题的发生,强哥也找了好多资料,可是还是没有获取到有用的原理说明,大多类似如下的解释:

e9cb9b5640042f075258c8f3ec61bb47.png

所以,在此也就不胡乱猜测,如果小伙伴们有知道的也可以留言一起讨论下哦~

关注公众号获取更多内容,有问题也可在公众号提问哦:

db80f087a9baa5c48ff951d21162229c.png

强哥叨逼叨

叨逼叨编程、互联网的见解和新鲜事

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值