【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理

news/2024/5/17 13:34:43/文章来源:https://blog.csdn.net/fckbb/article/details/137609884

前言: 

在当今互联网时代,数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言,高效地处理并发访问和事务管理是至关重要的。多版本并发控制(MVCC)是一种数据库事务处理的技术,旨在提高并发性和数据一致性,而MySQL是其中一个广泛采用MVCC的数据库管理系统

在本文中,我们将深入探讨MVCC的概念、原理和实现方式,特别关注MySQL中MVCC的实现。我们将探讨MVCC是如何克服传统数据库锁定机制的局限性,从而实现更高的并发性和更好的数据一致性。通过深入了解MVCC,读者将能够更好地理解MySQL的工作原理,并能够优化数据库设计和性能调优。

目录

前言: 

当前读:

快照读:

MVCC:

实现原理:

RC隔离级别下:

RR隔离级别下:

总结: 


本片的数据库表的属性,如果没有特殊说明,那默认就是(innoDB+RR) 

 在介绍MVCC之前,我们要先介绍两个概念:

当前读:

读取的是当前记录的最新版本,读取的时候还需要保证其他并发事务不能修改当前记录,会对当前记录加锁。对于我们日常的select......lock in share modeselect......for updateupdateinsertdelete都是一种当前读。

快照读:

读取的是数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。常见隔离级别下的select:

  • RC:每一次select,都生成一个快照读。
  • RR:开启一个事务之后,只有第一个select语句才会生成一张快照,此后读的都是快照中的数据,直到事务提交。
  • Serializable:快照读退化为当前读。

我们用一个例子来看一下,以下为我们模拟的表数据(数据库默认使用InnoDB,隔离级别为RR):

我们同时开启两个MySQL客户端来对这张表进行操作:

 先尝试读取数据,这种能读取到表中最新数据的模式就叫做当前读。现在我们来看看什么是快照读

1.创建两个MySQL客户端,都开启事务,并且在第一个MySQL客户端中做一次SQL查询。

2.在第二个MySQL客户端中对id为1的用户姓名进行修改,并且提交当前事务。

3.重新在第一个MySQL客户端中查询。

我们会发现:第一个MySQL客户端中读取的数据竟然是老数据。这是为什么呢?

原因很简单:之前我们讲过MySQL的innoDB引擎在RR的隔离级别下,当我们开启事务的时候,只有第一次Select是当前读,读取完之后会生成一张快照,此后这个事务中后续的所有相同的select语句读的都是第一次Select所生成的快照。

当我们提交第一个MySQL客户端的时候之后,再尝试select * from emp ,会发生什么呢?

我们可以发现,此时就可以读取到正常的数据了。也就是说在InnoDB中select....... in share mode语句就是当前读。


MVCC:

        MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于数据库管理系统中实现并发控制的技术。它允许多个事务同时对数据库进行读写操作而不会导致数据不一致或丢失。

MVCC 的核心思想是在数据库中维护多个数据版本,并根据事务的隔离级别来决定哪个版本对特定事务是可见的。快照读就为MVCC提供了一个非阻塞读的功能,MVCC的具体实现还需要依赖数据库中的三个隐式字段undo log 日志readView

实现原理:

1.记录中的隐藏字段:当我们尝试创建一张表之后,InnoDB会自动为我们加上两个字段:

  • DB_TRX_ID:最近一次修改或删除记录的事务ID
  • DB_ROLL_PTR:回滚指针,指向记录的上一个版本
  • DB_ROW_ID:隐藏主键,如果表结构没有主键,将会生成该隐藏字段

2.undo log 日志:

  • Undo 日志记录了对数据的修改操作,包括插入、更新、删除等。
  • Undo 日志中记录了修改前的数据值,以及撤销操作所需的信息,以便在事务回滚或 MVCC 中使用。
  • 当事务提交的时候,相关的Undo log 日志就被标记为可回收状态,可以在之后的操作中被回收

如果是insert语句,那么Undo log日志只需要在回滚的时候需要,当事务提交之后,会被立即删除。

如果是update,delete的时候,产生的undo log日志不仅在回滚的时候需要,在产生快照读的时候也需要,因此其不会被立即删除。(undo log 中残留的旧版本数据可供其他并发事务进行快照读)

3.undo log 版本链:

(本图来自黑马程序员,偷懒了没画,如有侵权,请联系我立即删除)

 

 4.readview

readview是快照读SQL执行时候MVCC提取数据的依据,记录并且维护当前事务活跃的事务(未提交)的id。

ReadView包含了四个核心字段:

字段含义
m_min_trx_id最小活跃事务ID
max_try_id预分配事务ID,其实是当前最大事务ID+1(因为事务是自增的)
m_ids当前活跃的事务ID集合
creator_trx_idReadView创建者的事务ID

那么基于readView,其实就已经决定了哪些事务可以访问undo的哪些数据版本:

InnoDB不同的隔离级别,生成ReadView的实际不同:

  • READ COMMITTED : 在事务每一次执行快照读的时候生成ReadView。
  • REPEATABLE READ:仅在事务中第一次执行快照读的时候生成ReadView,后续一致复用该ReadView。 

我们来口述以下在这两种不同的隔离级别下,具体读取的是哪一个版本的快照:

RC隔离级别下:

其实就是去做比较,将undo log 中的DB_TRX_ID套入比较规则中,只要一个比较符合规则,那么就可以进行读取该版本的数据

经过一个一个的尝试,我们可以发现DB_TRX_ID=2的时候 ,符合比较规则2:trx_id<min_trx_id。

因此我们事务5中第一次查询id为30的记录的时候,实际上读的是DB_TRX_ID=2的快照读。

其实这四个比较看起来比较唬人,其实很好理解:RC是读已提交,也就是说我们的事务5在读取的时候,要么读取在自己之前已经提交了事务的版本数据要么读取自己修改的数据。那我们返回表中看:只有事务2在表5第一条语句之前提交了事务,因此我们事务5可以读事务2的数据版本。

因此我们可以看到RC可以防止脏读,因为它用的数据版本就是一个已经提交了事务的数据版本,自然不可能读到其他事务还没有提交的数据

RR隔离级别下:

RR隔离级别下,单个事务中一直复用的是该事务第一次查询版本快照。在当前案例中,事务5一直复用的就是自己第一次查询id等于30的数据记录。

因此我们可以看到RR可以防止重复读,这是因为事务一直使用的是自己第一次产生的readview,readview一样,那么匹配到的历史数据版本就一样,如果我们一直读取的都是一个历史版本数据,自然不可能出现两次读取结果不一致的情况了。

总结: 

        MVCC 是数据库系统中一种重要的并发控制机制,它通过在数据库中维护多个版本的数据来支持事务的并发执行,并提供了一致性读取和隔离性的保证。在 MVCC 中,每个事务都可以看到一个独立的数据版本,这使得读操作不会被写操作所阻塞,从而提高了数据库的并发性能。

MVCC 的实现主要依赖于两个关键组件:Undo 日志和版本链。Undo 日志记录了事务执行过程中对数据所做的修改操作,用于在事务回滚或撤销时恢复数据到之前的状态。而版本链则是指数据库中维护的多个数据版本之间的关系,包括当前版本、已提交版本和未提交版本等。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

三种常见webshell工具的流量特征分析

又来跟师傅们分享小技巧了&#xff0c;这次简单介绍一下三种常见的webshell流量分析&#xff0c;希望能对参加HW蓝队的师傅们有所帮助。 什么是webshell webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境&#xff0c;主要用于网站管理、服务器管理、…

机器学习中的激活函数

激活函数存在的意义&#xff1a; 激活函数决定了某个神经元是否被激活&#xff0c;当这个神经元接收到的信息是有用或无用的时候&#xff0c;激活函数决定了对这个神经元接收到的信息是留下还是抛弃。如果不加激活函数&#xff0c;神经元仅仅做线性变换&#xff0c;那么该神经网…

蓝桥杯——17

学习视频&#xff1a;18-深搜的剪枝策略练习_哔哩哔哩_bilibili Q&#xff1a;找数字 #include<iostream> #include<cstring> using namespace std; int n; bool ok; void dfs(int num, int cnt) {if (cnt > 19) {return;}if (ok) {return;}if (num % n 0) {…

MySQL-基本SQL语句编写:运算符练习

运算符练习 1.选择工资不在5000到12000的员工的姓名和工资 SELECT last_name,salary FROM employees #where salary not between 5000 and 12000; WHERE salary < 5000 OR salary > 12000;2.选择在20或50号部门工作的员工姓名和部门号 SELECT last_name,department_id…

基于springboot+vue+Mysql的职称评审管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

4月6号排序算法(2)

堆排序 讲堆排序之前我们需要了解几个定义 什么叫做最大堆&#xff0c;父亲节点&#xff0c;以及孩子节点 将根节点最大的堆叫做最大堆或大根堆&#xff0c;根节点最小的堆叫做最小堆或小根堆。 每个节点都是它的子树的根节点的父亲 。 反过来每个节点都是它父亲的孩子 。 …

Java从坚持到精通-SpringSecurity

1.安全框架是什么 安全框架的本质就是一堆过滤器的组成&#xff0c;目的在于保护系统资源&#xff0c;所以在到达资源之前会做一系列的验证工作&#xff0c;这些验证工作通过一系列的过滤器完成。安全框架通常的功能有认证、授权、防止常见的网络攻击&#xff0c;以此为核心拓…

IP地址中网络号的查看方法

IP地址是互联网中设备的标识&#xff0c;它由网络号和主机号两部分组成。网络号用于标识设备所连接的网络&#xff0c;而主机号则用于标识该网络中的具体设备。了解如何查看IP地址中的网络号对于网络管理员和需要进行网络配置的用户来说至关重要。虎观代理将介绍几种常见的查看…

linux之文件系统、inode和动静态库制作和发布

一、背景 1.没有被打开的文件都在磁盘上 --- 磁盘级文件 2.对磁盘级别的文件&#xff0c;我们的侧重点 单个文件角度 -- 这个文件在哪里&#xff0c;有多大&#xff0c;其他属性是什么&#xff1f; 站在系统角度 -- 一共有多少文件&#xff1f;各自属性在哪里&#xff1f…

Vue3---基础2(component)

主要讲解 component 的创建 以及vue插件的安装 Vue.js Devtools 为谷歌浏览器的Vue插件&#xff0c;可以在调试工具内查看组件的数据等 下载 有两种下载方式 1. 谷歌应用商店 打开Chrome应用商店去下载&#xff0c;这个方法需要魔法 2. 极简插件 极简插件官网_Chrome插件下载_…

react渲染列表信息(简单易学)

1.新建个文件夹&#xff0c;启动终端&#xff0c;使用create-react-app my-react命令创建项目&#xff0c;其中my-react是自定义项目名称。 2.删除根目录src文件夹下多余文件&#xff0c;保留index.js和index.css文件 3.安装scss需要的依赖&#xff0c;使用npm install --sav…

常见性能测试工具对比

在性能测试工作中&#xff0c;我们常常会遇到好几个工具&#xff0c;但是每一个工具都有自己的优势&#xff0c;一时间不知道怎么选择。 今天我们就将性能测试常用的工具进行对比&#xff0c;这样大家在选择工具的时候心里就有底啦&#xff01; 阿里云PTS 性能测试PTS&#xff…

【Linux】shell 脚本基础使用

在终端中输入命令可以完成一些常用的操作&#xff0c;但是我们都是一条一条输入命令&#xff0c;比较麻烦&#xff0c;为了解决这个问题&#xff0c;就会涉及到 shell 脚本&#xff0c;它可以将很多条命令放到一个文件里面&#xff0c;然后直接运行这个文件即可。 shell 脚本类…

【UnityRPG游戏制作】Unity_RPG项目之界面面板分离和搭建

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

【Qt】多线程

目录 一、常用API 二、线程安全 2.1 互斥锁 2.2 条件变量 2.3 信号量 在Qt中&#xff0c;多线程的处理一般是通过QThread类来实现 QThread代表一个在应用程序中可以独立控制的线程&#xff0c;也可以和进程中的其他线程共享数据。QThread对象管理程序中的一个控制线程 …

深入探索力扣第12题:整数转罗马数字的算法之旅

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作http://t.csdnimg.cn/Q59WX作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打…

业务逻辑漏洞(靶场) fiddler

目录 fiddler简介&#xff1a; 业务逻辑漏洞&#xff1a; fiddler下载 靶场&#xff1a; 实验一 ​编辑实验二&#xff08;ps 更改实验url会变&#xff0c;fiddler没抓到东西看看代理改没改&#xff09; 实验三 实验四 fiddler简介&#xff1a; 一款网络抓包工具&#…

ht1622不显示无反应问题解决

如果你正在写ht1622 驱动时&#xff0c;怎么看程序都没问题&#xff0c;抓取波形&#xff0c;示波器分析波形&#xff0c;如果都没有问题&#xff0c;那么很大可能是硬件问题&#xff0c;检测看看 ht1622 RD是不是接地了。 RD 低会进入读取模式&#xff0c;所以不用RD 请将RD悬…

雄安建博会:中矿雄安新区的总部开工建设

中矿落位雄安&#xff1a;助力国家战略与新区发展 雄安新区&#xff0c;作为中国未来发展的重要战略支点&#xff0c;正迎来一系列央企总部的疏解与建设。最近&#xff0c;中国矿产资源集团有限公司&#xff08;简称“中矿”&#xff09;在雄安新区的总部项目正式开工建设&…

Jettison 1.8.7直装版 外部磁盘辅助弹出

Jettison 是一款适用于 macOS 的实用工具&#xff0c;旨在简化外部驱动器的管理。它可以自动卸载和重新挂载外部驱动器&#xff0c;帮助您更方便地使用和保护您的存储设备。 软件下载&#xff1a;Jettison 1.8.7直装版下载 自动卸载和重新挂载&#xff1a;Jettison 可以在您离开…