看一遍就理解:MVCC原理详解

介绍

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于实现数据库并发访问控制的机制。它允许多个用户同时读写同一数据项,从而提高了数据库在高并发环境下的性能和响应速度。以下是具体介绍:

  1. 基本概念
    • MVCC通过为每行数据维护多个版本来工作,每个版本都有自己的创建时间和事务ID。当一个事务需要读取数据时,它会读取对应版本的数据,而不是最新的数据。
    • MVCC避免了使用传统的锁机制来管理数据的并发访问,减少了锁竞争,从而提升了系统的吞吐量和响应时间。
  2. 工作机制
    • MVCC中,每个事务开始时都会创建一个ReadView,这是一个数据快照,记录了当前活跃的所有事务ID。当事务进行查询操作时,它会利用这个快照来判断哪些数据是可见的。
    • 对于INSERT、UPDATE或DELETE操作,系统会创建新的数据版本,并链接到旧版本上形成版本链。每个版本都保存了创建该版本的事务ID和时间戳。
  3. 关键组件
    • 系统中的每个事务都会被分配一个唯一的事务ID。这些ID用于追踪数据的版本以及决定哪些版本对特定事务是可见的。
    • 除了用户定义的数据列外,数据库还会为每个记录维护一些隐藏的元数据列,如行ID、事务ID和回滚指针等。这些信息用于支持MVCC的内部运作。
  4. 隔离级别
    • 在读已提交(READ COMMITTED)和可重复读(REPEATABLE READ)隔离级别下,MVCC通过生成数据的时间点快照来避免脏读、不可重复读和幻读现象的发生。不同的隔离级别决定了事务如何定义它们的ReadView。
  5. 应用场景
    • MVCC特别适用于具有高读/写比率的数据库环境,如联机事务处理系统(OLTP),可以显著提高系统的并发性能和数据一致性。
  6. 优缺点
    • 提高了并发处理能力,减少了等待锁释放的时间。
    • 降低了死锁的风险,因为减少了锁的使用。
    • 增加了系统的复杂性,可能会增加设计和调试的难度。
    • 在某些情况下,可能需要额外的存储空间来保存多版本的数据。

总的来说,MVCC是现代关系型数据库管理系统中一个至关重要的功能,它通过允许并行访问数据的方式来优化数据库的性能。理解其工作原理和实现方式有助于更好地设计和维护数据库应用,特别是在需要处理大量并发事务的环境中。

解决的MySQL问题背景

1.1 什么是数据库事务,为什么要有事务

事务,由一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。

假如A转账给B 100 元,先从A的账户里扣除 100 元,再在 B 的账户上加上 100 元。如果扣完A的100元后,还没来得及给B加上,银行系统异常了,最后导致A的余额减少了,B的余额却没有增加。所以就需要事务,将A的钱回滚回去,就是这么简单。

为什么要有事务呢? 就是为了保证数据的最终一致性。

1.2 事务包括哪几个特性?

事务四个典型特性,即ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

  • 原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部都执行,要么都不执行。
  • 一致性:指在事务开始之前和事务结束以后,数据不会被破坏,假如A账户给B账户转10块钱,不管成功与否,A和B的总金额是不变的。
  • 隔离性:多个事务并发访问时,事务之间是相互隔离的,一个事务不应该被其他事务干扰,多个并发事务之间要相互隔离。。
  • 持久性:表示事务完成提交后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。

1.3 事务并发存在的问题

1.3.1 脏读

当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

1.3.2 不可重复读

比如在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

1.3.3 幻读

幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读,他和不可重复读的主要区别在于一个每次读取是数据不一样,一个是读取的数量不一样。

1.4 四大隔离级别

为了解决并发事务存在的脏读、不可重复读、幻读等问题,数据库大叔设计了四种隔离级别。分别是读未提交,读已提交,可重复读,串行化(Serializable)

1.4.1 读未提交

读未提交隔离级别,只限制了两个数据不能同时修改,但是修改数据的时候,即使事务未提交,都是可以被别的事务读取到的,这级别的事务隔离有脏读、重复读、幻读的问题;

1.4.2 读已提交

读已提交隔离级别,当前事务只能读取到其他事务提交的数据,所以这种事务的隔离级别解决了脏读问题,但还是会存在重复读、幻读问题;

1.4 3 可重复读

可重复读隔离级别,限制了读取数据的时候,不可以进行修改,所以解决了重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题;

1.4.4 串行化

事务最高的隔离级别,在该级别下,所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

1.5 数据库是如何保证事务的隔离性的呢?

数据库是通过加锁,来实现事务的隔离性的。这就好像,如果你想一个人静静,不被别人打扰,你就可以在房门上加上一把锁。

加锁确实好使,可以保证隔离性。比如串行化隔离级别就是加锁实现的。但是频繁的加锁,导致读数据时,没办法修改,修改数据时,没办法读取,大大降低了数据库性能

那么,如何解决加锁后的性能问题的?

答案就是,MVCC多版本并发控制!它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。

MVCC实现原理

主要依赖于记录中的三个隐藏字段、undolog,read view来实现的。

1、隐藏字段

每行记录,除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段:

  • DB_ROW_ID:6字节,隐藏的主键,如果数据表没有主键,那么innodb会自动生成一个6字节的row_id
  • ​DB_TRX_ID:6字节,最近修改事务id,记录创建这条记录或者最后一次修改该记录的事务id
  • DB_ROLL_PTR:7字节,回滚指针,用于配合undo日志,指向上一个旧版本

假设有一条数据如下:

2、undolog

2.1 概念
回滚日志,表示在进行insert,delete,update操作的时候产生的方便回滚的日志。

2.2 说明

  • 当进行insert操作的时候,产生的undolog,只在事务回滚的时候需要用到,并且在事务提交之后可以被立刻丢弃
  • 当进行update和delete操作的时候,产生的undolog,不仅仅在事务回滚的时候需要,在快照读的时候也需要,所以不能随便删除,只有在快照读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除

当数据发生更新和删除操作的时候,实际只是设置了旧记录的deleted_bit,并不是将过时的记录删除,因为为了节省磁盘空间,innodb有专门的purge线程来清除deleted_bit为true的记录,如果某个记录的deleted_id为true,并且DB_TRX_ID相对于purge线程的read view 可见,那么这条记录就是可以被清除的。

2.3 undolog生成的记录链表
(1)假设有一个事务编号为1的事务向表中插入一条记录,那么此时行数据如下,主键id=1,事务id=1

(2)假设有第二个事务(编号为2)对该记录的name做出修改,改为lisi

底层操作:在事务2修改该行记录数据时
1、对该数据行加排他锁
2、把该行数据拷贝到undolog中,作为旧记录
3、修改该行name为lisi,并且修改事务id=2,回滚指针指向拷贝到undolog的副本记录中
4、提交事务,释放锁

(3)假设有第三个事务(编号为3)对该记录的age做了修改,改为32 

底层操作:在事务3修改该行记录数据时
1、对该数据行加排他锁
2、把该行数据拷贝到undolog中,作为旧记录,发现该行记录已经有undolog了,那么最新的旧数据作为链表的表头,插在该行记录的undolog最前面
3、修改该行age为32岁,并且修改事务id=3,回滚指针指向刚刚拷贝的undolog的副本记录
4、提交事务,释放锁

 上述的一系列图中,可以发现,不同事务或者相同事务的对同一记录的修改,会导致该记录的undolog生成一条记录版本链表,undolog的表头就是最新的旧记录,表尾就是最早的旧记录。

3、read view

Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,系统会生成一个此刻的快照,记录并维护系统此刻活跃事务的id,用来做可见性判断的,也就是说当某个事务在执行快照读的时候,对该记录创建一个Read View的视图,把它当作条件去判断当前事务能够看到哪个版本的数据,有可能读取到的是最新的数据,也有可能读取到的是当前行记录的undolog中某个版本的数据

1)可见性算法

将要被修改的数据的最新记录中的DB_TRX_ID(当前事务id)取出来,与系统此刻其他活跃事务的id去对比,如果DB_TRX_ID跟Read View的属性做了比较,不符合可见性,那么就通过DB_ROLL_PTR回滚指针去取出undolog中的DB_TRX_ID做比较,即遍历链表中的DB_TRX_ID,直到找到满足条件的DB_TRX_ID,这个DB_TRX_ID所在的旧记录就是当前事务能看到的数据。

2)可见性规则

首先要知道Read View中的三个全局属性:

  • trx_list:一个数值列表,用来维护Read View生成时刻系统正活跃的事务ID(1,2,3)
  • up_limit_id:记录trx_list列表中事务ID最小的ID(1)
  • low_limit_id:Read View生成时,系统即将分配的下一个事务ID(4)

具体的比较规则如下:

  • 首先比较DB_TRX_ID < up_limit_id
    如果小于,则当前事务能看到DB_TRX_ID所在的记录
    如果大于等于,则进入下一个判断
  • 接下来判断DB_TRX_ID >= low_limit_id
    如果大于等于,则代表DB_TRX_ID所在的记录在Read View生成后才出现的,那么对于当前事务不可见
    如果小于,则进入下一步判断
  • 判断DB_TRX_ID是否在活跃事务中,trx_list包含DB_TRX_ID
    如果包含,则代表在Read View生成的时候,这个事务还是活跃状态,未commit的数据,当前事务也是看不到,如果不包含,则说明这个事务在Read View生成之前就已经开始commit,那么修改的结果是能够看见的。

流程图如下:

总结:两种情况可见

  • DB_TRX_ID < up_limit_id
  • DB_TRX_ID不在trx_list范围内,且小于low_limit_id

拓展 :在RC隔离级别下,是每个快照读都会生成并获取最新的Read View,而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View,之后的快照读获取的都是同一个Read View。

 


 

 

 

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

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

相关文章

Python代码注释的艺术与智慧

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;注释的必要性 二、注释的误区&#xff1a;不是越多越好 过度注释的问题…

服务器端口号怎么看?如何查看服务器端口号呢?有哪些需要注意的?

简单来说&#xff0c;端口号就是计算机与外界通讯交流的出口&#xff0c;每个端口都有不同的编号&#xff0c;也就是“端口号”。它们是唯一的&#xff0c;用于标识不同的服务和应用程序。通过端口号&#xff0c;我们可以知道哪些服务正在运行&#xff0c;以及如何与它们进行通…

【Linux系统编程】进程概念、进程排队、进程标识符、进程状态

目录 什么是进程&#xff1f; 浅谈进程排队 简述进程属性 进程属性之进程标识符 进程操作之进程创建 初识fork fork返回值 原理角度理解fork fork的应用 进程属性之进程状态 再谈进程排队 进程状态 运行状态 阻塞状态 挂起状态 Linux下的进程状态 “R”(运行状…

洗地机哪个牌子最好用?2024洗地机排行榜

随着人们生活水平的提升&#xff0c;智能清洁家电已经成为日常生活中的必需品。如今的清洁家电市场上&#xff0c;洗地机、吸尘器和扫地机器人等设备各有其独特的功能和优势。洗地机结合了扫、拖、吸和自清洁等多种功能&#xff0c;不仅可以处理干湿垃圾&#xff0c;还能高效清…

工业路由器在新能源数字化中的应用:重塑能源行业的未来

随着全球对可再生能源和能源效率的追求日益加强&#xff0c;新能源数字化已成为推动行业发展的关键因素。在这一变革的浪潮中&#xff0c;工业路由器以其卓越的性能和独特的功能&#xff0c;成为新能源数字化不可或缺的核心组件。本文将深入探讨工业路由器在新能源数字化中的应…

使用Golang开发一个用于批量删除文件的命令行程序

核心代码 package cmdimport ("fmt""zdpgo_cobra""zdpgo_file" )func init() {rootCmd.AddCommand(deleteFileCmd)deleteFileCmd.Flags().StringVarP(&dirPath, "dir", "d", ".", "指定要删除的目录&qu…

【C语言】整型提升与char取值范围

整型提升介绍 C语言中整型算术运算总是至少以缺省&#xff08;默认&#xff09;整型类型的精度来进行的。为了获得这个精度&#xff0c;表达式中字符、短整型操作数在使用前被转换为普通整型。而这个过程是悄悄发生的。 整型提升的意义&#xff1a; 表达式的整型运算要在CPU…

C++ wasm 使用教程

环境搭建 git clone https://github.com/emscripten-core/emsdk.gitgit pull./emsdk install latest./emsdk activate latestsource ./emsdk_env.sh./emcc -v && ./emcc c11__Thread_local.c -s WASM_WORKERS --threadprofiler --memoryprofiler -v -o test.html &…

Sentinel的授权规则详解

文章目录 1、授权规则1.1、基本规则1.2、如何获取origin1.3、给网关添加请求头1.4、配置授权规则 2、自定义异常结果2.1、异常类型2.2、自定义异常处理 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学…

深度学习中的优化算法一(Pytorch 18)

一 优化和深度学习 优化算法 使我们能够 继续更新模型参数&#xff0c; 并使损失函数的值最小化。这就像在训练集上评估一样。事实上&#xff0c;任何满足于将优化视为黑盒装置&#xff0c;以在简 单的设置中最小化目标函数的人&#xff0c;都可能会知道存在着一系列此类“咒…

STM32 学习——2. PWM

这个项目将会不断改变pwm占空比&#xff0c;使用proteus示波器进行观察。 1. proteus8.15 原理图 2. cubemx 上图是配置外部晶振 上图配置在proteus中没啥作用&#xff0c;注意&#xff1a; 在实际开发板中&#xff0c;一定要配置它&#xff0c;不然下一次你写不进代码。 上图配…

番外篇 | YOLOv5-SPD:用最简单的方式完成低分辨率图像和小目标检测升级

前言:Hello大家好,我是小哥谈。论文提出了一个新的CNN构建模块称为SPD-Conv,用来替换每个步长卷转层和每个池化层(从而完全消除它们)。SPD-Conv由一个空间到深度(SPD)层和一个非步长卷积(Conv)层组成。本文详细介绍了如何在YOLOv5中引入SPD-Conv,助力助力低分辨率与小…

自用网站合集

总览 线上工具-图片压缩 TinyPNG线上工具-url参数解析 线上工具-MOV转GIF UI-Vant微信小程序版本其他-敏捷开发工具 Leangoo领歌 工具 线上工具-图片压缩 TinyPNG 不能超过5m&#xff0c;别的没啥缺点 线上工具-url参数解析 我基本上只用url参数解析一些常用的操作在线…

“等保测评与安全运维的协同:保障企业网络安宁

"等保测评与安全运维的协同&#xff1a;保障企业网络安宁"是一个涉及信息安全领域的重要话题。这里&#xff0c;我们可以从几个方面来探讨这个主题。 1. 等保测评&#xff08;等级保护测评&#xff09; 等保测评&#xff0c;即信息安全等级保护测评&#xff0c;是依…

[DDR5 Jedec 3]DDR5 SDRAM 状态图 和 基本功能

3000字, 依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解DDR》 3.1 简化状态图 来源: Jedec Proposed DDR5 Full spec 缩写功能ACT激活PRE预充电PRE_A全部预充电MRS寄存器集模式REF刷新TEN边界扫描模式ReadRD, RDS4, RDS8Read ARDA, RDS4A, RDS8AwriteWR, WRS4…

Ollama:一个在本地部署、运行大型语言模型的工具

Ollama&#xff1a;一个在本地部署、运行大型语言模型的工具 Ollama部署、运行大型语言模型概述安装配置Ollama命令模型库使用示例自定义模型从GGUF导入自定义提示从PyTorch或Safetensors导入 开启服务REST API卸载Ollama One-API概述One-API管理本地模型 Open WebUI概述Docker…

【Linux学习】深入了解Linux中进程状态及其转换

文章目录 进程状态进程排队进程的状态&#xff08;运行&#xff0c;阻塞&#xff0c;挂起&#xff09;进程的七个状态 孤儿进程 进程状态 进程 task_struct 可执行程序 进程不是一 直在运行的&#xff0c;可能在等待软硬件资源&#xff0c;比如scanf后&#xff0c;程序停止运…

邮件系统数据面临的安全问题及解决方法

随着电子邮件的普及&#xff0c;邮件系统已成为企业、学校、个人等用户之间进行信息交流的重要工具。然而&#xff0c;随着数据量的增加和用户对邮件系统的依赖&#xff0c;邮件系统数据安全问题也逐渐凸显。下面U-Mail技术张工就给大家讲解一下邮件系统数据面临的主要安全问题…

Ardupilot开源代码之Rover上路 - 后续3

Ardupilot开源代码之Rover上路 - 后续3 1. 源由2. 深度配置2.1 编码器2.2 WS2812B LED灯带2.3 4GLTE超视距2.3.1 摄像头2.3.2 QGC OSD虚拟遥控2.3.3 QGC外接JoyStick遥控 2.4 伴机电脑供电 3. 实测效果4. 遗留&后续4.1 设置倒车按钮4.2 MP无法连接ESP82664.3 高精度编码器问…

【知识拓展】ngrok-高性价比的内网穿透工具

前言 使用google colab运行的web应用无法打开进行测试。 第一时间想到是否有相关工具能将内网映射到外网供访问。于是找到了ngrok。 ngrok 是什么&#xff0c;我们为什么要使用它&#xff1f; ngrok官网是一个全球分布的反向代理&#xff0c;无论您在哪里运行&#xff0c;它…