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

news2025/1/12 8:43:28

文章目录

        • 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) const
    MY_ATTRIBUTE((warn_unused_result)) {
    ut_ad(id > 0);
    //快照的id小于活跃事务id集合中的最小事务id 或者 快照的id等于创建这个视图的事务id
    if (id < m_up_limit_id || id == m_creator_trx_id) {
        return(true);
    }
    //检查快照id是否合法,如果快照的id大于等于下一要分配的事务id,则需要抛出警告信息(会出现这种情况吗?)
    check_trx_id_sanity(id, name);
    //快照的id大于等于下一要分配的事务id
    if (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.coloradmin.cn/o/1623852.html

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

相关文章

2024深圳杯C题的8页思路分析+所有代码可执行+参考文献+持续更新参考论文(已经更新了代码与图像)

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

每周一算法:最短路计数

题目描述 给出一个 N N N个顶点 M M M 条边的无向无权图&#xff0c;顶点编号为 1 1 1 到 N N N。 问从顶点 1 1 1 开始&#xff0c;到其他每个点的最短路有几条。 输入格式 第一行包含 2 2 2 个正整数 N , M N,M N,M&#xff0c;为图的顶点数与边数。 接下来 M M …

vue3实现全局事件总线

1、vue3中使用全局事件总线是变化最大的。在vue2中&#xff0c;我们在new Vue中在beforeCreate钩子函数中使用vue.prototype.$busthis来创建全局事件总线。vue3中我需要借助第三方库来完成创建全局事件总线。 2、安装依赖 npm i mitt -s3、封装event-bus.js文件 import mitt …

Web前端开发之HTML_3

标签之表格Form表单块元素与行内元素&#xff08;内联元素&#xff09;HTML5新增标签 1. 标签之表格 <table></table> 1.1 表格&#xff08;快速生成&#xff1a;table>tr*2>td*3{单元格}&#xff09; 表格由行、列、单元格组成。单元格有同行等高、同列等…

【C++】:拷贝构造函数和赋值运算符重载

目录 一&#xff0c;拷贝构造函数1. 什么是拷贝构造函数2. 拷贝构造函数的特性3. 实践总结 二&#xff0c;赋值运算符重载2.1 运算符重载2.2 赋值运算符重载 一&#xff0c;拷贝构造函数 1. 什么是拷贝构造函数 拷贝构造函数是特殊的构造函数。是用一个已经存在的对象&#x…

ArtNeRF、Attention Control、Pixel is a Barrier、FilterPrompt

本文首发于公众号&#xff1a;机器感知 ArtNeRF、Attention Control、Pixel is a Barrier、FilterPrompt ArtNeRF: A Stylized Neural Field for 3D-Aware Cartoonized Face Synthesis Recent advances in generative visual models and neural radiance fields have greatly …

文件上传复习(upload-labs18-19关)

Pass-18&#xff08;条件竞争&#xff09; 代码和第17关大差不差&#xff0c;所以查看提示 需要用到代码审计 上传图片木马配合解析漏洞进行getshell 新建一句话木马 18.php&#xff0c;代码为&#xff1a; <?php fputs(fopen(../upload/shell18.php,w),<?php phpin…

js的算法-交换排序(冒泡)

交换排序 所谓交换排序&#xff0c;是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。基于交换的排序算法很多&#xff0c;本次介绍冒泡排序和快速排序。 冒泡 基本思想 从后往前&#xff08;或从前往后&#xff09;两两比较相邻元素的值&#xff0…

新风口下的必应bing国内广告投放该怎么做?

必应Bing作为全球搜索引擎市场的重要参与者&#xff0c;正逐渐显现出其在国内市场的独特价值和潜力。随着互联网生态的多元化发展&#xff0c;必应Bing凭借其高质量用户群和精准投放能力&#xff0c;成为了企业寻求新增长点的新风口。 一、洞察先机&#xff0c;精准定位市场 …

考研数学|跟武忠祥做《660》很吃力,要不要换张宇❓

不建议&#xff01; 我就是个妥妥的二战选手&#xff0c;一战听完汤家凤的课发现大量的题还是不会做&#xff0c;于是冒险把张宇的基础课听完一遍&#xff0c;毫不夸张的硕导致我最后没有强化阶段直接进入冲刺。可想而知&#xff0c;这能考好吗&#xff1f;21年数三87分&#…

ChromaDB教程

使用 Chroma DB&#xff0c;管理文本文档、将文本嵌入以及进行相似度搜索。 随着大型语言模型 &#xff08;LLM&#xff09; 及其应用的兴起&#xff0c;我们看到向量数据库越来越受欢迎。这是因为使用 LLM 需要一种与传统机器学习模型不同的方法。 LLM 的核心支持技术之一是…

JavaEE:File类查询一个文件的路径(举例+源码 )

一、File类概述 Java 中通过 java.io.File 类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。File 类中的方法可以对文件路径以及文件名等信息进行查询&#xff0c;也可以对文件进行各项增删改操作&#xff0c;本文主要介绍 File 类的查询方法。 二、代码示例 …

git忽略文件配置 !

.gitignore中!表示取反 注意&#xff0c;如果父目录被排除&#xff0c;则父目录下的子目录也会被排除&#xff0c;此时对父目录下的子目录取反也不会生效&#xff0c;比如存在目录结构&#xff0c;再.gitignore目录下配置的 /*&#xff08;排除所有文件&#xff09;&#xff0c…

构建Java线程间的默契:学习wait()、notify()和notifyAll()方法的巧妙运用

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

【源码】权益商城系统源码,支持多种支付方式

权益商城系统源码&#xff0c;支持多种支付方式&#xff0c;后台商品管理&#xff0c;订单管理&#xff0c;串货管理&#xff0c;分站管理&#xff0c; 会员列表&#xff0c;分销日志&#xff0c;应用配置。 上传到服务器&#xff0c;修改数据库信息&#xff0c;导入数据库&a…

C语言入门课程学习记录4

C语言入门课程学习记录4 第18课 - signed 与 unsigned第19课 - 再论数据类型第20课 - 经典问题剖析第21课 - 程序中的辅助语句&#xff08;上&#xff09;第22课 - 程序中的辅助语句&#xff08;下&#xff09; 本文学习自狄泰软件学院 唐佐林老师的 C语言入门课程&#xff0c;…

【高频】基于GBDT-FM模型的level-2高频数据实证研究(二)

【高频】基于GBDT-FM模型的level-2高频数据实证研究&#xff08;二&#xff09; 原创 Yud. 2AMquant 2024-04-04 11:30 广东 上一篇中初步提及了Level2数据中常见变量指标的构建方式&#xff0c;以及其带来的价格冲击。此篇将使用GBDT-LM模型对短程价格走势进行简单预测。 ps…

前端css中的transform(转换)的使用

前端css中的transform的使用 一、前言二、流程图三、举例&#xff08;一&#xff09;、平移1.平移&#xff0c;源码12.源码1运行效果(1).视频效果(2).截图效果 3.平移3d效果&#xff0c;源码24.源码2运行效果&#xff08;1&#xff09;、视频效果&#xff08;2&#xff09;、截…

【C语言】红黑树详解以及C语言模拟

一、红黑树的性质二、红黑树的旋转操作三、红黑树的插入操作四、红黑树的删除操作五、红黑树的应用六、C语言模拟红黑树七、总结 红黑树是一种自平衡二叉查找树&#xff0c;它能够保持树的平衡&#xff0c;从而确保查找、插入和删除的最坏情况时间复杂度为O( l o g n log_n log…

41-数组 _ 数组作为函数参数

41-1 冒泡排序函数的设计 数组传参的时候&#xff0c;形参有2种写法&#xff1a; 1、数组 2、指针 往往我们在写代码的时候&#xff0c;会将数组作为参数传个函数 如&#xff1a;实现一个冒泡排序&#xff0c;将数组的数据排成升序 冒泡排序的核心思想&#xff1a; 1、两…