MySQL多版本并发控制mvcc原理浅析

文章目录

        • 1.mvcc简介
          • 1.1mvcc定义
          • 1.2mvcc解决的问题
          • 1.3当前读与快照读
        • 2.mvcc原理
          • 2.1隐藏字段
          • 2.2版本链
          • 2.3ReadView
          • 2.4读视图生成原则
        • 3.rc和rr隔离级别下mvcc的不同

1.mvcc简介
1.1mvcc定义

mvcc(Multi Version Concurrency Control),多版本并发控制,是一种数据库的并发控制机制。它用于管理事务并发执行时对数据的访问和修改,保证在多个事务同时对数据库进行读写操作,不会出现数据不一致或丢失的情况

1.2mvcc解决的问题

当多个事务同时访问数据库中的相同数据时,可能会有几种情况:

  • 读:多个事务都是读操作,不会产生并发问题
  • 读+写:事务有读有写,那么会产生脏读、不可重复读、幻读的问题
  • 写:多个事务同时写,可能会产生数据丢失、覆盖等问题

针对以上问题,在读+写的情况下,通常需要加锁来解决问题,mysql的innodb实现了mvcc来更好的处理读写冲突,做到不用加锁,实现非阻塞并发读

在都是写操作的情况下,只能通过加锁的方式解决。

1.3当前读与快照读

当前读:读取的是最新版本的数据,保证读取时不会有其他事务修改数据,需要对记录加锁

加共享锁,读不受影响,写会被阻塞

select ... lock in share mode;

加排他锁,读和写都被阻塞(快照读不受影响)

select ... for update;

更新、插入、删除操作以及串行化隔离级别都是当前读

快照读:每一次修改数据,都会在undolog中存有原始记录(快照),快照读就是读取某一版本的记录。这种方式能够不加锁读数据,但是可能会读到旧的数据。一般的查询都是快照读

select * from tablename;
2.mvcc原理

mvcc主要通过行记录中的隐藏字段、undolog和readview实现的

2.1隐藏字段

mysql中,在每一行记录中除了自定义的字段,还有3个隐藏的字段(innodb引擎)

  1. row_id:如果表没有自定义主键,那么会自动生成row_id作为主键
  2. trx_id:记录修改、新增这条记录的事务id
  3. roll_pointer:回滚指针,指向当前记录的上一个版本
2.2版本链

在修改数据时,mysql会向undolog中记录数据原来的快照,用于进行回滚操作。undolog还能用来实现mvcc

如以下例子,mvcc生成版本链:

当事务1001(trx_id=1001)执行了 insert into user values(1,'竹子',23) 之后:

在这里插入图片描述

当事务1002(trx_id=1002)执行了 update user set name='竹笋' where id=1 之后:

在这里插入图片描述

当事务1003(trx_id=1003)执行了 update user set name='竹叶' where id=1 之后:

在这里插入图片描述

可以看到,不同版本的数据被指针连接起来形成了一个链表。

当我们要读取时,如何判断该读取哪个版本呢?这就与生成的读视图有关了。

2.3ReadView

读视图用于决定事务可以读到哪个版本的数据

它包含以下主要信息:

  1. trx_ids:当前mysql中所有活跃的事务id集合(没提交或回滚的事务集)
  2. low_limit_id:当前出现的最大的事务id+1,表示下一个要分配的事务id
  3. up_limit_id:当前活跃的事务id集合中,最小的事务id
  4. creator_trx_id:生成该ReadView视图的事务的id

MySQL5.7版本的源码对于这些信息的定义如下:
在这里插入图片描述

插入一个注意事项:🐭🐮🐯🐰🐉🐍🐴🐑🐒🐔🐶🐷

start transaction不代表立即生成ReadView,而是在事务中第一次快照读的时候生成ReadView,具体参考MySQL可重复读隔离级别下开启事务的一个注意事项

想要开启事务时就生成ReadView,请使用

start transaction with consistent snapshot;
2.4读视图生成原则

ReadView定义了一个可见性算法,当事务进行快照读时,依据该算法判断事务能够读取哪个快照。

源码的可见性判断逻辑如下:(下载源码可访问:官网,操作系统选择Source Code)

/** Check whether the changes by id are visible.@param[in]	id	transaction id to check against the view@param[in]	name	table name@return whether the view sees the modifications of id. */
//判断某个版本的数据是否对当前事务可见
bool changes_visible(trx_id_t		id,const table_name_t&	name) constMY_ATTRIBUTE((warn_unused_result)) {ut_ad(id > 0);//快照的id小于活跃事务id集合中的最小事务id 或者 快照的id等于创建这个视图的事务idif (id < m_up_limit_id || id == m_creator_trx_id) {return(true);}//检查快照id是否合法,如果快照的id大于等于下一要分配的事务id,则需要抛出警告信息(会出现这种情况吗?)check_trx_id_sanity(id, name);//快照的id大于等于下一要分配的事务idif (id >= m_low_limit_id) {return(false);} //当前不存在活跃的事务else if (m_ids.empty()) {return(true);}const ids_t::value_type*	p = m_ids.data();//通过二分查找判断快照id是否在活跃事务集合中,存在则快照不可见,不存在则快照可见return(!std::binary_search(p, p + m_ids.size(), id));
}
  1. 快照id等于当前事务id时(trx_id=creator_trx_id),说明该版本是当前事务修改的,该快照对当前事务可见
  2. 快照id小于活跃事务的最小id(trx_id<up_limit_id),说明该版本对应的事务已经提交了,该快照对当前事务可见
  3. 快照id大于等于下一个要分配的事务id(trx_id>=low_limit_id),则该快照对当前事务不可见
  4. 快照id小于下一个要分配的事务id并且活跃事务id数量为0(trx_id<low_limit_id && trx_ids.size==0),则该快照对当前事务可见
  5. 当以上条件都不满足,则在活跃事务id集合里查找快照id,如果不存在,则可见,否则不可见
3.rc和rr隔离级别下mvcc的不同

mvcc主要用来解决rc(读已提交)隔离级别下的脏读和rr(可重复读)隔离级别的不可重复读问题,所以mvcc只在rc和rr隔离级别下生效。

区别在于,rc级别下,每一次快照读都会生成一个最新的ReadView;RR级别下,只有事务中的第一次快照读会生成ReadView,之后的快照读会使用第一次生成的ReadView

事务能否查询到其他事物修改的数据,取决于ReadView,而rc和rr两个级别的ReadView生成方式不同,就导致了事务可见性不同。(rc级别下一个事务可以查询到其他事物在此期间修改并提交的数据,因为它的每次查询都会生成新的ReadView;rr级别下事务无法查询到其他事物在此期间修改并提交的数据,因为他的ReadView只在第一次快照读生成)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

买婴儿洗衣机怎么选择?推荐四大表现突出的宝藏婴儿洗衣机

现在还有人把宝宝衣服跟大人的混洗吗&#xff1f;或者把婴儿衣物跟其他衣物混洗吗&#xff1f;赶紧停止吧&#xff01;这样会带来非常严重的细菌交叉的感染&#xff0c;有小孩的家庭&#xff0c;或者说打算生小孩的家庭&#xff0c;一定要入手一台小型婴儿洗衣机&#xff0c;宝…

jmeter之跨线程关联

1&#xff09;_setproperty函数&#xff1a;将值保存成jmeter属性 2&#xff09;_property函数&#xff1a;在其他线程组中使用property函数读取属性 一、跨线程接口引用变量 1. 法一&#xff1a;jmeter自带函数_setProperty和_property 1. 1线程组 01 创建登录的【HTTP请求】…

学python的第二十天

多线程 以下内容来源于《看漫画学Python》这本书&#xff0c;前面十几天好多内容参考过本书内容&#xff0c;写的挺好。 1 线程相关知识 1.1 进程 一个进程就是一个正在执行的程序&#xff0c;每一个进程都有自己独立的一块内存空间&#xff0c;一组系统资源。在进程概念中&…

JVM (Micrometer)监控SpringBoot(AWS EKS版)

问题 怎样使用JVM (Micrometer)面板&#xff0c;监控Spring&#xff1f;这里不涉及Prometheus和Grafana&#xff0c;重点介绍与Micrometer与Springboot&#xff0c;k8s怎样集成。 pom.xml 引入依赖&#xff0c;如下&#xff1a; <properties><micrometer.version&…

STM32与Proteus的串口仿真详细教程与源程序

包含LCD1602显示&#xff0c;串口发送接收&#xff0c;完美实现。 文档内容齐全&#xff0c;包含使用说明&#xff0c;相关驱动等。 解决了STM32的Proteus串口收发问题。 注意&#xff1a;每输入一个字符后&#xff0c;要按一次“手动发送”按钮&#xff0c;才能收到正确字符…

【NoC片上网络 On-Chip Network】应用程序的网络流量 合成网络流量

应用程序的网络流量 and 合成网络流量 1. 应用程序的网络流量 APPLICATION TRAFFIC2. 合成网络流量 SYNTHETIC TRAFFIC3. 合成网络流量的具体介绍 应用程序的网络流量 and 合成网络流量 1. 应用程序的网络流量 APPLICATION TRAFFIC 在 MPSoC(多处理器片上系统) 中&#xff…

【leetcode面试经典150题】63. 删除链表的倒数第 N 个结点(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

go语言并发实战——日志收集系统(五) 基于go-ini包读取日志收集服务的配置文件

实现日志收集服务的客户端 前言 从这篇文章开始我们就正式进入了日志收集系统的编写&#xff0c;后面几篇文章我们将学习到如何编写日志收集服务的客户端,话不多说,让我们进入今天的内容吧&#xff01; 需要实现的功能 我们要收集指定目录下的日志文件&#xff0c;将它们发…

补充:js 制作qq、微信 的表情 缺少的微信表情图片

这篇文章是补充一下 这个csdn&#xff1a;js 制作qq、微信 的表情缺少的微信表情图片

Vue+Echarts 实现中国地图和飞线效果

目录 实现效果准备 实现效果 在线预览&#xff1a;https://mouday.github.io/vue-demo/packages/china-map/dist/index.html 准备 高版本的echarts&#xff0c;不包含地图数据&#xff0c;需要自己下载到项目中 1、地图数据下载 https://datav.aliyun.com/portal/school/at…

行为监控软件监控什么 行为监控软件下载

行为监控软件主要用于监控和分析用户的行为模式。这类软件可以监控的内容相当广泛&#xff0c;安企神作为典型的行为监控软件&#xff0c;可以从中窥见软件监控的内容&#xff1a; 找客服咨询价格 1、应用程序与上网行为管理 应用程序监控&#xff1a;跟踪员工使用各类软件的…

云渲染100的优惠活动有哪些?渲染100邀请码1a12

现在的云渲染平台有很多&#xff0c;每个平台都有各种活动&#xff0c;以广受好评的云渲染平台渲染100为例&#xff0c;我们来说下设计师怎样才能省钱又方便吧。 1、新用户福利 渲染100对新用户很友好&#xff0c;注册时填邀请码1a12有新手大礼包&#xff0c;可以渲染20多张小…