前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >绝对不谈死概念!用人能听懂的话带你玩明白MVCC的运行机制。

绝对不谈死概念!用人能听懂的话带你玩明白MVCC的运行机制。

作者头像
程序员牛肉
发布2024-09-26 13:23:09
1770
发布2024-09-26 13:23:09
举报
文章被收录于专栏:小牛肉带你学Java

大家好,我是程序员牛肉。

这篇中我不讲MVCC的死概念。那玩意网上太多了,一抓一大把。我再复制粘贴一遍没有任何意义。

如果你还不知道什么是数据库的MVCC机制,我推荐你可以看一看黑马的MySQL课程里面的MVCC机制解析,又或者是小林coding的讲解。他们对于MVCC机制是什么已经介绍的很详细了。

而我们今天对MVCC的深入理解,将通过两个问题来表达:

  • MVCC是如何防止脏读和不可重复读的?
  • MVCC机制一定能防住幻读吗?那他防不住哪些幻读?

我们来看看MVCC机制下的比较规则:

这个比较规则乍一看挺唬人的,但其实就一句话:“在MVCC机制下,一个事务要么读取自己修改过的数据,要么读取其他事务已经提交的数据。”

一定要理解我说的这句话,这将对你后面理解MVCC起到至关重要的作用。

让我们回到我开头的那个问题:MVCC是如何防止脏读和不可重复读的?

在RC的隔离级别下:

在一个事务中,每一次SELECT 都会生成一次快照,经由MVCC来确定能够读取哪个数据版本。

脏读的定义是:读取到其他事务未提交的数据。

而MVCC机制就是确保一个事务要么读取自己修改过的历史数据,要么读取其他事务已经提交的数据,这可不就防住了脏读嘛。

在RR的隔离级别下:

在一个事务中,只有第一次SELECT 会生成快照,此后一致沿用这个快照。

不可重复度的定义是:连续两次读取数据的结果不一致。

而MVCC是根据快照来判断当前事务能够读取哪一条数据历史记录的。如果我们一直沿用一个快照,那么可读取的数据版本就是同一个。同一个数据版本读数据得到的结果当然是一样的。这可不就防住了不可重复读嘛。

介绍完这两个,其实我们还可以做一下引申:为什么RC隔离级别下防不住不可重复读?

相信聪明的你很快就能知道答案:RC隔离级别下,每一次SELECT 都会生成一个新的快照。那么读取到的数据版本就可能不一致。自然有可能会出现幻读了。

第二个问题:MVCC机制一定能防住幻读吗?那他防不住哪些幻读?

看到我的问题,你就应该知道MVCC防不住所有的幻读。那MVCC能够防住哪些可能会发生幻读的场景呢?

下列的场景,当我们的事务B尝试往查寻结果集中尝试插入数据的时候,也不会发生幻读。

原因很简单:在事务B中虽然对结果集进行了插入,但我们的事务A在事务B还没有提交之前就进行了第二次查询。

也就是说:事务A是看不见这条事务B未提交数据的。而也符合MVCC的运行机制:在MVCC机制下,一个事务要么读取自己修改过的数据,要么读取其他事务已经提交的数据。

这其实就是B站很多UP主说的:“MVCC能解决当前读下的幻读”。但说实话按照我这种理解方式要好理解很多。

那MVCC防不住哪些幻读场景呢?

我们轻松一推理就知道了:在MVCC机制下,一个事务要么读取自己修改过的数据,要么读取其他事务已经提交的数据。

那我们有没有办法让这条插入记录变成事务A的历史修改数据呢?

当然有了,只要在事务B插入这条数据之后,我们update一下这条数据,就会把这条数据变成事务A的历史修改数据。

那么基于MVCC机制,事务A就可以读取到这条数据。

在这种情况下,MVCC是防不住幻读的,因为事务A的update把事务B的insert语句变成了自己的历史修改数据。

而MVCC让一个事务要么读取自己修改过的数据,要么读取其他事务已经提交的数据。

而这也就是很多UP主的“MVCC防不住一个事务中既有当前读,又有快照读的情况。”

在这里还需要注意了,很多人可能会认为事务A中的upate读不到事务B的插入数据,因为事务B的那条数据还未提交。

如果你有这个想法,那你还需要好好了解一下MySQL中的“快照读”和“当前读”。insert和update都是当前读,直接对最新的表数据进行修改,是没有快照这一说的。

那我们要如何防住这种幻读情况呢?

其实很简单,手动加锁就行了。加一个next_key 锁,锁住待查寻的数据范围就好了。而这也是MySQL的解决方案:

本图片来自小林coding

介绍到这里,相信你已经了解了“MVCC的运行机制”。我在介绍的时候已经尽量尝试少用专业名词和概念了。希望我的文章可以帮助到你。

对于MVCC,你的理解是什么呢?欢迎在评论区留言

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员牛肉 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档