【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理
前言:
在当今互联网时代,数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言,高效地处理并发访问和事务管理是至关重要的。多版本并发控制(MVCC)是一种数据库事务处理的技术,旨在提高并发性和数据一致性,而MySQL是其中一个广泛采用MVCC的数据库管理系统。
在本文中,我们将深入探讨MVCC的概念、原理和实现方式,特别关注MySQL中MVCC的实现。我们将探讨MVCC是如何克服传统数据库锁定机制的局限性,从而实现更高的并发性和更好的数据一致性。通过深入了解MVCC,读者将能够更好地理解MySQL的工作原理,并能够优化数据库设计和性能调优。
目录
前言:
当前读:
快照读:
MVCC:
实现原理:
RC隔离级别下:
RR隔离级别下:
总结:
本片的数据库表的属性,如果没有特殊说明,那默认就是(innoDB+RR)
在介绍MVCC之前,我们要先介绍两个概念:
当前读:
读取的是当前记录的最新版本,读取的时候还需要保证其他并发事务不能修改当前记录,会对当前记录加锁。对于我们日常的select......lock in share mode,select......for update,update,insert,delete都是一种当前读。
快照读:
读取的是数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。常见隔离级别下的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_id | ReadView创建者的事务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 日志记录了事务执行过程中对数据所做的修改操作,用于在事务回滚或撤销时恢复数据到之前的状态。而版本链则是指数据库中维护的多个数据版本之间的关系,包括当前版本、已提交版本和未提交版本等。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!
相关文章:

【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理
前言: 在当今互联网时代,数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言,高效地处理并发访问和事务管理是至关重要的。多版本并发控制(MVCC)是一种数据库事务处理的技术,旨…...

【LAMMPS学习】八、基础知识(1.6) LAMMPS 与其他代码耦合
8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…...

ArrayList中多线程的不安全问题
ArrayList中的不安全问题 正常的输出 List<String> list Arrays.asList("1","2","3"); list.forEach(System.out::println);为什么可以这样输出,是一种函数是接口,我们先过个耳熟 Arrys.asList是返回一个ArrayL…...
ALTER TABLE 之 定点变更(in-place alter)
定点变更算法可以提供优于慢速变更算法的诸多性能优势: 定点变更算法: 1,增加了表的可用性 ALTER TABLE操作使用定点变更算法时,其他用户稍后可以访问该表,因为数据库服务器只在更新表定义和重建包含更改列的索引时才锁…...

【RAG实践】Rerank,让大模型 RAG 更近一步
RAGRerank原理 上一篇【RAG实践】基于LlamaIndex和Qwen1.5搭建基于本地知识库的问答机器人 我们介绍了什么是RAG,以及如何基于LLaMaIndex和Qwen1.5搭建基于本地知识库的问答机器人,原理图和步骤如下: 这里面主要包括包括三个基本步骤&#…...
私有化客服系统:在线客服搭建与部署的创新之路
随着互联网技术的飞速发展,企业与客户之间的沟通方式也在不断地演变。在这个信息爆炸的时代,一个高效、便捷、智能的在线客服系统成为了企业提升服务质量、增强客户满意度的重要工具。本文将详细介绍在线客服系统的构建、部署以及私有化客服的优势&#…...

VM-UNet: Vision Mamba UNet for Medical Image Segmentation
VM-UNet: Vision Mamba UNet for Medical Image Segmentation VM-UNet:基于视觉Mamba UNet架构的医学图像分割 论文链接:http://arxiv.org/abs/2402.02491 代码链接:https://github.com/JCruan519/VM-UNet 1、摘要 文中利用状态空间模型SS…...
面向对象编程:在Python中的面向对象编程奥秘
面向对象编程在Python中的奥秘 在编程的世界里,面向对象编程(Object-Oriented Programming,简称OOP)是一种非常重要的编程范式。它改变了我们思考问题和设计代码的方式。Python作为一种支持面向对象的语言,为我们提供…...

考研数学|零基础100分保底复习方案+资料分享
目标100分其实很好实现,只要你有决心,不需要去看任何人的学习技巧 其实基础差,你只要专攻基础就好了,现在的很多考研课程和资料真的很不照顾基础不好的同学,好像就默认你什么都会一样,但是还是有对于基础差…...
【MATLAB源码-第29期】基于matlab的MIMO,MISO,SIMO,SISO瑞利rayleigh信道容量对比。
操作环境: MATLAB 2022a 1、算法描述 1. SISO(单输入单输出): - SISO 是指在通信系统中,只有一个天线用于传输信号,也只有一个天线用于接收信号的情况。这是最简单的通信方式。 2. SIMO(单…...

JRT高效率开发
得益于前期的基础投入,借助代码生成的加持,本来计划用一周实现质控物维护界面,实际用来四小时左右完成质控物维护主体,效率大大超过预期。 JRT从设计之初就是为了证明Spring打包模式不适合软件服务模式,觉得Spring打包…...

Spring Boot 切面的一种的测试方法,java中级开发面试
void afterReturnName() { Assertions.assertEquals(studentController.getNameById(123L).getName(), "测试姓名Yz");} } 但往往切面中的逻辑并非这么简单,在实际的测试中其实我们也完成没有必要关心在切面中到底发生了什么(发生了什么应该在…...
嵌入式自学路线-高薪路线(持续更新,欢迎关注)
1 入门:51STM32 主要学习内容中断、定时器、串口、NAND FLASH、网络控制器、LCD屏、触摸屏等的工作原理。学习资源推荐视频:野火,正点原子书籍:野火,正点原子学习建议如果你以后的方向是驱动开发,这部分学…...
SpringMVC的运行流程
SpringMVC的运行流程可以概括为以下几个主要步骤: 用户发送请求: 用户通过浏览器或其他客户端发送HTTP请求到服务器。 前端控制器(DispatcherServlet)接收请求: SpringMVC的前端控制器(通常是DispatcherSe…...
成绩分析 蓝桥杯 java
成绩分析 小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。 请计算这次考试的最高分、最低分和平均分。 输入格式 输入的第一行包含一个整数 n,表示考试人数。 接下来 n 行,每行包含一…...
计算psnr ssim niqe fid mae lpips等指标的代码
以下代码仅供参考,路径处理最好自己改一下 # Author: Wu # Created: 2023/8/15 # module containing metrics functions # using package in https://github.com/chaofengc/IQA-PyTorch import torch from PIL import Image import numpy as np from piqa import P…...

OpenHarmony开发技术:【国际化】实例
国际化 如今越来的越多的应用都走向了海外,应用走向海外需要支持不同国家的语言,这就意味着应用资源文件需要支持不同语言环境下的显示。本节就介绍一下设备语言环境变更后,如何让应用支持多语言。 应用支持多语言 ArkUI开发框架对多语言的…...
c++子类和父类成员函数重名
子类和父类返回值参数相同,函数名相同,有virtual关键字,则由对象的类型决定调用哪个函数。子类和父类只要函数名相同,没有virtual关键字,则子类的对象没有办法调用到父类的同名函数,父类的同名函数被隐藏了,…...

《C++程序设计》阅读笔记【7-堆和拷贝构造函数】
🌈个人主页:godspeed_lucip 🔥 系列专栏:《C程序设计》阅读笔记 本文对应的PDF源文件请关注微信公众号程序员刘同学,回复C程序设计获取下载链接。 1 堆与拷贝构造函数1.1 概述1.2 分配堆对象1.3 拷贝构造函数1.3.1 默…...
洛谷 P1048 [NOIP2005 普及组] 采药
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...