Mysql中的MVCC

 ”真正学会,如你般自由~“


 MVCC机制简介

        MVCC(Multi-Version-Concurrency-Control)多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程中实现事务内存。

                                                                                                                                          取自

        MVCC存在被使用于多个大型数据库软件,诸如Mysql、Oracle、PostgreSQL等。其中,在Mysql存储引擎中,MVCC机制的运用,对于Innodb支持事务,更好的处理读-写并发,提高并发性能等具有支撑作用。

 MVCC带来的好处?

        数据并发的三种场景:

🥊 写-写:  有线程安全问题,只能串行化执行。

🥊 读-写: 有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读。

🥊 读-读: 不存在任何问题,也不需要并发控制。

         MVCC主要为 读-写情况提供无锁并发控制:

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  • 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

概念辨析

💎 如何理解事务?

        说起事务的概念,其本质并不复杂。我们可以将其理解为 一组“操作逻辑”,而这套逻辑天然需要支持四大特性: 原子性、持久性、隔离性、一致性 —— ACID。

        在Mysql中,分别采用不同的措施来保证 事务这四大特性:

🎫 通过回滚机制,保证sql在执行的过程中要么都被执行成功,要么都执行失败 —— 原子性

🎫 事务一旦提交,数据就是永久的 —— 持久性

🎫 通过隔离级别,保证各个开启事务、执行SQL不会互相干扰 —— 隔离性

        Mysql唯独没有对保证 一致性做任何操作,但为保障其他三个特点所做的技术,最终就是为了保证事务的一致性!

💎 当前读 vs 快照读

当前读: 就是它读取的是记录的最新版本

快照读: 读取为历史版本

        我们可以先看一个实验,我们先将Mysql中的隔离界别调整为RC(Mysql默认的隔离级别为RR)

        重启客户端后,就可以查看到修改字段:

        创建一个新表,并在其中插入一些数据:

RC隔离级别下的事务:  

        这很符合预期,毕竟咱们设置的隔离级别就是 “RC”,即读可提交。

RR默认隔离级别下的事务:

        我们现在按照统一的操作,在RR隔离级别下会发生什么呢?

        是的,我们再也无法看到另一端启动的事务 对表做的任何修改,即便它执行了“commit”!

        直观地,在RR下两个事务进行select的表一定是不同的!而这两个不同的表,一张记录的是当前数据信息,而另一张表记录的则是历史数据!

       当我们使用,像"select lock in share mode"在锁机制下的查询sql,就能读取到对端事务提交修改的新数据。

        由此,所谓当前读 与 快照读的本质,就是查询的表信息版本的不同~通过控制、管理 不同的版本信息,从而实现隔离性~ 对于,事务能看到的版本范围,则是由 “隔离级别“ 决定!隔离级别是怎样实现,Mysql是如何管理这个过程的,则是依赖MVCC机制从根本上提供技术支持。

MVCC机制实现原理

        MVCC目的在于 —— 多版本并发控制。为了解决读-写场景下产生的问题,MVCC通过3个核心机制完成控制和管理:

🔮 3个记录的隐藏字段

🔮 undo日志

🔮 Read View

3个隐式字段

        ⛳ DB_TRX_ID:

6 byte,最近修改( 修改/插入 )事务ID,记录创建这条记录/最后一次修改该记录的事务ID

        ⛳ DB_ROLL_PTR

回滚指针,指向这条记录的上一个版本,通过这个指针,从而形成一个历史版本链。

        ⛳ DB_ROW_ID

隐含的自增 ID (隐藏主键),如果数据表没有主键, InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引。
⛳  flag 隐藏字段
仅用来标记, 记录被更新或删除并不代表真的删除。

        

undo日志

        undo log有两个作用:提供回滚和多个行版本控制,它是一个逻辑日志。

        当sql语句是insert\delete时,记录这条操作的同时,也会在该日志中对应插入delete\insert 语句,用于回滚。同样,如果是遇到 update命令时,也会将原数据进行一份拷贝,再进行修改,并让新表中的 回滚指针,填写原版本的地址(这里的地址,指的时undo天然可以看成一块内存缓冲区,当数据被写入内存时,天然就会携带内存地址)。

        上面的一个一个版本,我们可以称之为一个一个的快照。当我们开启快照读,就是到这里面存储的表中读取数据!至于哪些版本是我们应该看到的,就与我们下一小节的read view决定了!

read View

        所谓read view,就是事务进行 "快照读"操作时,产生出的读视图。任何一个事务启动时,都会被分配一个事务ID!而这个事务ID是线性递增的~言外之意,事务ID越小,说明该事务到来得越早!

        read view是事务进行快照读所产生的,它需不需要记录是哪个事务执行的这个操作?它需不需要保存快照读时刻下,哪些事务是“活跃的”(即未进行commit,仍处于事务状态的ID)?……

        一个Mysql服务中,一定不止一个事务启动,一定不止一次快照读产生的不止一个read view,这些东西需不需要管理? 答案是都需要!如何管理呢? 先描述,再组织~ 因此,read view其本质上就是一个结构体(类对象)!

        下面是 我们简化一下的ReadView 结构: 

class ReadView {
// 省略...
private:/** 高水位,大于等于这个ID的事务均不可见*/trx_id_t m_low_limit_id/** 低水位:小于这个ID的事务均可见 */trx_id_t m_up_limit_id;/** 创建该 Read View 的事务ID*/trx_id_t m_creator_trx_id;/** 创建视图时的活跃事务id列表*/ids_t m_ids;/** 配合purge,标识该视图不需要小于m_low_limit_no的UNDO LOG,* 如果其他视图也不需要,则可以删除小于m_low_limit_no的UNDO LOG*/trx_id_t m_low_limit_no;/** 标记视图是否被关闭*/bool m_closed;
};

🥎 m_ids: 用来维护Read View生成时刻,系统正活跃的事务ID

🥎 creator_trx_id: 创建该ReadView的事务ID

🥎 up_limit_id: m_ids中,最小的事务ID

🥎 low_limit_id: ReadView生成时刻系统尚未分配的下一个事务ID

        当我们获取历史版本链时,每一个事务所能看到的版本都应该是受限制的,比如一个早来到的事务,不可能了解到后到事务对表数据进行的修改,正如 古人先贤不会对当今的智能时代加以评论、享受。

        我们read view手头中,正有DB_TRX_ID能够标识事务的先后顺序……

        这个可见性过程是怎样的?我们可以参照如下流程:

🏀 此时到来一个 creator_ID事务ID,它现在进行了一次快照读,生产read view,记录下了当前活跃的事务ID,更新了up_limit_id \ low_limit_id。它会去undo日志中,寻找任意一条记录,并获取上面的 DB_TRX_ID。

🏀 DB_TRX_ID < up_limit_id。如果小于,则事务能够看到这条记录。反之,我们继续往下走~

🏀 DB_TRX_ID >= low_limit_id。如果大于,则该事务不能看到这条记录,反之我们继续往下走~

🏀 DB_TRX_ID IN [m_ids]。如果该事务ID不存在活跃事务之中,那么就能看到这条记录,反之就不能。

RR与RC机制的本质区别

        总结这两种隔离级别的区别就是一句话,” 形成快照的时机不同 “。

RC: 每一次查询都会创建read view,保证读取当前最新版本。

RR:  只能生产一次read view,之后的一切查询读取都只能按照这个read view读取。

        正是RC每次快照读,都会形成Read View,所以,RC才会有不可重复读问题。


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图片编辑器tui-image-editor

提示&#xff1a;图片编辑器tui-image-editor 文章目录 前言一、安装tui-image-editor二、新建components/ImageEditor.vue三、修改App.vue四、效果五、遇到问题 this.getResolve is not a function总结 前言 需求&#xff1a;图片编辑器tui-image-editor 一、安装tui-image-ed…

【李沐精读系列】GPT、GPT-2和GPT-3论文精读

论文&#xff1a; GPT&#xff1a;Improving Language Understanding by Generative Pre-Training GTP-2&#xff1a;Language Models are Unsupervised Multitask Learners GPT-3&#xff1a;Language Models are Few-Shot Learners 参考&#xff1a;GPT、GPT-2、GPT-3论文精读…

javaSE-----继承和多态

目录 一.初识继承&#xff1a; 1.1什么是继承&#xff0c;为什么需要继承&#xff1a; 1.2继承的概念与语法&#xff1a; 二.成员的访问&#xff1a; 2.1super关键字 2.2this和super的区别&#xff1a; 三.再谈初始化: 小结&#xff1a; 四.初识多态&#xff1a; 4.1多…

100. 相同的树

代码实现&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ bool compare(struct TreeNode *tree1, struct TreeNode *tree2) {if (tree1 NULL && tree2 ! NU…

防御保护第七次作业-IPSEC VPPN实验

&#xff08;场景选用点到点&#xff0c;配置好FW1的出接口地址和对端FW3的接口地址&#xff0c;认证方式选用预共享密钥&#xff0c;身份认证选用IP地址&#xff09; 1、FW1 IP Sec策略配置 IKE参数配置&#xff1a; IP Sec参数&#xff1a; FW2配置&#xff1a; 加密数据流配…

SpringBoot 热部署。

SpringBoot 热部署。 文章目录 SpringBoot 热部署。 pom.xml。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional…

Jmeter二次开发实现rsa加密

jmeter函数助手提供了大量的函数&#xff0c;像 counter、digest、random、split、strLen&#xff0c;这些函数在接口测试、性能测试中大量被使用&#xff0c;但是大家在实际工作&#xff0c;形形色色的测试需求不同&#xff0c;导致jmeter自带或者扩展插件给我们提供的函数无法…

React-子传父

1.概念 说明&#xff1a;React中子组件向父组件传递数据通常涉及回调函数和状态提升等方法。 2.代码实现 2.1绑定事件 说明&#xff1a;父组件绑定自定义事件 <Son onGetSonMsg{getMsg}></Son> 2.2接受事件 说明&#xff1a;子组件接受父组件的自定义事件名称…

数据结构与算法-插值查找

引言 在计算机科学的广阔天地中&#xff0c;数据结构和算法扮演着至关重要的角色。它们优化了信息处理的方式&#xff0c;使得我们在面对海量数据时能够高效、准确地进行检索与分析。本文将聚焦于一种基于有序数组且利用元素分布规律的查找算法——插值查找&#xff08;Interpo…

tomcat基础介绍

目录 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; 2、Tomcat的配置文件详解 3、Tomcat的构成组件 6、Tomcat的请求过程 一、Tomcat的基本介绍 1、Tomcat是什么&#xff1f; Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器…

C++核心编程之内存分区模型,引用,函数提高

1&#xff0c;类型分区模型 c程序在执行中&#xff0c;将内存大方向划分为4个区域 1&#xff0c;代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 2&#xff0c;全局区&#xff1a;存放全局变量和静态变量以及常量 3&#xff0c;栈区&#xff1…

【性能测试】Jmeter性能压测-阶梯式/波浪式场景总结(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、阶梯式场景&am…

IDEA中四款代码补全的插件

说明&#xff1a;本文介绍四款IDEA中代码补全的插件及使用感受&#xff0c;插件如下&#xff1a; 以下插件都在2023.2版本的IDEA中安装使用的&#xff0c;旧版本IDEA可能无法使用。 Tabnine 在IDEA的插件商店中安装&#xff0c;官网&#xff08;https://www.tabnine.com/&…

ai智能写作软件推荐,ai一键生成作文

很多小伙伴们都觉得写作是一件让人头痛的事情。因为不仅要让自己的文字流畅有条理&#xff0c;还需要通过一些修辞手法来使文章更加生动有趣。市场上不断涌现出各种各样的AI人工智能原创文章写作平台&#xff0c;哪些才好用&#xff0c;才是适合自己的呢&#xff1f; 爱制作ai …

Z Potentials | 星爵,他的征途不止向量数据库

纵观过去几十年的科技发展史&#xff0c;每一代新的技术架构的出现往往都伴随着新的数据范式的出现&#xff0c;也催生了多家百亿到千亿美金数据平台的诞生。如果说 2023 年科技领域的关键词是 LLM&#xff0c;那么数据库领域的关键词一定非向量数据库莫属。向量数据库是一种专…

Redis核心数据结构之字典(二)

字典 解决键冲突 当有两个或以上数量的键被分配到了一个哈希表数组的同一个索引上面&#xff0c;我们称这些键发生了冲突(collision)。 Redis的哈希表使用链地址法(separate chaining)来解决键冲突&#xff0c;每个哈希表节点都有一个next指针&#xff0c;多个哈希表节点可以…

egg如何写单元测试

优秀的代码需要有单元测试进行质量保证&#xff0c;每个测试用例都给应用的稳定性提供了一层保障。 测试目录结构 我们约定 test 目录为存放所有测试脚本的目录&#xff0c;测试所使用到的 fixtures 和相关辅助脚本都应该放在此目录下。 测试文件的目录和我们需要测试的文件目…

#QT(智能家居界面-界面切换)

1.IDE&#xff1a;QTCreator 2.实验 3.记录 &#xff08;1&#xff09;创建一个新界面&#xff08;UI界面&#xff09; &#xff08;2&#xff09;可以看到新加入一个ui文件&#xff0c;双击打开&#xff0c;设置窗口大小与登录界面一致 &#xff08;3&#xff09;加入几个PUS…

【NR 定位】3GPP NR Positioning 5G定位标准解读(一)

目录 前言 1. 3GPP规划下的5G技术演进 2. 5G NR定位技术的发展 2.1 Rel-16首次对基于5G的定位技术进行标准化 2.2 Rel-17进一步提升5G定位技术的性能 3. Rel-18 关于5G定位技术的新方向、新进展 3.1 Sidelink高精度定位功能 3.2 针对上述不同用例&#xff0c;3GPP考虑按…

力扣经典题目解析--反转链表

原题地址: . - 力扣&#xff08;LeetCode&#xff09; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 题目解析 链表&#xff08;Linked List&…