MySQL 之多版本并发控制 MVCC

news2024/11/15 16:24:18

MySQL 之多版本并发控制 MVCC

  • 1、MVCC 中的两种读取方式
    • 1.1、快照读
    • 1.2、当前读
  • 2、MVCC实现原理之 ReadView
    • 2.1、隐藏字段
    • 2.2、ReadView
    • 2.3、读已提交和可重复读隔离级别下,产生 ReadView 时机的区别
  • 3、MVCC 解决幻读
  • 4、总结

       MVCC(多版本并发控制) 没有正式的标准,在不同的 DBMS 中MVCC的实现方式可能不同,本文中讲解的是 InnoDB 中 MVCC 的实现机制(MySQL 其它的存储引擎并不支持 MVCC).

 

1、MVCC 中的两种读取方式

 
       MVCC 在 MySQL InnoDB 中的实现主要是为了提高数据库并发性能,用更好的方式去处理 读-写冲突,做到即使有读写冲突,也能做到 不加锁,非阻塞并发读,而这个读指的就是 快照读,而非当前读。
       当前读实际上是一种加锁的操作,是悲观锁的实现。而MVCC本质是采用乐观锁思想的一种方式。
       快照读和当前读是 MVCC 中的两种读取方式。MVCC 通过快照读和当前读两种方式,在保持事务隔离性的同时,提高了数据库的并发性能

 

1.1、快照读

 
快照读(又叫一致性读),读取的是快照数据,即不加锁的非阻塞读。不加锁的简单 select 都属于快照读。快照读的实现是基于 MVCC(多版本并发控制),在很多情况下,快照读避免了加锁操作,降低了开销。

  • 由于快照读基于 MVCC(多版本并发控制),所以快照读可能读到的并不一定是数据的最新版本,很有可能读的是之前的历史版本数据。
  • 快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读。

 

1.2、当前读

 
       当前读读取的记录是最新版本的数据,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。加锁的 SELECT,或者对数据进行增删改都会进行当前读。比如:

# 共享锁
select * from tb_table lock in share mode;
# 排它锁
select * from tb_table for update;
# 排它锁
insert into tb_table values# 排它锁
delete from tb_table where# 排他锁
update tb_table set

 

2、MVCC实现原理之 ReadView

 
MVCC 的实现依赖于:隐藏字段、undo log、ReadView.

 

2.1、隐藏字段

 
对于InnoDB引擎来说,每个行记录除了记录本身的数据之外,还存在几个隐藏的列。

  • DB_ROW_ID :如果没有为表显式的定义主键,并且表中也没有定义唯一索引,那么InnoDB会自动为表添加一个 row_id 的隐藏列作为主键。
  • DB_TRX_ID :每个事务都会分配一个事务ID,当对某条记录发生变更时,就会将这个事务的事务ID写入 trx_id 中。
  • DB_ROLL_PTR :回滚指针,本质上就是指向 undo log 的指针。
    在这里插入图片描述

2.2、ReadView

 
       在 MVCC 机制中,多个事务对同一行记录A,进行更新会产生多个历史快照,这个历史快照保存在 undo log 中。当一个事务想要查询 记录A 这行数据时,需要读取哪个版本的记录将是一个问题。ReadView 就可以解决以上 行可见性问题。

在读未提交的隔离级别下事务,查询的数据都是最新版本,所以不需要MVCC。在串行化隔离级别下的事务,InnoDB 规定使用加锁的方式来访问记录,也不需要MVCC。

ReadView 就是事务在使用 MVCC 机制进行快照读操作时产生的读视图。ReadView 主要包含了以下4个重要内容:

  • creator_trx_id,创建该 ReadView 的事务ID.

    只要在对表中的记录做改动时(执行 INSERT、DELETE、UPDATE 这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id只都默认为0.

  • trx_ids,表示生成 ReadView 时,当前系统中活跃的读写事务的 事务id列表

  • up_limit_id,活跃的事务中最小的事务ID.

  • low_limit_id,表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。low_limit_id 是系统最大的事务ID值.

    low_limit_id 并不是trx_ids 中的最大值,事务ID是递增分配的。比如:现在有ID为1、2、3这三个事务,之后ID为3的事务提交了,那么一个新的读事务在生成 ReadView 时,trx_ids 就包括1 和2,up_limit_id 的值就是1,low_limit_id的值就是4.

ReadView 的规则:在访问某条记录时,需要按照以下步骤(ReadView 的规则)判断记录的某个版本是否可见

  • 如果被访问版本的 trx_id(db_trx_id) 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。
  • 如果被访问版本的 trx_id(db_trx_id) 属性值小于 ReadView 中的 up_limit_id 值,表明生成该版本的事务在当前事务生成 ReadView 前已经提交,所以该版本可以被当前事务访问。
  • 如果被访问版本的 trx_id(db_trx_id) 属性值大于或等于 ReadView 中的 low_limit_id 值,表明生成该版本的事务在当前事务生成 ReadView 后才开启,所以该版本不可以被当前事务访问。
  • 如果被访问版本的 trx_id(db_trx_id) 属性值在 ReadView 的 up_limit_id 和 low_limit_id 之间,就需要判断一下 trx_id 属性值是否在 trx_ids 列表中。
  • 如果在,说明创建 ReadView 时,生成该版本的事务还是活跃的,该版本不可以被访问。
  • 如果不在,说明创建 ReadView时,生成该版本的事务已经被提交,该版本可以被访问。

MVCC 整体操作流程:

查询一条记录时,系统通过MVCC机制查找记录的流程:

  • ① 首先获取事务自己的版本号,也就是事务ID.
  • ② 获取 ReadView.
  • ③ 查询得到的数据,然后与 ReadView 中的事务版本号进行比较。
  • ④ 如果不符合 ReadView 规则,就需要从 undo log 中获取历史快照。
  • ⑤ 最后返回符合规则的数据。

       如果某个版本的数据对当前事务不可见,那就顺着版本链找到下一个版本的数据,继续按照上边的步骤判断可见性,依此类推,直到版本链中的最后一个版本。

InnoDB 中,MVCC 是通过 Undo Log + ReadView 进行数据读取, Undo Log 保存了历史快照,而 Read View 规则帮我们判断当前版本的数据是否可见。

 

2.3、读已提交和可重复读隔离级别下,产生 ReadView 时机的区别

 

  • 在隔离级别为读已提交(Read Commit)时,一个事务中的每一次 SELECT 查询都会重新获取一次 ReadView.

    步骤事务说明
    1begin;
    2select * from tb_table where id > 2;获取一次 ReadView
    3……
    4select * from tb_table where id > 2;获取一次 ReadView
    5commit;
    • 步骤2和步骤4,一样的查询语句,在读已提交的隔离级别下,会分别获取一次 ReadView,如果两次的ReadView 不同,就可能产生不可重复读或者幻读的情况。
  • 当隔离级别为可重复读的时候,一个事务只在第一次 SELECT 时会获取一次 ReadView,而后面所有的 SELECT 都会复用这个 ReadView,所以可以避免不可重复读。
    在这里插入图片描述

 

3、MVCC 解决幻读

 
       使用例子说明 InnoDB 如何解决幻读,以下示例是在InnoDB引擎的可重复读隔离级别下讨论。现在 tb_table 表中已存在一条 主键id = 1 的数据,该条记录隐藏的 db_trx_id = 10。

db_trx_id = 10数据:id = 1,name = 张三NULL

假设现有 事务A 和 事务B 并发执行,事务A 的事务id 为 20,事务B 的事务id 为 30.

  • 步骤 1:事务A 开始第一次查询数据。

    – 事务A 开始第一次查询数据

    select * from tb_table where id >=1;
     
    ① --> 在开始查询前,MySQL 会为事务A产生一个 ReadView,此时 ReadView 的内容如下:trx_ids = [20,30],up_limit_id = 20,low_limit_id = 31,creator_trx_id = 20.
     
    ② --> 执行select * from tb_table where id >=1;查出id=1,db_trx_id= 10的数据,按ReadView机制判断该行数据是否可见。
     
    ③ --> 按 ReadView 机制 该查询出的数据 db_trx_id = 10 ,小于事务A的ReadView 的up_limit_id,故该数据在事务A 开启之前,其他事务已提交,所以该行数据可见。
     
    结论:事务A 的第一次查询,能读到一条数据,id=1,name= 张三。

  • 步骤2:接着事务B(事务id=30),往tb_table 插入两条数据,并提交事务(假设不考虑 gap lock)。

    insert into student(id,name) values (2,'李四')insert into student(id,name) values (3,'王五')

    此时 tb_table 中就要三条数据了,对应的 undo log 如下。
    在这里插入图片描述

  • 步骤3:接着事务A开启第二次查询,由于在可重复读隔离级别下,事务A不会再次生成ReadView.

    – 事务A 开始第二次查询数据

    select * from tb_table where id >=1;
     
    ① --> 此时tb_table中的3条数据都满足 id>=1 的条件,因此会先查出来,然后根据 ReadView 机制,判断每条数据是不是都可以被事务A可见。
     
    ② --> 首先 id = 1 这条数据同步骤1,对事务A可见。
     
    ③ --> 然后是 id = 2 的数据,它的 trx_id = 30,介于 ReadView 的 up_limit_id = 20 和 low_limit_id = 31 之间,需要再次判断 trx_id = 30 是否处于 ReadView 的 trx_ids=[20,30] 数值内。结果在trx_ids数组内,表示 id= 2 这条数据是与事务A 在同一时刻启动的其他事务提交的,所以这条数据不能被事务A可见。
     
    ④ --> 同理,id = 3 这条数据,trx_id 也为 30,因此也不能被事务A 可见。
     
    结论:最终事务A 的第二次查询,只能查询出 id = 1 的这条数据,这和事务A 的第一次查询的结果一样,因此没有出现不可重复读现象

    在这里插入图片描述

注意只靠MVCC不能完全解决幻读问题。虽然MVCC可以提供事务的一致性视图,并保持数据的一致性版本,但它本身并不能防止其他事务插入新的数据。通过结合 next-key locking 和 MVCC,InnoDB 在可重复读隔离级别下解决了幻读问题,确保了事务在多次读取相同范围数据时的一致性

      间隙锁是在 innodb的 可重复读级别才会生效,且 Next-Key Locks 实际上是由间隙锁加行锁实现的MySQL 在 InnoDB 存储引擎下,可重复读的隔离级别下,不存在幻读问题
 

4、总结

 
MVCC(多版本并发控制)的核心点在于 ReadView 的原理,READ COMMITTED、REPEATABLE READ 这两个隔离级别的一个很大不同就是生成 ReadView 的时机不同:

  • READ COMMITTED每一次进行普通 select 操作前,都会生成一个 ReadView.
  • REPEATABLE READ 只在第一次进行普通 select 操作前生成一个 ReadView,之后的查询操作都重复使用这个 ReadView 就好了。

 

MVCC(多版本并发控制)解决的问题

  • 读写之间阻塞的问题。通过 MVCC 可以让读写相互不阻塞,即读不阻塞写,写不阻塞读,可以提升事务并发处理能力。
  • 降低了死锁的概率。因为 MVCC 采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
  • 解决快照读的问题。当查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

 

 

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

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

相关文章

国外客户发开发信怎么发?写外贸邮件方法?

如何给国外客户发开发信?给老外发外贸开发信的技巧? 与国外客户保持联系并积极开展业务合作变得至关重要。一种有效的方式是通过发展信件,这可以帮助建立关系、传递信息和促成商机。蜂邮将介绍如何向国外客户发开发信,以确保您的…

c语言:矩阵交换

题目&#xff1a; 代码和思路&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>int main() {int n 0;int m 0;int arr[10][10] { 0 }; // 输入行和列scanf("%d%d", &n, &m);int i 0;int j 0;//读取数组for (i 0; i < n; i)…

nginx学习(3)

Nginx 负载均衡 实战案例 实现效果 浏览器地址栏输入地址 http://172.31.0.99/oa/a.html&#xff0c;负载均衡效果&#xff0c;平均 8083 和 8084 端口中 一、配置 1、先创建2个文件夹&#xff0c;并将apache-tomcat-8.5.87解压到tomcat8083和tomcat8084中 &#xff08;或…

Linux中安装部署环境(JAVA)

目录 在Linux中安装jdk 包管理器yum安装jdk JDK安装过程中的问题 验证安装jdk 在Linux中安装tomcat 安装mysql 在Linux中安装jdk jdk在Linux中的安装方式有很多种, 这里介绍最简单的方法, 也就是包管理器方法: 包管理器yum安装jdk Linux中常见的包管理器有: yumaptp…

Nginx部署前端项目

Nginx部署前端项目 1.在nginx官网http://nginx.org/en/download.html &#xff0c;下载稳定版本&#xff1a; 2.解压后&#xff0c;点击根目录中的nginx.exe即可启动Nginx&#xff0c;或是在nginx安装目录中启动cmd并输入以下命令启动&#xff1a; nginx.exe 或 start nginx3…

本地部署 EmotiVoice易魔声 多音色提示控制TTS

本地部署 EmotiVoice易魔声 多音色提示控制TTS EmotiVoice易魔声 介绍ChatGLM3 Github 地址部署 EmotiVoice准备模型文件准备预训练模型推理 EmotiVoice易魔声 介绍 EmotiVoice是一个强大的开源TTS引擎&#xff0c;支持中英文双语&#xff0c;包含2000多种不同的音色&#xff…

深信服测开实习

感觉会有人对这种类型的博客感兴趣&#xff0c;所以想了想还是发上来了。 今天早上十点收到了通知&#xff0c;这周五报道。 大致说工作时长&#xff1a; 周一到周五 一二四 早上九点到中午十二点。两小时午休。下午两点到晚上六点半。一小时晚休。七点半到晚上八点半下班。三…

这8个Wireshark使用技巧,一看就会!

今天就给你分享8个常用的Wireshark使用技巧&#xff0c;一看就会。如果是处理 HTTP&#xff0c;HTTPS 大家还是用还是用 Fiddler&#xff0c;但如果是其他协议比如 TCP&#xff0c;UDP&#xff0c;还是用wireshark。 今天给你准备了wireshark和Fiddler的安装包给你&#xff0c…

蔡崇信看好的菜鸟,“基本面”究竟如何?

今年5月,阿里巴巴集团曾公布云智能集团将完全分拆独立走向上市&#xff0c;菜鸟、盒马启动上市计划&#xff0c;国际数字商业集团启动外部融资。但随着16日阿里巴巴集团最新财报的发布&#xff0c;及宣布终止分拆阿里云、盒马IPO搁置&#xff0c;现在&#xff0c;仅有菜鸟在按原…

中小企业怎么实现数字化转型?有什么实用的工单管理系统?

当前&#xff0c;世界经济数字化转型已是大势所趋。在这个数字化转型的大潮中&#xff0c;如果企业仍然逆水而行&#xff0c;不随大流&#xff0c;那么&#xff0c;企业将有可能会被抛弃&#xff0c;被对手超越&#xff0c;甚至被市场边缘化&#xff0c;导致最终的结果是&#…

AIGC创作系统ChatGPT源码,支持最新GPT-4-Turbo模型,支持DALL-E3文生图

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

每日一题 53. 最大子数组和(中等,数组)

很经典的数组题了 class Solution:def maxSubArray(self, nums: List[int]) -> int:ans -inft 0for i in nums:t ians max(ans, t)if t < 0:t 0return ans

防火墙部署模式 -- 镜像流量(旁路模式)

镜像流量&#xff08;旁路模式&#xff09; 如图&#xff0c;与单臂路由模式不同&#xff0c;旁路模式中&#xff0c;PC的流量不会流经防火墙&#xff0c;就算防火墙宕机也不会影他们之间的数据传输。 镜像的原理是交换机把被镜像端口的流量复制一份&#xff0c;发到监听端口&…

element UI表格中设置文字提示(tooltip)或弹出框(popover)时候注意的地方

在表格中自定义内容的时候需要使用标签&#xff0c;否则无法正常显示 文档中有两种写法&#xff1a;1、使用 slot“reference” 的具名插槽&#xff0c;2、使用自定义指令v-popover指向 Popover 的索引ref。 使用tooltip 时用具名 slot 分发content&#xff0c;替代tooltip中…

再谈super、static、final

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 从一道面试题说起 pub…

app小程序定制开发的优势|企业软件网站建设

app小程序定制开发的优势|企业软件网站建设 小程序定制开发是目前互联网行业中备受关注的领域之一。随着智能手机的普及和移动互联网的迅猛发展&#xff0c;越来越多的企业和个人开始重视小程序的潜力&#xff0c;并积极寻求定制开发的服务。那么&#xff0c;为什么小程序定制开…

光谱图像常见评价指标

光谱图像常见评价指标 SAM&#xff08;Spectral Angle Mapper&#xff09;RMSE——Root Mean Square ErrorPSNRSSIMMSSIMEGARS SAM&#xff08;Spectral Angle Mapper&#xff09; ​ SAM算法是由Kruse等[146]在1993年提出&#xff0c;把图像中的每个像元的光谱视为一个高维向…

为什么越来越多人选择学习Python?

今天我要和大家聊聊一个很热门的话题&#xff1a;为什么那么多人学习Python&#xff1f; 最近小编发现一个有趣的现象&#xff0c;高中生们居然在学校课程里学Python&#xff0c;这不仅给我们这些已经毕业多年的人当头一棒&#xff0c;更是彻底颠覆了传统观念。现在的高中生竟…

国产化区块链平台-FISCO BCOS 区块链

目录 FISCO BCOS 版本信息 系统概述 关键特性 组件服务 开发运维工具 FISCO BCOS作为一种企业级区块链平台&#xff0c;为企业和组织提供了高性能、隐私保护和可定制的区块链解决方案。其强大的架构和丰富的功能使得企业能够在安全可信的环境中开展区块链应用&#xff0…

【Linux】C文件系统详解(四)——磁盘的物理和抽象结构

文章目录 磁盘结构磁盘物理结构磁盘的具体物理结构磁盘结构的逻辑抽象 文件系统BootBlockSuperBlockGroupDescriptorTableinode tableDataBlocksinodeBitmapblockBitmaplinux中的inode 和文件名如何理解文件的增删查改删 补充细节1.如果文件误删了,我们该怎么办?2.inode确定分…