[Database] 关系型数据库中的MVCC是什么?怎么理解?原理是什么?MySQL是如何实现的?

news2024/9/22 3:50:28

文章目录

  • 前言
  • 并发控制
    • 并发控制的实现与锁的本质
  • MVCC是什么?
    • MVCC的多版本(Multi-Version)指的是什么?
  • MVCC的实现方式?
    • MySQL的实现
    • PostgreSQL的实现
  • 结语

前言


在并发场景下,如果我们不对数据做保护,那么很容易出现不可预知的数据错误,在多线程中是如此,在数据库进程服务多个外部进程时也是如此,笔者将用本文去介绍数据库在面对并发场景时,是如何做并发控制的。同时也会简单介绍一下并发控制和锁的基础。

并发控制


并发控制,英:Concurrency Control,也叫并发访问控制(Concurrency Access Control)。

前者也许不太好想象,后者相对来说比较好想象。我们读写信息载体上(内存、磁盘、etc…)的数据的操作就叫数据访问。那么所谓并发访问控制其实也就是对我们多个“访客”同时读写载体上数据进行一个控制。

并发控制的实现与锁的本质

前面我们提到了并发访问控制,那么怎么去控制并发访问呢?其实也不神秘,答案就是锁(Locking)机制实现并发控制

并发控制是靠锁实现的。那么锁的本质又是什么呢?锁的本质也非常简单,锁需要的最基础的信息无非就是是否已经上锁,你可以用一个bit、一个boolean型甚至说一个文件的存在与否去表示 是否上锁这个信息。其他的访客观测已经上锁这个状态时就停止对资源的操作就是所谓的并发访问控制的真相了

下面笔者简单列举几个锁的例子:

  1. Java的ReentrantLock:底层靠AQS管理一个32位(int)的锁状态,0表示未上锁,0以上表示上锁了多少次。
  2. Java的ReadWriteLock:底层靠AQS管理一个32位(int)的锁状态,高16位存储写锁信息,低16位存储读锁信息。
  3. Java的内置锁:底层靠对象头(Object Head)里最开始的一个字(Word,32位 / 64位)来存储锁信息。
  4. 某App的文件锁:一个App进程加锁时,创建xxx.lock空文件,其他App进程看到这个文件存在就知道锁存在。从而实现并发访问控制。
  5. 分布式锁:在一个多个进程(不论是否是一个机器上的进程)都能访问到数据的地方(比如Redis或是其他的任意的远程数据服务都行)存放一个锁状态信息,和前面一样这个锁状态信息可以是一个int或boolean,具体怎么设计看需求。(就像前面的ReentrantLock和ReadWriteLock,不同需求可以设计不同的锁状态,但原理相通)

所以可以看到其实锁其实本身是非常简单的。

MVCC是什么?


我们前一章介绍了并发控制(Concurrency Control),有没有发现并发控制的缩写是CC,和我们的MVCC后两个字母是一样的?欸,对了,MVCC,全称:Multi-Version Concurrency Control,中译:多版本并发控制

在笔者之前的一篇文章《[Database] 脏读、幻读这些都是什么?事务隔离级别又是什么?MySQL数据库的事务隔离级别都有哪些?》里,讲述了RDBMS在并发场景下,不同隔离级别所面临的几种数据一致性问题。参考下图:
不同事务隔离级别会面临的问题
里面介绍READ COMMITTED(读提交) 这个隔离级别时,提到了不可重复读这个问题。也就是同一事务里,前后两次相同的查询会因为其他事务的提交(数据被修改)而读取到不一致的数据。

为了解决不可重复读这个问题,让同一事务里多次读取也能读到相同数据,MVCC被引入。

MVCC的多版本(Multi-Version)指的是什么?

数据和我们的软件一样,也有版本,同一个事务里前后两次查询到不同的数据,意味着前一次查询取到老版本的数据,后一次查询取到新版本的数据,并且这之后再去查询也只会是最新版本的数据,再也读不到老版本的数据,所以被称为不可重复读

那么可以看到MVCC的多版本其实指的是多版本的数据。MVCC的思想是让数据库有能力临时保持旧版本数据或能通过一些额外信息去构建(construct)老版本的数据(Record)。这样就能够在同一个事务中读取到老版本数据,保证多次查询都是相同版本的数据被获取。

MVCC的实现方式?

MVCC只是一种思想,并没有具体的规范,不同的数据库有不同的实现方式。上一节我们其实我们也提到了两种实现方式,这两种方式都能恢复老版本数据。

  1. 让数据库有能力临时保持旧版本数据:比如冗余的行记录(Record)+ 版本号的方式。
  2. 能够通过一些额外信息去构建老版本的数据:比如通过undo log这个额外信息去构建老版本数据。

那么这两种实现都有分别有哪些数据在使用呢?笔者了解的关系型数据库并不多,相对常见的三种的话就是PostgreSQL、MySQL和Oracle了,它们的实现方式如下表:

实现相关RDBMS
临时保持旧版本数据PostgreSQL
利用undo log信息去构建老版本数据MySQL(InnoDB引擎)、Oracle

MySQL的实现

在MySQL的文档这一章节《15.3 InnoDB Multi-Versioning》中,也清楚地说明了MySQL是如何实现多版本并发控制的。
InnoDB Multi-Versioning
简单来说呢InnoDB会持有被修改的记录的旧版本信息,这些信息被保存在undo表空间里被叫做回滚段(rollback segment)的数据结构里。InnoDB可以利用这些信息做回滚、也可以利用这些信息去构建一个记录(Row、Record)的早期版本。

在内部,InnoDB会给每个记录(行)增加三个属性用于实现MVCC,分别是:

  1. 6-byte的 DB_TRX_ID:记录最后一次更新数据(insert / update)的事务ID。删除操作会把记录里某个比特位设置为已删除,也被认为是update操作的一种。
  2. 7-byte的 DB_ROLL_PTR:ROLL指针信息,指针指向回滚段(rollback segment)里的一个undo log记录。也是这里面的信息让InnoDB有能力构建早期版本的记录。
  3. 6-byte的 DB_ROW_ID:每次新插入行的时候都会自增赋值的行ID,是默认的聚簇索引的一员。

PostgreSQL的实现

笔者对PostgreSQL了解不多,想具体了解可以参考这篇文章:《How does MVCC (Multi-Version Concurrency Control) work》。

大致如下图:
MVCC (Multi-Version Concurrency Control) – Updating a record

可以看到,这种实现数据库会同时持有冗余的记录(如下图),冗余的记录会在事务结束后,在某个时间被数据库垃圾回收掉。
冗余的记录

结语


总结,MVCC是一种并发控制,其没有具体的实现标准,不同关系型数据库的供应商会有不同的实现。
MVCC是让我们的数据库能够实现REPEATABLE READ这一默认事务隔离级别的基础,MVCC的存在使得事务在并发场景下能够满足同一事务内多次查询数据不受到其他事务的影响而保持前后一致(保持数据一致性)。

我是虎猫,希望本文对你有所帮助。(=・ω・=)

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

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

相关文章

分布式文件存储系统FastDFS[1]-介绍以及安装

一、分布式文件存储 1.分布式文件存储的由来 在我们的项目中有很多需要存储的内容出现,比如图片,视频,文件等等,在早期的时候用户量不大,产生的文件也不是很多,这时我们可以把文件和服务程序放在一个服务器…

STAAD.Pro CONNECT Edition

STAAD.Pro CONNECT Edition Bentley STAAD或STAAD Pro软件是分析和设计世界第三世界的第一款最佳工程软件,对于金属、混凝土、木材、铝和冷金属的专业选择,设计几乎所有类型的塑料、石化、隧道、桥梁、蜡烛等结构专业的功能和软件中任何数据大小的使用。…

Java课程案例学习(3)

2.1 学生管理系统实现步骤 案例需求 针对目前我们的所学内容,完成一个综合案例:学生管理系统!该系统主要功能如下: 添加学生:通过键盘录入学生信息,添加到集合中 删除学生:通过键盘录入要删…

Jcmd 虚拟机诊断利器

Jcmd 虚拟机诊断利器 Java虚拟机(JVM)是运行Java程序的抽象化的计算器。今天,来学习下如何轻松诊断正在运行的JVM。 JDK本身中提供了许多可用的工具,可以用于各种开发、监视和故障排除活动。推荐使用jcmd,简单易懂&a…

[附源码]计算机毕业设计南通大学福利发放管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

ThinkPHP6综合业务管理系统

有需要请私信或看评论链接哦 可远程调试 ThinkPHP6综合业务管理系统一 介绍 综合业务管理系统基于ThinkPHP6开发,数据库mysql,前端Layui,后台模板ok-admin。管理员登录系统后可对场所,分类,用户,运营商&am…

图片扫描仪第一弹,我实现了一个办公位简笔画

来一波对比 其实我工位还有点手办,一个植物,实在不会画,于是画了个基础版的。 办公位简笔画 虽然,这个工位上没有一个动画,但是图形和实物神似,所以可以用另一个动总结这个简笔画,那就是生动…

量子计算(十一):常见逻辑门以及含义

文章目录 常见逻辑门以及含义 一、Hadamard(H)门 二、Pauli-X 门 三、Pauli-Y 门 四、Pauli-Z 门 五、旋转门(rotation operators) 1、RX(θ)门 2、RY(θ)门 3、RZ&#xf…

深入理解计算机系统

hi,大家好,我是大师兄,让我们一起复习了一遍计算机系统核心知识,希望大家早日掌握这些核心知识,打造自己坚实的基础,为自己目标慢慢积累,等到自己春天的到来。详细点击查看-> 极客星球。计算…

PDF解除密码怎么操作?教你一键解除密码

我们在处理工作文件时,经常会有一些文件是加密状态的,这种文件必须要输入密码才可以打开,这时候就造成了很多不便,如果文件需要打印,我们就必须先输入密码,而且在每次查看文件前,都必须输入密码…

记录一次 在linux 搭建的mysql迁移到docker容器中

上篇文章写道,我腾讯云被攻击了,然后我各种删除木马文件,但在这个过程中,有些系统文件没认到,以为是木马文件,就删除了,各种处理无果,打开腾讯云的救援模式,备份了些重要…

【数据库】mysql索引

DB索引: 如果表创建了索引,那么DB会维护一张关于索引和主键关系的表 好处:快速查找数据 缺点:要额外维护一张表,会额外占用空间,对于表数据的更新操作都涉及更新索引 索引的操作 创建索引:…

LeetCode 74. 搜索二维矩阵

🌈🌈😄😄 欢迎来到茶色岛独家岛屿,本期将为大家揭晓LeetCode 74. 搜索二维矩阵,做好准备了么,那么开始吧。 🌲🌲🐴🐴 一、题目名称 LeetCode 74.…

[Android] [ROOT] Magisk(魔术师/面具) 设置以及必装模块的安装

🍁简介 当我们给手机刷入Magisk(面具)后,等于获得了安卓系统的最高管理员权限,也就是root权限。获取root权限后的设备相对于未root的设备,安全性会有一定的降低。也许是基于这个原因,现在大部分应用都会检测你的设备是…

xcode常用功能与操作

查看target是静态还是动态库 选中target,点击Build Settings tag,然后再右上角搜索框输入 mach,查看Mach-O type的值即可 mach-o文件类型分为: Executable:应用的主要二进制 Dylib Library:动态链接库&am…

栈与队列5:逆波兰表达式求值

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。 转载代码随想录 原文链接: 代码随想录 leetcode链接:150. 逆波兰表达式求值 题目: 根据 逆波兰表示法,求表达式的值。 有效的算符包括 、-、*、…

安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】

💕💕💕💕💕💕💕💕💕💕💕提取手机分区方法列举💕💕💕💕💕💕💕&a…

mybatis-plus,sgg,杨bochao,p49完成

MyBatis-Plus (baomidou.com) 一 MyBatis-Plus简介 增强工具。只做增强不做改。 可以直接在mybatis的基础上整合mybatis-plus。此时并不会影响mybatis的功能,即mybatis原来的功能都在,该怎么用还怎么用。锦上添花的是还能使用mybatis-plus提供的&#…

修改node_modules中安装的依赖(如第三方ui组件样式)并在下次安装时保留

场景:需要修改安装的某个ui库的样式或者其他依赖,直接去node_modules中修改后,重新安装,或者其他小伙伴的电脑上并不能同时修改 方案:用patch-package 可以保留修改 步骤一 安装 patch-package —> npm i patch-…

jQuery - 获取内容和属性

jQuery 拥有可操作 HTML 元素和属性的强大方法。 jQuery DOM 操作 jQuery 中非常重要的部分,就是操作 DOM 的能力。 jQuery 提供一系列与 DOM 相关的方法,这使访问和操作元素和属性变得很容易。 DOM Document Object Model(文档对象模型&a…