【MySQL】MVCC(多版本并发控制)详解

MVCC

MVCC概述

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

MVCC就是在ReadCommitted(读已提交)、RepeatableRead(可重复读) 隔离级别,不加锁的情况下,解决并发事务的脏读、幻读和不可重复读问题。

MVCC 在 MySQL InnoDB 中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

什么是当前读、快照读?

当前读: 读到的数据都是最新的数据,像排他锁(又称写锁updateinsertdeleteselect for update共享锁(又称读锁select lock in share mode,这些操作都是当前读。

快照读: 可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。像不加锁的select操作就是快照读,如果隔离级别是串行化,快照读会退化成当前读。

数据库并发场景

  • 读-读: 不存在任何问题。
  • 读-写: 有线程安全问题,可能出现脏读、幻读、不可重复读。
  • 写-写: 有线程安全问题,可能存在更新丢失等。

MVCC(多版本并发控制)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。

MVCC实现原理

MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3个隐式字段,undo日志版本链 , Read View 来实现的。

三个隐式字段

数据库中的每行记录都有DB_TRX_ID(事务id)DB_ROLL_PTR(回滚指针)DB_ROW_ID(隐藏主键)这三个字段。

DB_TRX_ID(事务id)DB_ROLL_PTR(回滚指针)DB_ROW_ID(隐藏主键)
记录创建这条记录,最后一次修改该记录事务的ID。每处理一个事务,其值自动 +1回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里)隐含的自增 ID(隐藏主键),如果数据表没有主键,InnoDB 会自动以DB_ROW_ID产生一个聚簇索引

undo日志版本链

undo日志版本链是指一行数据被多个事务依次修改过后,在每个事务修改完后,Mysql会保留修改前的数据undo回滚日志,并且用两个隐藏字段DB_TRX_ID(事务id)DB_ROLL_PTR(回滚指针)把这些undo日志串联起来形成一个历史记录版本链。

undo日志分类:

undo log 主要分为两种:

  • insert undo log 代表事务在 insert 新记录时产生的 undo log,只在事务回滚时需要,并且在事务提交后可以被立即丢弃
  • update undo log 事务在进行 updatedelete时产生的 undo log ;不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除。
undo日志版本链流程图

1)事务A,在employee表插入了一条数据,name为zhangsan、age为22、主键id为1、事务id为100、回滚指针和隐式主键为null。这条日志会在insert undo log中。

在这里插入图片描述
2)事务B对employee表主键id为1的记录做了修改,修改了name字段为lisi。(在事务B之前都没有事务修改过这条数据)

  • 拷贝改行数据到undo log中,作为旧纪录,既在 undo log 中有当前行的拷贝副本。
  • 修改name字段为lisi,假设事务id自增到101,回滚指针指向拷贝的副本。

在这里插入图片描述

3)事务C对employee表主键id为1的记录做了修改,修改了age字段为18。

  • 在拷贝数据到undo log中,发现这行数据已经有undo日志版本链了。修改后的数据,假设事务id为102。回滚指针就会指向undo日志版本链最后修改的那一条记录。

在这里插入图片描述

Read View 读视图

在可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view该视图在事务结束之前永远都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成read-view)这个视图由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id+1(max_id)组成,事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。

Read View 主要是用来做可见性判断的,可见性算法如下 (trx_id事务id)

绿色部分( trx_id<min_id ):已提交的事务
红色部分( trx_id>max_id ):未开始的事务
黄色部分(min_id <=trx_id<= max_id):活跃的事务。

  1. 如果 row trx_id 落在绿色部分( trx_id<min_id ),表示这个版本是已提交的事务生成的,这个数据是可见的;
  2. 如果 rowtrx_id等于当前事务的trx_id,这个数据是可见的;
  3. 如果 rowtrx_id 落在红色部分( trx_id>=max_id ),表示这个版本是由将来启动的事务生成的,是不可见的;
  4. 如果 rowtrx_id 落在黄色部分(min_id <=trx_id<max_id),那就包括两种情况
    a. 若 rowtrx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见
    b. 若 rowtrx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见

对于删除的情况可以认为是update的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的trx_id,同时在该条记录的头信息(record header)里的(deleted_flag)标记位写上true,来表示当前记录已经被删除,在查询时按照上面的规则查到对应的记录如果delete_flag标记位为true,意味着记录已被删除,则不返回数据。

关于readview和可见性算法的原理解释

readview和可见性算法其实就是记录了sql查询那个时刻数据库里提交和未提交所有事务的状态。

要实现RR隔离级别,事务里每次执行查询操作readview都是使用第一次查询时生成的readview,也就是都是以第一次查询时当时数据库里所有事务提交状态来比对数据是否可见,当然可以实现每次查询的可重复读的效果了。

要实现RC隔离级别,事务里每次执行查询操作readview都会按照数据库当前状态重新生成readview,也就是每次查询都是跟数据库里当前所有事务提交状态来比对数据是否可见,当然实现的就是每次都能查到已提交的最新数据效果了。

RepeatableRead(可重复读)MVCC可见性算法示例

假设有一张account表,account表有主键idnamebalance三个字段。最开始这张表里面的数据是:
在这里插入图片描述

1)事务trx_id = 100,修改了balance字段为200,此时事务100还未提交
2)事务trx_id = 200,修改了balance字段为300,此时事务200还未提交
3)事务trx_id = 300,修改了balance字段为500,此时事务300已经提交

此时的undo log日志版本链如下图:

在这里插入图片描述
4)事务trx_id = 400,执行select语句查询id=1,balance字段的数据,数据库为该行数据生成一个Read View读视图,假设数据看没有其它事务了,此时的readview数组:[100,200],min_id:100,max_id:400+1 = 401

此时的row最新的trx_id为300,因为事务400未作修改操作。从undo log日志版本链最后修改的,一直往上查询。根据上面的可见性算法分析:

  1. 先判断trx_id<min_id(300<100)不满足条件
  2. 再判断trx_id=create_trx_id(当前事务id),(300=400)不满足条件
  3. 再判断trx_id>=max_id(300>=401)不满足条件
  4. 再判断min_id <=trx_id<max_id(100<=300<401)满足条件
  5. trx_id=300,很显然不在readview数组[100,200]中,可见

得出结论:事务400查询的数据balance字段为500

5)事务trx_id = 200,又修改了balance字段为800,此时事务200已提交

此时的undo log日志版本链如下图:

在这里插入图片描述

6)事务trx_id = 400,又执行select语句查询id=1,balance字段的数据。在可重复读隔离级别下,不会重新生成Read View读视图,还是用的之前的Read View读视图。此时的readview数组:[100,200],min_id:100,max_id:400+1 = 401

此时的row最新的trx_id为200,同步骤4分析:

  1. 先判断trx_id<min_id(200<100)不满足条件
  2. 再判断trx_id=create_trx_id(当前事务id)(200=400)不满足条件
  3. 再判断trx_id>=max_id(200>=401)不满足条件
  4. 再判断min_id <=trx_id<max_id(100<=200<401)满足条件
  5. trx_id=200,很显然在readview数组[100,200]中,不可见

上面判断出最新修改的undo log日志不满足,继续往上查询,同理可以推断出,事务400查询的数据balance字段为500

ReadCommitted(读已提交)MVCC可见性算法示例

读已提交和可重复读是类似的,读已提交就是每次执行select,就会重新生成Read View读视图。

上面的我就不复制了,唯一不同的就是步骤6,

6)事务trx_id = 400,又执行select语句查询id=1,balance字段的数据。当前的活跃事务就只剩下事务100了,此时的readview数组:[100],min_id:100,max_id:400+1 = 401

此时的row最新的trx_id为200:

  1. 先判断trx_id<min_id(200<100)不满足条件
  2. 再判断trx_id=create_trx_id(当前事务id),(200=400)不满足条件
  3. 再判断trx_id>=max_id(200>=401)不满足条件
  4. 再判断min_id <=trx_id<max_id(100<=200<401)满足条件
  5. trx_id=200,很显然在readview数组[100,200]中,可见

得出结论:事务400查询的数据balance字段为800

参考文章:
【MySQL笔记】正确的理解MySQL的MVCC及实现原理

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

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

相关文章

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级&#xff0c;之前做过PIC系列单片机的升级&#xff0c;现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。 因为国民技术系列单片机在很多大程度上都模仿了STM32&#xff0c;所以我想其升级方案极有可能差不多。于是在…

基于SSM的智能仓储系统研究与设计

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

开源与闭源:大模型时代的技术交融与商业平衡

一、开源和闭源的优劣势比较 1.1 开源 优势&#xff1a; 1.技术共享与吸引人才&#xff1a; 开源促进了技术共享&#xff0c;吸引了全球范围内的人才参与大模型的发展&#xff0c;形成了庞大的开发者社区。 2.推动创新&#xff1a; 开源模式鼓励开发者共同参与&#xff0c;推动…

【STM32】RTC(实时时钟)

1.RTC简介 本质&#xff1a;计数器 RTC中断是外部中断&#xff08;EXTI&#xff09; 当VDD掉电的时候&#xff0c;Vbat可以通过电源--->实时计时 STM32的RTC外设&#xff08;Real Time Clock&#xff09;&#xff0c;实质是一个 掉电 后还继续运行的定时器。从定时器的角度…

腾讯云4核8G服务器性能如何多少钱一年?

腾讯云服务器4核8G配置优惠价格表&#xff0c;轻量应用服务器和CVM云服务器均有活动&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;轻量应用服务器4核8G12M带宽一年446元、529元15个月&#xff0c;腾讯云百科txybk.com分…

牛客——OR36 链表的回文结构(C语言,配图,快慢指针)

本题是没有对C的支持的&#xff0c;但因为Cpp支持C&#xff0c;所以这里就用C写了&#xff0c;可以面向更多用户 链表的回文结构_牛客题霸_牛客网 (nowcoder.com) 思路一&#xff1a;链表翻转 简单的想想整形我们怎么比较&#xff0c;就是将整形A 依次取尾&#xff0c;放到整形…

航天联志Aisino-AISINO26081R服务器通过调BIOS用U盘重新做系统(windows系统通用)

产品名称:航天联志Aisino系列服务器 产品型号:AISINO26081R CPU架构&#xff1a;Intel 的CPU&#xff0c;所以支持Windows Server all 和Linux系统&#xff08;重装完系统可以用某60驱动管家更新所有硬件驱动&#xff09; 操作系统&#xff1a;本次我安装的服务器系统为Serv…

python趣味编程-5分钟实现一个Tic Tac Toe游戏(含源码、步骤讲解)

The Tic Tac Toe In Python是用 Python 编程语言编写的,这个Tic Tac Toe Game In Python是一个简单的基于 GUI 的策略游戏板,非常容易理解和使用。 所有的游戏规则都是一样的,就像我们玩实时井字棋一样,这是一个简单的多人游戏。 Python 中的 Tic Tac Toe 游戏:项目信息 …

物理驱动深度学习方法总结

一、物理驱动深度学习方法总结 现有博主更新物理驱动深度学方法总体介绍 二、 PINN介绍 PINN综述Blog介绍&#xff1a;内嵌物理知识神经网络 &#xff08;Physics Informed Neural Network&#xff0c;简称PINN&#xff09; 是一种科学机器在传统数值领域的应用方法&…

ping命令使用示例解析

【一】ping命令简介 ping &#xff08;Packet Internet Groper&#xff09;是一种因特网包探索器&#xff0c;用于测试网络连接量的程序。ping的一般用途有&#xff1a; ①【测试网络物理链路是否正常】&#xff1a;通过将ICMP(Internet控制消息协议)回显数据包发送到网络终端&…

[PHP]关联和操作MySQL数据库然后将数据库部署到ECS

在Mac电脑上使用VS Code进行PHP开发并关联操作MySQL数据库&#xff0c;然后将数据库部署到ECS。 1.安装PHP和MySQL 确保你的Mac上已经安装了PHP和MySQL。你可以使用Homebrew来安装它们&#xff1a; $ brew install php $ brew install mysql 安装mysql完成后记住这一句: …

蓝桥杯第三周算法竞赛D题E题

发现更多计算机知识&#xff0c;欢迎访问Cr不是铬的个人网站 D迷宫逃脱 拿到题目一眼应该就能看出是可以用动态规划来解决。但是怎么定义dp呢? 这个题增加难度的点就在当所在位置与下一个要去的位置互质的时候&#xff0c;会消耗一把钥匙。当没有钥匙的时候就不能移动了。想…

cocos----刚体

刚体&#xff08;Rigidbody&#xff09; 刚体&#xff08;Rigidbody&#xff09;是运动学&#xff08;Kinematic&#xff09;中的一个概念&#xff0c;指在运动中和受力作用后&#xff0c;形状和大小不变&#xff0c;而且内部各点的相对位置不变的物体。在 Unity3D 中&#xff…

使用 React Flow 构建一个思维导图应用

思维导图是围绕共同主题或问题将思想、概念、信息或任务分组的视觉表示。思维导图应用是一种软件应用&#xff0c;允许您创建、可视化和组织您的思想、想法和信息作为思维导图。本文将向您展示如何实现自己的思维导图应用程序。 在我们开始之前&#xff0c;我想向您展示一下我们…

ke11..--2其他界面也要提取我的locatStarage

获取浏览器里面的本地缓存 localStorage就是我们的浏览器缓存在哪都可以用 下面代码是获取打印到我们的页面上 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> …

Hessian协议详解

前言 Hessian协议是一种基于二进制的轻量级远程调用协议&#xff0c;用于在分布式系统中进行跨语言的通信。它使用简单的二进制格式来序列化和反序列化数据&#xff0c;并支持多种编程语言&#xff0c;如Java、C#、Python等。Hessian协议相对于其他协议的优势在于其简单性和高…

微服务实战系列之Token

前言 什么是“Token”&#xff1f; 它是服务端生成的一串字符串&#xff0c;以作客户端进行请求的一个令牌&#xff0c;当第一次登录后&#xff0c;服务器生成一个Token便返回给客户端&#xff1b;以后客户端只携带此Token请求数据即可。 简言之&#xff0c;Token其实就是用户身…

【2022改良版】学法减分助手PRO小程序源码

【2022改良版】学法减分助手PRO小程序源码 &#xff0c;交管推出个学法减分&#xff0c;每个驾驶员可以把被扣的6分&#xff0c;以看视频答题的形式学习回来&#xff0c;然后答题这个一共二十道题每道题60秒&#xff0c; 有好多人不会&#xff0c;用咱们的小程序就可以模拟练习…

北京君正客户应用案例:掌静脉3D人脸猫眼视屏智能锁

凯迪仕在今年4月发布了智能锁旗舰新品K70 Pro Max掌静脉3D人脸猫眼视屏智能锁&#xff0c;随即这款新品也成了行业热议的焦点。凯迪仕每次新品都力求突破精益求精&#xff0c;不仅追求科技感、高级感与品质感&#xff0c;而且赋予科技温度&#xff0c;带来人文化的关怀。K70 Pr…

OpenCV快速入门:像素操作和图像变换

文章目录 前言1. 像素操作1.1 像素统计1.2 两个图像之间的操作1.2.1 图像加法操作1.2.3 图像加权混合 1.3 二值化1.4 LUT&#xff08;查找表&#xff09;1.4.1 查找表原理1.4.2 代码演示 2 图像变换2.1 旋转操作2.1.1 旋转的基本原理2.1.2 代码实现 2.2 缩放操作2.3 平移操作2.…