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) 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只在第一次快照读生成)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kubeedge:Metamanager源码速读(不定期更新)

Kubeedge源码版本&#xff1a;v1.15.1 在看Metamanager之前&#xff0c;先看一下Metamanager源码的目录结构&#xff08;位于edge/pkg下&#xff09;和官方文档&#xff1a; 目录结构如下面的两张图所示。请忽略绿色的文件高亮&#xff0c;这是Jetbrains goland对未提交修改的…

【教程】MySQL数据库学习笔记(五)——约束(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 第三章 《数据定义语言DDL》 第四章 《数据操…

【求助】西门子S7-200PLC定时中断+数据归档的使用

前言 已经经历了种种磨难来记录我的数据&#xff08;使用过填表程序、触摸屏的历史记录和数据归档&#xff09;之后&#xff0c;具体可以看看这篇文章&#xff1a;&#x1f6aa;西门子S7-200PLC的数据归档怎么用&#xff1f;&#xff0c;出现了新的问题。 问题的提出 最新的…

25 - MOV 指令

---- 整理自B站UP主 踌躇月光 的视频 文章目录 1. 指令系统设计2. MOV 指令3. 实现3.1 CPU 电路图3.2 代码实现3.3 实验过程3.4 实验结果3.5 实验工程 1. 指令系统设计 指令 IR 8 位程序状态字 4 位微程序周期 4 位 2. MOV 指令 MOV A, 5; 立即寻址 MOV A, B; 寄存器寻址 MO…

基于PaddlePaddle平台训练物体分类——猫狗分类

学习目标&#xff1a; 在百度的PaddlePaddle平台训练自己需要的模型&#xff0c;以训练一个猫狗分类模型为例 PaddlePaddle平台&#xff1a; 飞桨&#xff08;PaddlePaddle&#xff09;是百度开发的深度学习平台&#xff0c;具有动静统一框架、端到端开发套件等特性&#xf…

tailwindcss在使用cdn引入静态html的时候,vscode默认不会提示问题

1.首先确保vscode下载tailwind插件&#xff1a;Tailwind CSS IntelliSense 2.需要在根目录文件夹创建一个tailwind.config.js文件 export default {theme: {extend: {// 可根据需要自行配置&#xff0c;空配置项可以正常使用},}, }3.在html文件的标签中引入配置文件&#xf…

程序员到架构师,除了代码,还有文档和图

文章目录 前言一、书面设计文档文档应该作为代码和口头交流的补充文档应该注意鲜活 二、图——架构讨论的直观语言总结 前言 作为人类&#xff0c;我们天生就被视觉所吸引。在这个信息爆炸的时代&#xff0c;从精炼的代码到清晰的文档&#xff0c;再到直观的图&#xff0c;我们…

【数据结构】串(String)

文章目录 基本概念顺序存储结构比较当前串与串s的大小取子串插入删除其他构造函数拷贝构造函数扩大数组空间。重载重载重载重载[]重载>>重载<< 链式存储结构链式存储结构链块存储结构 模式匹配朴素的模式匹配算法(BF算法)KMP算法字符串的前缀、后缀和部分匹配值nex…

Parade Series - CoreAudio Reformating

// 获得音频播放设备格式信息CComHeapPtr<WAVEFORMATEX> pDeviceFormat;pAudioClient->GetMixFormat(&pDeviceFormat);constexpr int REFTIMES_PER_SEC 10000000; // 1 reference_time 100nsconstexpr int REFTIMES_PER_MILLISEC 10000;// Microsoftif (p…

Golang | Leetcode Golang题解之第49题字母异位词分组

题目&#xff1a; 题解&#xff1a; func groupAnagrams(strs []string) [][]string {mp : map[[26]int][]string{}for _, str : range strs {cnt : [26]int{}for _, b : range str {cnt[b-a]}mp[cnt] append(mp[cnt], str)}ans : make([][]string, 0, len(mp))for _, v : ra…

Alibaba 的fastjson源码详解

一、概述 Fastjson 是阿里巴巴开源的一个 Java 工具库&#xff0c;它常常被用来完成 Java 的对象与 JSON 格式的字符串的相互转化。 Fastjson 可以操作任何 Java 对象&#xff0c;即使是一些预先存在的没有源码的对象。 二、源码分析 1.首先以fastjson-1.2.70为例&#xff0c;…

nodejs

334 先下载zip文件&#xff0c;然后加上.zip,可以看到两个文件 在user中可以看到 输入即可得到flag。 335. 这里提到eval函数&#xff0c;eval中可以执行js代码&#xff0c;可以尝试使用这个函数进行测试 payload&#xff08;显示当前目录下的文件和文件夹列表&#xff09; …

基于emp的mysql查询

SQL命令 结构化查询语句&#xff1a;Structured Query Language 结构化查询语言是高级的非过程化变成语言&#xff0c;允许用户在高层数据结构上工作。是一种特殊目的的变成语言&#xff0c;是一种数据库查询和程序设计语言&#xff0c;用于存取数据以及查询、更新和管理关系数…

Python 网络与并发编程(四)

文章目录 协程Coroutines协程的核心(控制流的让出和恢复)协程和多线程比较协程的优点协程的缺点 asyncio实现协程(重点) 协程Coroutines 协程&#xff0c;全称是“协同程序”&#xff0c;用来实现任务协作。是一种在线程中&#xff0c;比线程更加轻量级的存在&#xff0c;由程…

android脱壳第二发:grpc-dumpdex加修复

上一篇我写的dex脱壳&#xff0c;写到银行类型的app的dex修复问题&#xff0c;因为dex中被抽取出来的函数的code_item_off 的偏移所在的内存&#xff0c;不在dex文件范围内&#xff0c;所以需要进行一定的修复&#xff0c;然后就停止了。本来不打算接着搞得&#xff0c;但是写了…

基础SQL DCL语句

DCL是数据控制语言&#xff0c;用来管理数据库用户&#xff0c;还有控制用户的访问权限 1.用户的查询 MySQL的用户信息存储在mysql数据库中&#xff0c;查询用户时&#xff0c;我们需要使用这个数据库。 后面&#xff0c;还有很多数据&#xff0c;因为篇幅的问题&#xff0c;就…

【FFmpeg】音视频录制 ② ( 使用 Screen Capturer Recorder 软件生成 ffmpeg 可录制的音视频设备 )

文章目录 一、使用 Screen Capturer Recorder 软件生成音视频设备1、设备查找问题 - 引入 Screen Capturer Recorder 软件2、下载安装 Screen Capturer Recorder 软件3、验证 Screen Capturer Recorder 生成的设备 一、使用 Screen Capturer Recorder 软件生成音视频设备 1、设…

【PyTorch】torch.gather() 用法

gather常被用于image做mask的操作中&#xff0c;对哪些地方进行赋值0/1 API&#xff1a; torch.gather — PyTorch 2.2 documentation torch.gather(input, dim, index, outNone) → Tensor gather()的意义&#xff1a; 顾名思义&#xff0c;聚集、集合&#xff1a;gather…

在mac上安装node.js及使用npm,yarn相关命令教程

1、安装node.js 官网&#xff1a;Node.js — Download Node.js 选择需要的版本&#xff0c;点击DownLoad 2、点击继续&#xff0c;直到安装成功。 2.1打开终端输入命令node -v 显示版本号则说明已安装成功 3、全局安装yarn命令 1、sudo npm install --global yarn &#xf…