Mysql的MVCC知多少(隐藏字段,undolog版本链和ReadView)

news2025/1/20 1:38:25

文章目录

  • 前言
  • 一、什么是MVCC
  • 二、快照读与当前读
  • 三、4种隔离级别与MVCC
  • 四、MVCC实现
    • 4.1 隐藏字段和undolog版本链
    • 4.2 ReadView
  • 五、说明

前言

其实自己之前对MVCC知之甚少,总觉得是一块很难啃的骨头,有点内惧,但当你真的掌握之后,就发现打开了一扇大门,豁然开朗,鸟语花香~~

一、什么是MVCC

MVCC(multiversion Concurrency Control)多版本并发控制。
见名知意,MVCC就是通过多个数据行的版本对实现数据库的并发控制的。所谓并发,就是在某些隔离级别下,可以看到被别人修改前或后的数据,这样在查询的时候就不用等别人更新完我才能看到或操作了。

MVCC在Mysql InnoDB中的实现主要是为了提供数据库的并发性能,使得即使有读写冲突,也能做到不加锁。其思想其实是乐观锁的一种实现方式。

而MVCC的工作就是:生成一个ReadView,通过ReadView找到符合条件的记录版本(历史版本由undo log构建)。
查询语句只能读到生成ReadView之前已提交事务所做的修改,在生成ReadView之前未提交的事务或者之后才开启的事务所做的修改是看不到的。
写操作针对的是最新版本,读记录和历史版本以及改动记录的最新版本并不冲突,也就是采用MVCC时,读写并不冲突。

二、快照读与当前读

这里记住10字真言:读为快照读,写为当前读。
所谓快照读就是读的是快照数据,快照数据的出现也是为了避免加锁从而提高并发。
既然是快照,那么快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。快照读的前提是隔离级别不能是串行级别,串行级别下的快照读会退化成当前读。
当前读就是读的最新的数据,读的时候要保证其他的并发事务不能修改当前的记录,会对读的数据进行加锁。

三、4种隔离级别与MVCC

Read Uncommitted(读未提交):可以读到未提交的数据,即当前读,直接读最新的即可。
Serializable Read(串行读):使用加锁的方式来访问,也是最新读,即当前读。
Read Committed(读已提交)和Repeatable Read(可重复读)都是读到已提交的事务修改过的数据,如果一个事务修改了记录但未提交,就不能读取到这条最新记录,所以核心问题是判断版本链中哪个版本对当前事务可见,而这就是ReadView要解决的问题。

所以,这四种隔离级别中,只有Read Committed(读已提交)和Repeatable Read(可重复读)是MVCC要解决的并发的读写冲突的问题。
其中,Read Committed(读已提交)是每次查询的时候都获取一次最新的ReadView
Repeatable Read(可重复读)是只在第一次查询时获取ReadView,后面再查询都复用这个ReadView。之所以只在第一次查询获取ReadView,是为了避免不可重复读,而不可重复读就是两次读取的结果不一致,为了解决这个问题,那就索性两次读都读一个数据,这样就避免了两次读的数据不一致。
这里我还是想补充一下4种隔离级别存在的三种并发问题,以及解决和未解决的并发问题:

隔离级别存在的并发问题已解决的并发问题
Read Uncommitted(读未提交)脏读、不可重复读,幻读脏写
Read Committed(读已提交)不可重复读、幻读脏写、脏读
Repeatable Read(可重复读)幻读脏写、脏读、不可重复读
Serializable Read(串行读)-脏写、脏读、不可重复读、幻读

其实通过MVCC机制还解决了可重复读的幻读问题,这里我就不想细说了。

四、MVCC实现

说了这么多,MVCC究竟是怎么实现的呢?前面也提到过:
MVCC的工作就是:生成一个ReadView,通过ReadView找到符合条件的记录版本(历史版本由undo log构建)。
总结下来MVCC的实现就是依靠三个关键字:隐藏字段,undolog版本链和ReadView来实现的。

4.1 隐藏字段和undolog版本链

隐藏字段主要包括:trx_idroll_pointer
trx_id : 每次一个事务对某条数据记录改动时,都会把事务ID赋值给trx_id 隐藏列。
roll_pointer:每次对某条数据记录改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到记录修改前的信息。
下面举个🌰:
当前有一张person表,有一条:
id=1,name=“韩立”,class=一班 的数据,这条数据的trx_id=8,下面对这条数据进行如下的修改:

发生时间顺序事务10事务20
1BEGIN;
2BEGIN;
3UPDATE student SET name=“韩跑跑” WHERE id=1;
4UPDATE student SET name=“厉飞雨” WHERE id=1;
5COMMIT;
6UPDATE student SET name=“张铁” WHERE id=1;
7UPDATE student SET name=“曲魂” WHERE id=1;
8COMMIT;

以上的操作流程对name 的每次修改都会记录一条日志,每条日志都有一个roll_pointer属性,将这些undo日志连起来就成为了个链表:
在这里插入图片描述
id=1的这条记录在2个事务中做了4次变更,每次变更就会把前一个旧值放到undo日志中,随着更新的次数增多,所有的更新记录即版本就被roll_pointer连成一个链表,我们称之为版本链,链头就是当前记录的最新值,每个版本中还包括生成该版本对应的trx_id(事务ID)。

4.2 ReadView

前面反复提到过ReadView是个什么玩意呢?
ReadView就是事务在使用MVCC机制进行快照读操作时产生的读视图。包括creator_trx_id,trx_ids,up_limit_id,low_limit_id

  • creator_trx_id:创建这个ReadView的事务ID。(只有在对表中的记录做INSERT,DELETE,UPDATE时才会为事务分配事务ID,只有读事务的话事务ID默认为0。)
  • trx_ids:表示在生成ReadView时当前系统中活跃的读事务的事务ID列表。
  • up_limit_id:活跃的事务中最小的事务ID。
  • low_limit_id:表示生成ReadView时系统中应该分配给下一个事务的ID值。low_limit_id是系统中最大的事务ID值,并不仅限于活跃的事务ID。

针对low_limit_id的说明:low_limit_id并不是trx_ids中最大值。假设现有id为1,2,3都未提交的事务,只有3提交了,提交之后,就剩下1和2是活跃的,3提交后有一个新的读事务生成了ReadView时,则trx_ids包括1和2,up_limit_id=1,low_limit_id=4。

有了ReadView,会按照下面的规则,遍历版本链中的版本是否可见。

  • 如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同(trx_id=creator_trx_id),则说明当前事务正在访问的就是自己修改过的记录,该版本可以被当前事务访问。
  • 如果被访问版本的trx_id属性值小于ReadView中的up_limit_id值(trx_id<up_limit_id),则说明生成该版本的事务在当前事务生成ReadView之前已经提交,该版本可以被当前事务访问。
  • 如果被访问版本的trx_id属性值大于或ReadView中的low_limit_id值(trx_id>=low_limit_id),则说明生成该版本的事务在当前事务生成ReadView之后才开启,该版本不可以被当前事务访问。
  • 如果被访问版本的trx_id属性值介于ReadView中的up_limit_idlow_limit_id之间(up_limit_id<trx_id<low_limit_id),则需要判断一下trx_id值是否在trx_ids列表中:
    • 如果在,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被当前事务访问。
    • 如果不在,说明创建ReadView时生成该版本的事务已经提交了,该版本可以被当前事务访问。

五、说明

本文的知识点都是因为看了B站尚硅谷康师傅的Mysql课程,康师傅出品必属精品,等后面有时间我还会再刷两遍,真是受益匪浅,强烈安利众仙家~~

-----------------你知道的越多,不知道的越多--------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/106082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Fastadmin ThinkPHP5 宝塔环境 下Redis的使用教程

本篇为学习参考&#xff0c;不喜勿喷 此为宝塔windows环境下 1.首先在宝塔的安装面板&#xff0c;找到redis&#xff0c;点击安装。 2.安装完redis后&#xff0c;点击设置&#xff0c; 设置个密码(ps:留空代表没有设置密码) 3.php环境安装redis扩展&#xff08;ps:安装redis扩…

Linux学习笔记——Linux用户和权限管控

03、Linux用户和权限管控 3.1、认知root 用户 3.1.1、root用户&#xff08;超级管理员&#xff09; 1、无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#x…

赛狐ERP运营篇 | 店铺管理数智化 ,风险规避更有效!

亚马逊卖家在运营的当中会遇到以下这些问题&#xff1a; 1、工作重复度高&#xff0c;每天浪费大量的时间整理数据报表。 2、数据分析指标单一&#xff0c;无法掌握全局数据指标&#xff0c;综合分析Listing。 3、熬夜调广告&#xff0c;无法精准调整广告预算、竞价。 4、运…

2023年入职/转行网络安全,该如何规划?

前言 前段时间&#xff0c;知名机构麦可思研究院发布了 《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;其中&#xff0c;信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景&#xff0c;想必无需我多言&#xff0c;作为…

c盘扩展卷选项是灰的怎么办?win10系统c盘扩展卷灰色

在Windows自带的磁盘管理工具中&#xff0c;用户想要对C盘进行扩容&#xff0c;c盘扩展卷选项是灰的怎么办&#xff1f; 那么&#xff0c;在本文中&#xff0c;易我小编将为您解答c盘分区扩展灰色的相关知识&#xff0c;帮你用户高效快捷地拓展C盘。 一、c盘分区扩展灰色的原因…

Android入门第52天-在SharedPreference中使用加密

简介 在上一篇中&#xff0c;我们讲了SharedPreference的使用。但是那不是一个生产场景。特别是我们举了一个例子&#xff0c;存放登录信息的例子。这个例子里用户的密码没有加密&#xff0c;比如说在真实的实际生产环境里用户的一些敏感信息或者说是像&#xff1a;用户四要素…

磁矢位的引入 工程电磁场 P19

首先我们有恒定磁场的两个方程 为了更方便解决问题&#xff0c;我们引入磁矢位 由此我们可以得到 我们可以得到 我们要确定A&#xff0c;则既需要知道旋度&#xff0c;我们还需要知道散度 如果是均匀媒质&#xff0c;是常数 我们可以得到 我们进行展开可以得到 我们要知道…

索引的底层实现及应用和失效场景

简介 合适的索引能让查询语句性能得到极大的优化&#xff0c;它只是优化业务的一种方式&#xff0c;不能为了建立索引而建立索引。 索引是什么&#xff1f; 索引是一种为了快速查找数据的数据结构&#xff0c;是帮助数据库快速获取数据的 排好序的数据结构 (BTree)。 索引的好…

鸿翼医药备份解决方案:守护医疗数据 携手共克时艰

新冠疫情期间&#xff0c;CT检查成为了明确诊断的重要手段&#xff0c;医学影像科迎来了检测人次的高峰。随着大量的医学影像数据的产生&#xff0c;影像数据占据了医疗数据总数的80-85%&#xff0c;占据了大量的系统存储空间。 我国医学影像数据的年增长率大约为30-40%&#x…

容器云的双活与灾备技术

在多中心多云环境下&#xff0c;可将容器云部署为多活和灾备模式&#xff0c;通过全局负载均衡器实现应用的多中心多活与灾备。容器应用跨数据中心的双活&#xff0c;是将一个应用的不同副本部署到不同的数据中心&#xff0c;如图 1 所示的 Database 应用。 图1 Database应用双…

腾讯天美Java程序员月均20万!掌握这个后,也太香了....

最近在知乎上看到了这样一个热门问答 &#xff08; 图源自知乎&#xff0c;侵删&#xff09; 还附带了一张收入证明&#xff0c;看完后老夫直呼&#xff1a;我滴乖乖&#xff01;太刺激了&#xff01; 虽然这样的高收入只是少数&#xff0c;就像网友说的&#xff0c;不能看做是…

口罩形势下的医院财务管理

过去大多数年轻人一年甚至几年都不需要去医院&#xff0c;但是近三年的口罩带给人们的不便&#xff0c;使得医院一号难求&#xff0c;在这种新的形势下&#xff0c;医院财务管理也成为重要的改革对象财务管理是医院经济工作的核心。 医院所有的经营决策都必须以医院财务核算为…

代码随想录Day57|647.回文子串、516.最长回文子序列、动态规划总结篇

文章目录647.回文子串516.最长回文子序列动态规划总结篇647.回文子串 文章讲解&#xff1a;代码随想录 (programmercarl.com) 题目链接&#xff1a; 题目&#xff1a; 给定一个字符串&#xff0c;你的任务是计算这个字符串中有多少个回文子串。 具有不同开始位置或结束位置…

企业如何在工作中应用知识管理?

伴随着知识经济时代的兴起&#xff0c;企业的经营管理模式发生了新的变革。这种变革主要体现在管理方式由传统的工业生产经营转向了创新的知识经济管理和知识管理&#xff08;KnowledgeManagement, KM)&#xff0c;通过技术创新、高技术领域的探索&#xff0c;以打破制约产业技…

附录2-上传自己的包

目录 1 Node中包的规范 2 创建包 2.1 package.json 2.2 内容部分 2.2.1 格式化时间 handle_date.js 2.2.2 转义/还原 HTML handle_html.js 2.2.3 index.js 2.2.4 测试功能 2.3 说明文档 3 发布包 3.1 注册账号 3.2 登录账号 3.3 上传 4 删除包 4.…

能源管理系统与能源管理平台|瑜岿科技

构建“以新能源为主体的新型电力系统”。众所周知&#xff0c;随着新能源大规模接入&#xff0c;电力系统将呈现显著的“双侧随机性”和“双峰双高”的“三双”特征&#xff0c;为保证电力系统安全稳定高效运行&#xff0c;必须加速推进源网荷储一体化和多能互补发展&#xff0…

790. 多米诺和托米诺平铺(难度:中等)

题目链接&#xff1a;https://leetcode.cn/problems/domino-and-tromino-tiling/ 题目描述&#xff1a; 有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 “L” 的托米诺形。两种形状都可以旋转。 给定整数 n &#xff0c;返回可以平铺 2 x n 的…

使用 Webpack 从 0 到 1 构建 Vue3 项目

目录 1. 初始化项目结构 2. 安装 webpack&#xff0c;补充智能提示 3. 初步编写 webpack.config.js 4. 配置 运行 / 打包 命令&#xff0c;首次打包项目 5. 添加 Vue 及相关配置 6. 增加 删除上次打包文件 的配置 7. 在 webpack 中&#xff0c;配置别名 &#xff0c;替换…

设计模型-工厂方法模式

1、什么是工厂方法 工厂方法模式&#xff08;Factory Method&#xff09;&#xff0c;又称多态性工厂模式&#xff0c;属于设计模式三大分类中的创建型模式&#xff0c;作为抽象工厂模式的孪生兄弟&#xff0c;工厂方法模式定义了一个创建对象的接口&#xff0c;但由子类决定要…

【Quarkus技术系列】「序章」打造基于Quarkus的云原生微服务框架实践的理论知识基础

前提介绍 本系列文章主要讲解如何基于Quarkus技术搭建和开发“专为Kubernetes而优化的Java微服务框架”的入门和实践&#xff0c;你将会学习到如何搭建Quarkus微服务脚环境及脚手架&#xff0c;开发Quarkus的端点服务&#xff0c;系统和应用层级的配置介绍与Quarkus的编程模型…