Mysql中的MVCC

news2024/12/26 21:03:10

 ”真正学会,如你般自由~“


 MVCC机制简介

        MVCC(Multi-Version-Concurrency-Control)多版本并发控制,MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程中实现事务内存。

                                                                                                                                          取自

        MVCC存在被使用于多个大型数据库软件,诸如Mysql、Oracle、PostgreSQL等。其中,在Mysql存储引擎中,MVCC机制的运用,对于Innodb支持事务,更好的处理读-写并发,提高并发性能等具有支撑作用。

 MVCC带来的好处?

        数据并发的三种场景:

🥊 写-写:  有线程安全问题,只能串行化执行。

🥊 读-写: 有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读。

🥊 读-读: 不存在任何问题,也不需要并发控制。

         MVCC主要为 读-写情况提供无锁并发控制:

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  • 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

概念辨析

💎 如何理解事务?

        说起事务的概念,其本质并不复杂。我们可以将其理解为 一组“操作逻辑”,而这套逻辑天然需要支持四大特性: 原子性、持久性、隔离性、一致性 —— ACID。

        在Mysql中,分别采用不同的措施来保证 事务这四大特性:

🎫 通过回滚机制,保证sql在执行的过程中要么都被执行成功,要么都执行失败 —— 原子性

🎫 事务一旦提交,数据就是永久的 —— 持久性

🎫 通过隔离级别,保证各个开启事务、执行SQL不会互相干扰 —— 隔离性

        Mysql唯独没有对保证 一致性做任何操作,但为保障其他三个特点所做的技术,最终就是为了保证事务的一致性!

💎 当前读 vs 快照读

当前读: 就是它读取的是记录的最新版本

快照读: 读取为历史版本

        我们可以先看一个实验,我们先将Mysql中的隔离界别调整为RC(Mysql默认的隔离级别为RR)

        重启客户端后,就可以查看到修改字段:

        创建一个新表,并在其中插入一些数据:

RC隔离级别下的事务:  

        这很符合预期,毕竟咱们设置的隔离级别就是 “RC”,即读可提交。

RR默认隔离级别下的事务:

        我们现在按照统一的操作,在RR隔离级别下会发生什么呢?

        是的,我们再也无法看到另一端启动的事务 对表做的任何修改,即便它执行了“commit”!

        直观地,在RR下两个事务进行select的表一定是不同的!而这两个不同的表,一张记录的是当前数据信息,而另一张表记录的则是历史数据!

       当我们使用,像"select lock in share mode"在锁机制下的查询sql,就能读取到对端事务提交修改的新数据。

        由此,所谓当前读 与 快照读的本质,就是查询的表信息版本的不同~通过控制、管理 不同的版本信息,从而实现隔离性~ 对于,事务能看到的版本范围,则是由 “隔离级别“ 决定!隔离级别是怎样实现,Mysql是如何管理这个过程的,则是依赖MVCC机制从根本上提供技术支持。

MVCC机制实现原理

        MVCC目的在于 —— 多版本并发控制。为了解决读-写场景下产生的问题,MVCC通过3个核心机制完成控制和管理:

🔮 3个记录的隐藏字段

🔮 undo日志

🔮 Read View

3个隐式字段

        ⛳ DB_TRX_ID:

6 byte,最近修改( 修改/插入 )事务ID,记录创建这条记录/最后一次修改该记录的事务ID

        ⛳ DB_ROLL_PTR

回滚指针,指向这条记录的上一个版本,通过这个指针,从而形成一个历史版本链。

        ⛳ DB_ROW_ID

隐含的自增 ID (隐藏主键),如果数据表没有主键, InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引。
        ⛳  flag 隐藏字段
仅用来标记, 记录被更新或删除并不代表真的删除。

        

undo日志

        undo log有两个作用:提供回滚和多个行版本控制,它是一个逻辑日志。

        当sql语句是insert\delete时,记录这条操作的同时,也会在该日志中对应插入delete\insert 语句,用于回滚。同样,如果是遇到 update命令时,也会将原数据进行一份拷贝,再进行修改,并让新表中的 回滚指针,填写原版本的地址(这里的地址,指的时undo天然可以看成一块内存缓冲区,当数据被写入内存时,天然就会携带内存地址)。

        上面的一个一个版本,我们可以称之为一个一个的快照。当我们开启快照读,就是到这里面存储的表中读取数据!至于哪些版本是我们应该看到的,就与我们下一小节的read view决定了!

read View

        所谓read view,就是事务进行 "快照读"操作时,产生出的读视图。任何一个事务启动时,都会被分配一个事务ID!而这个事务ID是线性递增的~言外之意,事务ID越小,说明该事务到来得越早!

        read view是事务进行快照读所产生的,它需不需要记录是哪个事务执行的这个操作?它需不需要保存快照读时刻下,哪些事务是“活跃的”(即未进行commit,仍处于事务状态的ID)?……

        一个Mysql服务中,一定不止一个事务启动,一定不止一次快照读产生的不止一个read view,这些东西需不需要管理? 答案是都需要!如何管理呢? 先描述,再组织~ 因此,read view其本质上就是一个结构体(类对象)!

        下面是 我们简化一下的ReadView 结构: 

class ReadView {
// 省略...
private:
  /** 高水位,大于等于这个ID的事务均不可见*/
  trx_id_t m_low_limit_id
  /** 低水位:小于这个ID的事务均可见 */
  trx_id_t m_up_limit_id;
  /** 创建该 Read View 的事务ID*/
  trx_id_t m_creator_trx_id;
  /** 创建视图时的活跃事务id列表*/
  ids_t m_ids;
  /** 配合purge,标识该视图不需要小于m_low_limit_no的UNDO LOG,
  * 如果其他视图也不需要,则可以删除小于m_low_limit_no的UNDO LOG*/
  trx_id_t m_low_limit_no;
  /** 标记视图是否被关闭*/
  bool m_closed;
};

🥎 m_ids: 用来维护Read View生成时刻,系统正活跃的事务ID

🥎 creator_trx_id: 创建该ReadView的事务ID

🥎 up_limit_id: m_ids中,最小的事务ID

🥎 low_limit_id: ReadView生成时刻系统尚未分配的下一个事务ID

        当我们获取历史版本链时,每一个事务所能看到的版本都应该是受限制的,比如一个早来到的事务,不可能了解到后到事务对表数据进行的修改,正如 古人先贤不会对当今的智能时代加以评论、享受。

        我们read view手头中,正有DB_TRX_ID能够标识事务的先后顺序……

        这个可见性过程是怎样的?我们可以参照如下流程:

🏀 此时到来一个 creator_ID事务ID,它现在进行了一次快照读,生产read view,记录下了当前活跃的事务ID,更新了up_limit_id \ low_limit_id。它会去undo日志中,寻找任意一条记录,并获取上面的 DB_TRX_ID。

🏀 DB_TRX_ID < up_limit_id。如果小于,则事务能够看到这条记录。反之,我们继续往下走~

🏀 DB_TRX_ID >= low_limit_id。如果大于,则该事务不能看到这条记录,反之我们继续往下走~

🏀 DB_TRX_ID IN [m_ids]。如果该事务ID不存在活跃事务之中,那么就能看到这条记录,反之就不能。

RR与RC机制的本质区别

        总结这两种隔离级别的区别就是一句话,” 形成快照的时机不同 “。

RC: 每一次查询都会创建read view,保证读取当前最新版本。

RR:  只能生产一次read view,之后的一切查询读取都只能按照这个read view读取。

        正是RC每次快照读,都会形成Read View,所以,RC才会有不可重复读问题。


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

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

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

相关文章

Editor.md-编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

[LeetCode][426]【学习日记】将二叉搜索树转化为排序的双向链表——前驱节点pre 和 当前节点cur 的使用

题目 426. 将二叉搜索树转化为排序的双向链表 将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。 对于双向循环列表&#xff0c;你可以将左右孩子指针作为双向循环链表的前驱和后继指针&#xff0c;第一个节点的前驱是最后一个节点&#xff0c;最后一个节点的后继是第…

力扣--深度优先算法/回溯算法90.子集Ⅱ

思路分析&#xff1a; 成员变量&#xff1a; result: 用于存储最终的子集结果。path: 用于存储当前正在构建的子集。 DFS函数&#xff1a; dfs(vector<int>& nums, int start): 递归地生成子集。 从给定的start索引开始遍历数组。如果当前元素与前一个元素相同&#…

论文阅读FCN-Transformer Feature Fusion for PolypSegmentation

本文提出了一种名为Fully Convolutional Branch-TransFormer (FCBFormer)的图像分割框架。该架构旨在结合Transformer和全卷积网络&#xff08;FCN&#xff09;的优势&#xff0c;以提高结肠镜图像中息肉的检测和分类准确性。 1&#xff0c;框架结构&#xff1a; 模型采用双分…

Java项目:46 ssm005基于SSM框架的购物商城系统+jsp(含文档)

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 项目是单体ssm电商水果平台&#xff0c;包括前台商城平台及后台管理系统 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流…

linux中查看目录文件(ls)用法:

查看目录下的文件&#xff1a;ls&#xff08;list&#xff09; 作用 查看目录下的内容 格式 ls -参数 操作对象参数 参数功能-l以长格形式显示文件和目录的详细信息,ls命令默认只显示名称的短格式。-d显示指定目录本身的信息,而不显示目录下的各个文件和子目录的信息。-…

【三分钟学会Redis 客户端常用命令】redis数据库、对象、字符串、列表、集合、哈希、过期设置等

目录 1. 数据库&#xff1a;2. 键&#xff1a;3. 值&#xff1a;字符串&#xff1a;列表&#xff1a;哈希&#xff1a;集合&#xff1a;有序集合&#xff1a; 4. 键过期设置&#xff1a; 1. 数据库&#xff1a; 切换数据库命令&#xff1a;select index清空数据库&#xff08;…

链表与归并排序

一个C#链表实例 链表&#xff0c;主要是“链”每个类中&#xff0c;都包含一个指向后一个节点的指针 class ListNode{public string Name { get; set; }public ListNode Next;public ListNode(string name){this.Name name;this.Next null;}}基本练成链子&#xff0c;对于插…

CSS 02

1.复合选择器 &#xff08;1.1&#xff09;后代选择器 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&q…

[软件工具]yolo实例分割数据集转labelme的json格式

软件界面&#xff1a; YOLO实例分割数据集转LabelMe JSON格式软件是一款功能强大的数据转换工具&#xff0c;旨在将YOLO&#xff08;You Only Look Once&#xff09;实例分割数据集转换为LabelMe的JSON格式&#xff0c;以满足不同图像标注软件之间的数据共享需求。 该软件具有…

ChatGLM:基于ChatGLM-6B使用ptuning进行微调,实现类instruction的效果

由于业务需要&#xff0c;调研下怎么训练一个虚拟角色出来&#xff0c;所以找了一些文档参考&#xff0c;其中有一个基于ChatGLM-6B使用ptuning进行微调&#xff0c;实现类instruction的效果的现成的项目&#xff0c;给大家分享下。 一、介绍 由于ChatGLM-6B 不支持instructio…

springMVC下载文件

目录 &#x1f36d;&#x1f36c;下载页面&#xff08;其实就一个超链接&#xff09; &#x1f36d;&#x1f36c;下载的具体操作 &#x1f36d;&#x1f36c;结果 承接上传文件&#xff0c;接下来看看下载文件的操作及注意事项 下载页面&#xff08;其实就一个超链接&…

EChart使用(折柱混合图,饼图)

ECharts&#xff0c;一个使用 JavaScript 实现的开源可视化库&#xff0c;可以流畅的运行在 PC 和移动设备上&#xff0c;兼容当前绝大部分浏览器&#xff0c;底层依赖矢量图形库 ZRender&#xff0c;提供直观&#xff0c;交互丰富&#xff0c;可高度个性化定制的数据可视化图表…

LLVM-3.5 —— 01记,编译 LLVM 3.5.0 clang and clang-query

包括编译&#xff1a;clang clang-tools-extra 0, prepare env sudo apt install llvm sudo apt install clang 使用最新的g 会出错。 1, source code $ git clone --recursive $ cd llvm-project $ git checkout llvmorg-3.5.0 $ cp -r ./clang ./llvm/tools/ $ mkdir llv…

机器学习-04-分类算法-02贝叶斯算法

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中分类算法&#xff0c;本篇为分类算法与贝叶斯算法部分。 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 懂业务会选择合适的算法数据处理算法训练算法调优算法融合 算法评估持续调优工程…

Java宝典-实战小项目:图书管理系统

目录 1. 功能介绍及效果演示2. 整体框架的搭建2.1 book包2.2 operation包2.3 user包2.4 Main 3. 相关功能的实现3.1 Add(新增图书)3.2 Borrow(借阅图书)3.3 Change(修改信息)3.4 Delete(删除图书)3.5 Exit(退出系统)3.6 Return(归还图书)3.7 Search(查找)3.8 Show(展示书架) 老…

Python绘图-14绘制3D图(下)

14.7绘制3D等高线图个性化colormap 14.7.1图像呈现 14.7.2绘图代码 import numpy as np # 导入numpy库&#xff0c;numpy是Python的一个强大的数值计算扩展程序库&#xff0c;支持大量的维度数组与矩阵运算。 import matplotlib.pyplot as plt # 导入matplotlib的绘图模块p…

hyperf 二十六 数据迁移 二

教程&#xff1a;Hyperf 参考文章hyperf 二十五 数据迁移 一-CSDN博客 根据之前写的数据迁移的文章&#xff0c;已经说明Hyperf\Database\Schema\Schema::create()实际运行Hyperf\Database\Schema\Grammars\MySqlGrammar::compileCreate()生成的sql字符串。 文档所谓"在…

Games101笔记-计算机图形学概述

光栅化&#xff1a;把三维空间的几何形体显示在屏幕上 实时&#xff1a;每秒30帧的画面 曲线和曲面&#xff1a; 如何表示一条光滑曲线&#xff0c;如何表示曲面如何用简单的曲面通过细分的方法得到更复杂的曲面在形状发生变化时&#xff0c;面要如何变化&#xff0c;如何保…

STM32F103 CubeMX 定时器输出PWM控制呼吸灯

STM32F103 CubeMX 定时器输出PWM控制呼吸灯 1. 生成代码1. 1 配置外部时钟&#xff0c;SWD口1.2 配置定时器31.3 配置定时器2 2. 代码编写的部分 使用的cubmx 软件的版本&#xff1a;6.2.0 最新版本 6.10&#xff08;2024年3月11日&#xff09; 1. 生成代码 1. 1 配置外部时钟…