当前位置: 首页 > news >正文

MySQL--深入理解MVCC机制原理

什么是MVCC?

MVCC全称 Multi-Version Concurrency Control,即多版本并发控制,维持一个数据的多个版本,主要是为了提升数据库的并发访问性能,用更高性能的方式去处理数据库读写冲突问题,实现无锁并发。

什么是快照读和当前读?

  • 快照读:不加锁非阻塞读,快照读要求数据库隔离级别不能是串行化,否则会退化到当前读,快照读是基于多版本并发控制的,因为是基于多版本并发控制,所以快照读可能读取的不是最新的数据。
  • 当前读:当前读就是读取最新的数据版本,快照读读取的时候,会对读取的数据加锁,读取的时候其他事务不能修改当前数据。

MVCC和快照读、当前读的关系?

MVCC 多版本并发控制,而快照就是数据的一个版本,MVCC 的无锁并发就是依赖快照读机制实现的。

MVCC的实现原理?

MVCC 实现依赖于数据库记录中的三个隐式字段、undo日志、Read View 版本链,本篇讨论皆基于 MySQL 的 InnoDB 存储引擎。

三个隐式字段:

隐式字段,是我们正常来看看不到的字段,数据库的每行数据除了我们看到的字段之外,还有三个我们看不到的字段。

  • DB_TRX_ID:记录当前事务最后一次修改的事务ID,即事务 ID,事务 ID 是递增的。
  • DB_ROW_ID:隐藏的自增主键ID,如果数据库没有主键ID,数据库会自动生成一个 6个字节的 DB_ROW_ID。
  • DB_ROLL_PTR:回滚指针,指向上一个数据版本。

简单图例:

在这里插入图片描述

undo log 日志:

我们都知道undo log 日志是回滚日志,是数据库保证数据一致性的一个支撑,当出现异常情况时候,通过 undo log 日志来进行数据回滚,其实它还有其他作用,undo log 又分为两种,如下:

  • insert undo log,insert 操作时候产生的日志,只会在发生异常需要进行回滚的时候使用,事务提交后,undo log 就没有用处了,就会被丢弃。
  • update undo log 和 delete undo log,这两类 undo log 不仅在事务回滚时候要用到,同时在快照读的时候也会用到。

undo log 也会记录一条版本链表,每次修改数据的时候,数据库会先把当前数据拷贝一份到 undo log中,然后再对数据进行修改,最在undo log 中最新修改的数据副本会在链的头部,同时它有一个回滚指针指向他的上一个版本。

Read View:

Read View 是事务执行快照读产生的视图,在事务执行快照读的时候,系统会以当前时刻生成一个快照,以此来维护系统此时活跃的事务id,用来做可见性判断,当某个事务进行快照读的时候,我们根据 Read View 来判断当前事务可以读取哪个版本的数据,然后就去该数据的 undo log 里面找数据,当然也可能是读取最新的数据。

Read View 遵守可见性规则,它的三个属性如下:

  • trx_list:用来维护 Read View 生成时候系统活跃的事务ID,是一个列表。
  • up_limit_id:活跃事务ID中最小的ID。
  • low_limit_id:Read View 生成时候,系统将要分配的下一个事务ID。

可见性算法主要是把要修改的数据的最新版本的事务ID,即DB_TRX_ID取出来,与当前系统中活跃的其他事务ID去对比,而Read View 就维护了这些活跃的事务ID,如果在 Read View 中找不到合适条件的数据记录,就会去 undo log 日志根据回滚指针 DB_ROLL_PTR 来找数据记录直到找到为止。

Read View 的比较流程如下:

注意事务ID 是递增的。

  • 第一步,比较 DB_TRX_ID < up_limit_id, 是否小于活跃事务 Read View中最小的事务ID,如果小于,则当前事务能看到 DB_TRX_ID 所在的记录,否则进入第二个判断。
  • 第二步,比较 DB_TRX_ID >=low_limit_id, 是否大于等于下一个将要发生的事务ID,如果大于等于则代表 DB_TRX_ID 所在的记录在 Read View生成后才出现的,那对当前事务肯定不可见,否则进入第三个判断。
  • 第三步, 判断 DB_TRX_ID 是否在活跃事务 Read View 之中,如果在,则代表我 Read View 生成时刻,你这个事务还在活跃,还没有Commit,你修改的数据,我当前事务也是看不见的,如果不在,则说明,这个事务在 Read View 生成之前就已经 Commit 了,因为第一步、第二步已经判断了是否小于最小活跃事务ID和是否是将要发生的事务ID,两者都不是,同时又不在 活跃事务 Read View 中,只能说明在这个事务 Read View 在当前是事务发生之前了,当前事务理所当然能够看到。

简易流程如下:

在这里插入图片描述

读已提交(Read Committed)、可重复读(Repeatable Read) 隔离级别下的快照读的区别?

读已提交(Read Committed)、可重复读(Repeatable Read) 隔离级别下的快照读最大的区别就是生成 Read View 时机不同。

  • 可重复读(Repeatable Read) 隔离级别下,一个事务只有在第一次读取数据的时候生成一个Read View,Read View 记录当前活跃的事务ID,后面继续读取数据时候,如果用到快照读,那他使用的还是第一次读取时候的 Read View,这也是为什么可重复读(Repeatable Read) 隔离级别下,看不到别的事务的修改记录的原因。
  • 读已提交(Read Committed) 隔离级别下,事务开启后,每次使用快照读的时候,都会重新生成一个活跃事务ID,第一读取和第二次读取使用的不是同一个 Read View,那第二次读取的时候,第一次读取时候的 Read View 中的某些事务可能已经提交了,那在第二次快照读的时候就可以看到了,这也是在读已提交(Read Committed) 隔离级别下可以看到别的事务提交的记录的原因 。

MVCC解决了什么问题?

想要知道MVCC解决了什么问题,我们要先知道数据库多个事务并发访问会有什么问题,数据库并发访问场景如下:

  • 读读并发:多个事务同时读取同一份数据,不存在问题,无需进行并发控制。
  • 读写并发:多个事务同时读写同一份数据,有线程安全问题,可能会脏读、幻读、不可重复度问题。
  • 写写并发:多个事务同时对同一份数据写,可能会有更新丢失的情况。

而MVCC 就是解决以上三种并发中的读写并发问题,是一种无所并发控制,可以解决脏读、不可重复读问题,可以解决部分场景的幻读问题。

什么是幻读?MVCC可以解决幻读问题吗?

MVCC 可以解决快照读的幻读问题,MVCC 机制是依赖 快照读、undo log、Read View 来实现的,可以解决快照读的幻读问题,但是不能解决 update、delete 的幻读问题,因为这些操作是当前读。

以下讨论基于可重复读(Repeatable Read) 隔离级别。

当前读幻读演示:

时间事务A事务B
1开始事务
2第一次查询:select * from user where id > 1;
3开始事务
4执行insert: INSERT INTO user(id, user_name, user_code, age, address, hobby)VALUES(6, ‘赵六’, ‘TC-00000006’, 26, ‘广西’, ‘羽毛球’);
5提交事务
6第二次查询:select * from user where id > 1;
7修改数据:update user set name = ‘赵六国’ where id = 6;
8第三次查询:select * from user where id >1;
9提交事务

流程解释:

  • 在第2个时间点的时候,快照读,可以得到 id 大于 1的数据。
  • 在第6个时间点的时候,虽然时间点4插入了一条 id 为6的数据,并且在时间点5提交了事务,但是时间点6还是查询不到 id 为6的这条数据,查询结果和第2个时间点的查询结果没有区别。
  • 在第7个时间点的时候,查询结果就有了变化,因为 update 操作是当前读,而事务B在第5个时间点已经提交了一条 id 为6的数据,根据当前读的规则,此刻是可以读取到 id 为6 的数据,也就可以更新 id 为 6 的数据。
  • 第8个时间点的时候,执行第三次查询,此时是基于当前最新版本查询的,所以会查询到事务B提交的 id 为6的数据,对比第一次、第二次查询,多出了 id 为6的数据,这就是幻读

当前读的幻读问题怎么解决?

加锁解决,关于锁的介绍,传送门如下:

MySQL–锁机制详解

#共享锁
SELECT * FROM user LOCK IN SHARE MODE;  
# 排他锁
SELECT * FROM user FOR UPDATE; 
# 排他锁
INSERT INTO  user 
# 排他锁
UPDATE user 
# 排他锁
DELETE FROM  user 

注意:INSERT、UPDATE 、DELETE 操作数据库默认加排他锁。

解决幻读问题演示:

时间事务A事务B
1开始事务
2第一次查询:select * from user where id > 5 lock in share mode;
3事务A显示加了间隙锁
4开始事务
5执行insert: INSERT INTO user(id, user_name, user_code, age, address, hobby)VALUES(6, ‘赵六’, ‘TC-00000006’, 26, ‘广西’, ‘羽毛球’);
6阻塞了,处于等待状态
7select * from user where id > 5
8提交事务
9事务A提交了,释放了间隙锁,事务B 执行 INSERT 操作
10提交事务
  • 在第2个时间点的时候,使用 lock in share mode 语法显示加锁了,不仅表中存在的数据加锁了,而且还给 id>5 的区间加了间隙锁
  • 因为时间点2的操作,给 id>5 的区间加了间隙锁 ,所以事务B 在时间点5的时候执行 INSERT 操作的时候,出现了阻塞。
  • 因为时间点5的 INSERT 操作被阻塞了,所以这次查询的数据跟时间点2的查询结果完全一致。
  • 事务B想要执行 INSERT 成功,必须要等待事务A 提交事务释放锁,这就解决了幻读问题。

MVCC可以解决更新丢失问题吗?

MVCC 解决的是读写并发问题,而更新丢失是写写并发问题,MVCC不能解决更新丢失问题,更新丢失依赖数据库的隔离级别来解决。

如有不正确的地方请各位指出纠正。

相关文章:

MySQL--深入理解MVCC机制原理

什么是MVCC&#xff1f; MVCC全称 Multi-Version Concurrency Control&#xff0c;即多版本并发控制&#xff0c;维持一个数据的多个版本&#xff0c;主要是为了提升数据库的并发访问性能&#xff0c;用更高性能的方式去处理数据库读写冲突问题&#xff0c;实现无锁并发。 什…...

数据挖掘简介与应用领域概述

数据挖掘&#xff0c;作为信息技术领域中的重要分支之一&#xff0c;旨在从大量数据中发现潜在的模式、关联和趋势&#xff0c;以提取有用的信息和知识。在信息爆炸时代&#xff0c;大量数据的积累成为了常态&#xff0c;数据挖掘技术的出现填补了人们处理这些数据的空白&#…...

瑞熙贝通打造智慧校园实验室安全综合管理平台

一、建设思路 瑞熙贝通实验室安全综合管理平台是基于以实验室安全&#xff0c;用现代化管理思想与人工智能、大数据、互联网技术、物联网技术、云计算技术、人体感应技术、语音技术、生物识别技术、手机APP、自动化仪器分析技术有机结合&#xff0c;通过建立以实验室为中心的管…...

openstack调整虚拟机CPU 内存 磁盘 --来自gpt

在OpenStack中调整虚拟机&#xff08;即实例&#xff09;的CPU、内存&#xff08;RAM&#xff09;和磁盘大小通常涉及到以下几个步骤&#xff1a;首先&#xff0c;确定你要修改的实例名称或ID&#xff1b;其次&#xff0c;根据需要调整的资源类型&#xff0c;使用相应的命令进行…...

【IC设计】Verilog线性序列机点灯案例(三)(小梅哥课程)

声明&#xff1a;案例和代码来自小梅哥课程&#xff0c;本人仅对知识点做做笔记&#xff0c;如有学习需要请支持官方正版。 文章目录 该系列目录设计目标设计思路RTL及Testbench代码RTL代码Testbench代码 仿真结果上板视频 该系列目录 Verilog线性序列机点灯案例(一)&#xff…...

【打工日常】使用Docker部署团队协作文档工具

一、ShowDoc介绍 ​ShowDoc是一个适合IT团队共同协作API文档、技术文档的工具。通过showdoc&#xff0c;可以方便地使用markdown语法来书写出API文档、数据字典文档、技术文档、在线excel文档等等。 响应式网页设计&#xff1a;可将项目文档分享到电脑或移动设备查看。同时也可…...

(一)Neo4j下载安装以及初次使用

&#xff08;一&#xff09;下载 官网地址&#xff1a;Neo4j Graph Database & AnamConnect data as its stored with Neo4j. Perform powerful, complex queries at scale and speed with our graph data platform.https://neo4j.com/ &#xff08;二&#xff09;安装并配…...

QT for Mcu的学习建议

QT for MCU&#xff08;微控制器单元&#xff09;是一个相对较新的领域&#xff0c;它允许在资源受限的微控制器上运行Qt框架&#xff0c;从而为嵌入式设备带来丰富的用户界面和跨平台的开发体验。以下是一些建议&#xff0c;可以帮助你开始学习Qt for MCU&#xff1a; 理解Qt…...

【C语言初阶(五)】数组

❣博主主页: 33的博客❣ ▶文章专栏分类: C语言从入门到精通◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; 目录 1. 前言2.一维数组的概念3.一维数组的创建和初始化3.1数组的创建3.2数组的初始化3.3数组的类型 4.一维数组的使用4.1数组下标4.2数组元素打印4.4数组元…...

词令微信小程序怎么添加到我的小程序?

微信小程序怎么添加到我的小程序&#xff1f; 1、找到并打开要添加的小程序&#xff1b; 2、打开小程序后&#xff0c;点击右上角的「…」 3、点击后底部弹窗更多选项&#xff0c;请找到并点击「添加到我的小程序」&#xff1b; 4、添加成功后&#xff0c;就可以在首页下拉我的…...

【PyTorch】基础学习:在Pycharm等IDE中打印或查看Pytorch版本信息

【PyTorch】基础学习&#xff1a;在Pycharm等IDE中打印或查看Pytorch版本信息 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1…...

SDN网络简单认识(2)——南向接口

目录 一、概述 二、南向接口与南向协议 2.1 南向接口&#xff08;Southbound Interfaces&#xff09; 2.2 南向协议&#xff08;Southbound Protocols&#xff09; 2.3 区别与联系 三、常见南向协议 2.1 OpenFlow 2.2 OVSDB&#xff08;Open vSwitch Database Manageme…...

如何保存缓存和MySQL的双写一致呢?

如何保存缓存和MySQL的双写一致呢&#xff1f; 所谓的双写一致指的是&#xff0c;在同时使用缓存(如Redis)和数据库(如MySQL)的场景下,确保数据在缓存和数据库中的更新操作保持一致。当对数据进行修改的时候&#xff0c;无论是先修改缓存还是先修改数据库&#xff0c;最终都要保…...

第十三篇:复习Java面向对象

文章目录 一、面向对象的概念二、类和对象1. 如何定义/使用类2. 定义类的补充注意事项 三、面向对象三大特征1. 封装2. 继承2.1 例子2.2 继承类型2.3 继承的特性2.4 继承中的关键字2.4.1 extend2.4.2 implements2.4.3 super/this2.4.4 final 3. 多态4. 抽象类4.1 抽象类4.2 抽象…...

PyTorch学习笔记之基础函数篇(四)

文章目录 2.8 torch.logspace函数讲解2.9 torch.ones函数2.10 torch.rand函数2.11 torch.randn函数2.12 torch.zeros函数 2.8 torch.logspace函数讲解 torch.logspace 函数在 PyTorch 中用于生成一个在对数尺度上均匀分布的张量&#xff08;tensor&#xff09;。这意味着张量中…...

C++/CLI学习笔记3(快速打通c++与c#相互调用的桥梁)

c/cli变量和操作符 3.1:什么是变里 变量是存储数据以便应用程序临时使用的内存位置&#xff0c;具有名称、类型和值。变量值在应用程序执行期间可能改变&#xff0c;变量名也是。变量使用前必须声明&#xff0c;即指定类型和提供名称。变量的类型决定了值的范围以及能执行的操…...

unity

Unity官方下载_Unity最新版_从Unity Hub下载安装 | Unity中国官网 Unity Remote - Unity 手册 登陆账号&#xff0c;找到一个3d 免费资源 3D Animations & Models | Unity Asset Store unity 里面window->package Manager 里面可以看到自己的asset &#xff0c;下载后…...

考研复习C语言初阶(3)

目录 一.函数是什么? 二.C语言中函数的分类 2.1库函数 2.2自定义函数 三.函数的参数 3.1实际参数&#xff08;实参&#xff09; 3.2 形式参数&#xff08;形参&#xff09; 四.函数的调用 4.1 传值调用 4.2 传址调用 五. 函数的嵌套调用和链式访问 5.1 嵌套调用 5…...

CCF 202009-3 点亮数字人生(拓扑排序)

题目背景 土豪大学的计算机系开了一门数字逻辑电路课&#xff0c;第一个实验叫做“点亮数字人生”&#xff0c;要用最基础的逻辑元件组装出实际可用的电路。时间已经是深夜了&#xff0c;尽管实验箱上密密麻麻的连线已经拆装了好几遍&#xff0c;小君同学却依旧没能让她的电路正…...

Docker笔记-进入运行中的镜像,查看日志等操作

docker搭建好后&#xff0c;查看运行的docker镜像&#xff1a; docker ps -a 进入运行的容器&#xff0c;命令如下&#xff1a; docker exec -it <容器ID> /bin/bash # 或者&#xff0c;直接用容器里面的命令&#xff0c;比如mysql镜像 docker exec -it <容器ID>…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...