【MySQL】MVCC详解, 图文并茂简单易懂
欢迎来到啊妮莫的学习小屋 |
祝读本文的朋友都天天开心呀 |
目录
- MVCC简介
- 快照读与当前读
- 快照读
- 当前读
- 隔离级别
- 隐藏字段和Undo Log版本链✨
- MVCC原理--ReadView✨
- ReadView简介
- 设计思路
- 适用隔离级别
- 重要内容
- ReadView规则
- MVCC整体流程
- 不同隔离级别下的MVCC
- 读已提交
- 可重复读
- 总结
MVCC简介
MVCC
也称: 多版本并发控制
. 顾名思义, MVCC是通过数据行的多个版本管理来实现数据库的并发控制. MVCC
使得在InnoDB
的事务隔离级别下, 执行一致性读
操作有了保证. 简单来说就是: 在需要读取一些正在被另一个事务更新的行数据时, 读取之前的历史版本数据(旧数据); 而不需要等待另一个事务释放锁.
并不是所有的存储引擎都支持MVCC
技术, 本文讲解的是MySQL
中InnoDB
存储引擎下的MVCC
机制.
快照读与当前读
MVCC
机制主要解决的是读--写冲突
问题, 提高数据库的并发性能.
当发生读写冲突时:
读
采用快照读
, 不加锁 非阻塞并发读
写
采用当前读
, 加锁
MVCC
机制本质上是采用了乐观锁思想
快照读
又名一致性读
, 读取到的是快照数据. 不加锁的简单SELECT都是快照读.
例如:
SELECT * FROM student WHERE...
快照读
可能读到的并不一定是数据的最新版本, 而有可能是之前的历史版本.
快照读可以形象的理解为我们生活中的照片, 拍摄到的画面都是过去式.
当前读
当前读
读取到的是 最新版本数据.
读取时需要保证其他并发事务不能修改当前记录, 因此需要加锁
.
例如:
SELECT * FROM student LOCK IN SHARE MODE; # 共享锁
SELECT * FROM student FOR UPDATE; # 排他锁
-- 修改操作对应的排他锁
INSERT INTO student VALUES ...
DELETE FROM student WHERE ...
UPDATE student SET ...
当前读可以形象的理解为生活中的直播, 看到到的画面是实时的, 最新的.
隔离级别
事务有四种隔离级别: 读未提交
, 读已提交
, 可重复读
, 串行化
.
读未提交
: 其他事务可以看见未提交事务做出的数据改变. 也就是会发生脏读
.读已提交
: 其他事务只能看到已经提交事务做出的数据改变. 若另一个事务不断的更新某一行数据并提交, 那么读取出来的数据前后不一致, 即不可重复读
.可重复读
: 解决了不可重复读
问题, 确保同一事务多次读取结果一致. 但是依然会发生幻读
问题–另一个事务插入新的数据行, 那么读取该范围内的数据时, 会发现新的"幻影"行.串行化
: 最严格的隔离级别, 通过加锁
避免了脏读, 不可重复读和幻读, 但是性能较差.
MySQL
的默认隔离级别是可重复读
可重复读
隔离级别解决了脏读
和不可重复读
问题, 未解决幻读
问题.
但是, MySQL
中的MVCC
机制解决了幻读
问题! 它可以在大多数情况下代替行级锁, 提高数据库的事务并发能力.
隐藏字段和Undo Log版本链✨
对于使用InnoDB
存储引擎的表来说, 其聚簇索引中的行数据包含了三个隐藏字段: row_id
, trx_id
, roll_pointer
.
其中trx_id
和roll_pointer
使得用户记录生成一条Undo Log版本链.
trx_id
: 这个字段记录了最后修改行记录的事务ID
.roll_pointer
: 这个字段是一个指针, 指向该行记录的回滚段, 在发生事务回滚时用来撤销行记录的修改.
例如: students的表数据如下
mysql> SELECT * FROM students WHERE id=1;
+------+----------+----------+
| id | stu_name | major |
+------+----------+----------+
| 1 | 张三 | 软件工程 |
+------+----------+----------+
1 row in set (0.00 sec)
假设插入该记录的事务ID
等于8, 则该条记录的示意图如下所示:
🌈
注意: insert undo只在事务回滚起作用, 当事务提交后, 该类型的undo日志就没有用了, 它占用的UndoLog Segment也会被系统回收(也就是该undo日志占用的Undo页面链表要么被重用, 要么被释放).
假设之后两个事务ID
分别为10, 20的事务对该条数据进行UPDATE操作, 操作流程如下:
🌈
注意: 不能两个事务交叉更新同一条数据! 即: 一个事务修改另一个未提交的事务修改过的数据 (脏写).
InnoDB使用锁来保证不会有脏写的情况发生: 当一个事务更新了某条记录后, 会给这条记录加锁; 另一个事务需要等待锁被释放后才可以更新.
每次修改, 都会记录一条undo日志
, 每一条undo日志
也都会有一个roll_pointer
字段, 将这些undo日志
串成一个链表–Undo Log 版本链
Undo Log 版本链
的头结点就是当前的最新记录. 所有版本依靠roll_ptr
字段连接成一个链表.
MVCC原理–ReadView✨
MVCC
的实现依赖于: 两个隐藏字段
, Undo Log
, ReadView
.
ReadView简介
ReadView
就是事务在使用MVCC
机制进行快照读
操作时产生的读视图
.
当事务读取数据时, 会数据库系统生成当前的一个快照, InnoDb
会为事务构造一个数组, 用于记录并维护系统中当前的活跃事务ID组
(活跃是指: 开启了但是还没有进行提交).
设计思路
适用隔离级别
ReadView
仅仅适用于读已提交
和可重复读
隔离级别, 对于这两种隔离级别, 都必须保证读到的是已经提交的事务修改过的记录. 假如另一个事务已经修改但是还没有提交, 是不能直接读取到的. 核心问题是判断版本链中哪些版本记录是当前事务可见的,这是ReadView
要解决的主要问题.
对于读未提交
: 读到的就是最新版本数据.
对于串行化
: 事务排队执行, InnoDB
使用锁
机制来避免读写冲突
.
重要内容
creator_trx_id
: 创建这个ReadView
的事务ID
.trx_ids
: 在生成ReadView
时, 当前系统中活跃的读写事务的ID列表
.up_limit_id
: 活跃的事务中最小的事务ID
.low_limit_id
: 表示在生成ReadView
时系统应该分配给下一个事务的ID
, 也就是系统中最大的事务ID值.
🌈
注意: 对于只读事务, creator_trx_id 默认为0
举例:
若现有id为1, 2, 3这三个事务, 之后id=3的事务提交了;
那么一个新的读事务在生成ReadView的时, trx_ids=[1,2], up_limit_id=1, low_limit_id的值为4
ReadView规则
当需要读取某条记录的时候, 只需要按照以下步骤就可以判断该记录的某个版本是否可见.
- 当读取版本的
trx_id
=creator_trx_id
, 也就是当前事务修改过的记录–可见. trx_id
<up_limit_id
, 该版本的事务已经在生成ReadView
之前就提交了–可见.trx_id
>=low_limit_id
, 该版本的事务是在生成ReadView
之后才开启的–不可见.up_limit_id
<=trx_id
<low_limit_id
, 则需要分情况讨论- 不在
trx_ids
列表中, 说明该事务已经提交–可见. - 在列表中, 该事务在生成
ReadView
时处于活跃状态–不可见.
- 不在
如图所示:
MVCC整体流程
- 获取自己的事务版本号:
creator_trx_id
- 生成ReadView
- 将查询到的数据, 与
ReadView
中的事务版本号进行对比 - 若可见, 则从
Undo Log
中获取历史快照, 否则顺着版本链找到下一个数据, 重复3,4. - 若最后一个版本也不可见, 则意味着这条记录对该事务是完全不可见的, 查询结果就不包含该记录.
🌈
说明: MVCC是通过隐藏字段生成的Undo Log版本链, 加上ReadView规则帮我们判断当前版本的数据是否可见.
不同隔离级别下的MVCC
读已提交
在隔离级别为读已提交
时,一个事务中的每一次 SELECT 查询都会重新获取一次Read View
🌈
注意: 此时同样的查询语句都会重新获取一次
Read View
这时如果Read View
不同,就可能产生不可重复读
或者幻读
的情况
可重复读
当隔离级别为可重复读
的时候,就避免了不可重复读
,这是因为一个事务只在第一次 SELECT 的时候会获取一次 ReadView
,而后面所有的 SELECT 都会复用这个ReadView
总结
本文介绍了MVCC
在READ COMMITTD
、REPEATABLE READ
这两种隔离级别下事务在执行快照读
操作时访问记录的版本链的过程。这样使不同事务的读-写操作
并发执行,从而提升系统性能。
核心点在于 ReadView 的原理,READ COMMITTD
、REPEATABLE READ
这两个隔离级别的一个很大不同就是生成ReadView的时机不同:
READ COMMITTD
在每一次进行普通SELECT操作前都会生成一个ReadViewREPEATABLE READ
只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。
🌈
说明: 执行DELETE语句或者更新主键的UPDATE语句并不会立即把对应的记录完全从页面中删除,而是执行一个所谓的delete mark操作; 相当于只是对记录打上了一个删除标志位,这主要就是为MVCC服务的
通过MVCC
可以解决:
-
读写冲突问题
: 通过MVCC可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升数据库并发处理能力 -
降低了死锁的概率
: 这是因为MVCC采用了乐观锁的方式. 读取数据时并不需要加锁,对于写操作,也只锁定必要的行 -
解决快照读的问题
: 当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果
如果本篇文章对你有所帮助的话, 不要忘了给我点个赞哦~ 笔芯💞
相关文章:

【MySQL】MVCC详解, 图文并茂简单易懂
欢迎来到啊妮莫的学习小屋 祝读本文的朋友都天天开心呀 目录 MVCC简介快照读与当前读快照读当前读 隔离级别隐藏字段和Undo Log版本链✨MVCC原理--ReadView✨ReadView简介设计思路适用隔离级别重要内容 ReadView规则MVCC整体流程 不同隔离级别下的MVCC读已提交可重复读 总结 M…...
中国数字化发展的问题与机会
橙蜂智能公司致力于提供先进的人工智能和物联网解决方案,帮助企业优化运营并实现技术潜能。公司主要服务包括AI数字人、AI翻译、埃域知识库、大模型服务等。其核心价值观为创新、客户至上、质量、合作和可持续发展。 橙蜂智农的智慧农业产品涵盖了多方面的功能,如智能化推荐、…...

【ROS2】☆ launch之Python
☆重点 ROS1和ROS2其中一个很大区别之一就是launch的编写方式。在ROS1中采用xml格式编写launch,而ROS2保留了XML 格式launch,还另外引入了Python和YAML 编写方式。选择哪种编写取决于每位开发人员的爱好,但是ROS2官方推荐使用Python方式编写…...

如何稳定使用 O1 / O1 Pro,让“降智”现象不再困扰?
近期,不少朋友在使用 O1 或 O1 Pro 模型时,都会碰到“降智”或“忽高忽低”的智力波动,比如无法识图、无法生成图片、甚至回答准确度也不稳定。面对这些问题,你是不是也感到头疼呢? 为了找到更可靠的解决办法…...
zookeeper监听机制(Watcher机制)
文章目录 引言I zookeeper监听机制Watcher机制实现分布式的通知功能触发事件种类Watcher的三个过程II watch机制特点一次性触发事件封装event异步发送先注册再触发常见的通知状态和事件类型III 应用案例(Kafka)Kafka的消息模型Kafka在Zookeeper中保存的元数据Kafka 基于Contr…...
docker 启动 nacos 单机模式
docker 启动 nacos 单机模式 # 拉取镜像# 启动,如果不拉镜像会自动拉取最新的 image docker run --name standalong_nacos -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODEstandalone -d nacos/nacos-server# 状态查看外部访问验证 输入部署的 docker ip 地址以及…...

学习threejs,导入babylon格式的模型
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.BabylonLoader babyl…...

03.MPLS静态LSP配置实验
MPLS静态LSP配置实验 1、实验环境2、基础配置开启全局mpls接口下开启mpls配置静态LSP配置FEC从1.1.1.1到3.3.3.3配置FEC从3.3.3.3到1.1.1.13、信息查看查看LFIB表(标签转发信息表)查看FIB表(转发信息表)查看详细FFIB表tracert lsp iptracert -vping lsp ip4、抓包验证1、实…...
程序血缘分析技术在工商银行软件工程中的应用
当前,随着软件领域技术更新换代速度的日益加快,市场需求也变得更加多样化和个性化,业界普遍通过加速产品迭代来满足客户需求,但在此过程中也暴露出一些研发管理痛点问题,如服务和程序类资产信息分散于各个不同的应用和系统中,信息归集费时费力;设计、开发和测试人员无法…...

计算机毕业设计Django+Tensorflow音乐推荐系统 音乐可视化 卷积神经网络CNN LSTM音乐情感分析 机器学习 深度学习 Flask 大
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

macOS 使用 FreeRDP 远程访问 Windows:完整指南20250109
🖥️ macOS 使用 FreeRDP 远程访问 Windows:完整指南 引言 随着远程办公需求的快速增长,跨平台远程管理已经成为不可或缺的技能之一。作为一款开源轻量的远程桌面协议实现工具,FreeRDP 为 macOS 用户提供了一个简单、高效的解决…...

Java agent
Java Agent是一种特殊的Java程序,它可以在JVM启动时或运行时动态加载,用于监控和修改其他Java应用程序的行为。通过Java Agent,开发者可以在不修改目标应用程序源码的情况下,动态地插入功能,如性能分析、日志记录…...

Web无障碍
文章目录 🟢Web Accessibility-Web无障碍🟢一、Web Accessibility-Web1. web无障碍设计2. demo3.使用相关相关开源无障碍工具条(调用可能会根据网络有点慢) 如有其他更好方案,可以私信我哦✒️总结 🟢Web Accessibility-Web无障碍…...

概率基本概念 --- 离散型随机变量实例
条件概率&独立事件 随机变量 - 离散型随机变量 - 非离散型随机变量 连续型随机变量奇异性型随机变量 概率表示 概率分布函数概率密度函数概率质量函数全概率公式贝叶斯公式 概率计算 数学期望方差协方差 计算实例 假设有两个离散型随机变量X和Y,它们代…...

毕业项目推荐:基于yolov8/yolov5/yolo11的动物检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
基于 WEB 开发的高校学籍管理系统设计与实现
标题:基于 WEB 开发的高校学籍管理系统设计与实现 内容:1.摘要 摘要:随着信息技术的不断发展,高校学籍管理系统的信息化建设已成为必然趋势。本文以高校学籍管理系统为研究对象,探讨了基于 WEB 开发的高校学籍管理系统的设计与实现。通过对系…...

阿里云发现后门webshell,怎么处理,怎么解决?
当收到如下阿里云通知邮件时,大部分管理员都会心里一惊吧!出现Webshell,大概是网站被入侵了。 尊敬的 xxxaliyun.com: 云盾云安全中心检测到您的服务器:47.108.x.xx(xx机)出现了紧急安全事件…...

HTB:Bank[WriteUP]
目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 提取出靶机TCP开放端口 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用curl对域名进行访问…...

如何用数字万用表测量是否漏电?
测量电气设备或线路是否漏电是确保安全的重要步骤。台式数字万用表(DMM)是一种常见的测试工具,它可以帮助我们检测和确认是否存在漏电现象。本文将详细介绍如何使用台式数字万用表进行漏电检测,包括准备工作、具体操作步骤和安全注…...

黑马跟学.苍穹外卖.Day04
黑马跟学.苍穹外卖.Day04 苍穹外卖-day04课程内容1. Redis入门1.1 Redis简介1.2 Redis下载与安装1.2.1 Redis下载1.2.2 Redis安装 1.3 Redis服务启动与停止1.3.1 服务启动命令1.3.2 客户端连接命令1.3.3 修改Redis配置文件1.3.4 Redis客户端图形工具 2. Redis数据类型2.1 五种常…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...