MySQL之MVCC原理详解

news2024/11/19 7:23:25

MySQL之MVCC(多版本并发控制)

谈谈数据库隔离级别

谈起MVCC,就不得不说到事务隔离级别,因为MVCC是为了实现数据库的隔离级别,保证事务并发的情况下数据安全的同时还能保持高性能的方式。

在事务并发的场景下会引起脏读,不可重复读,幻读问题,MySQL支持四种隔离级别来解决事务并发中的这些问题。

读未提交:只限制两个数据不能同时修改,但是修改数据的时候,即使事务未提交也可能读到未提交的数据,这种隔离级别仍有脏读,不可重复读,幻读问题

读已提交:当前事务只能读取到其他事务提交的数据,解决了脏读问题,但还是存在不可重复读,幻读问题

可重复读:限制了读取数据的时候,不可以进行修改,所以解决了重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题;

序列化:、所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

数据库是如何保证事务的隔离性的

最为简单粗暴的方式就是加锁,不管是读操作还是写操作都加锁当然能保证事务的隔离性,但很显然频繁的加锁,释放锁,在读数据时没办法修改,修改数据时没办法读取大大降低了数据库的性能,所以加锁显然是不可取的

那更为高性能的方式,让我们在读取数据时可以修改,修改数据时可以读取,保证数据库的高性能的方式就是MVCC,数据库隔离级别读已提交、可重复读 都是基于MVCC(多版本并发控制)实现的。

这里的多版本指记录的多版本,还记得我们的undo日志吗?我们每一次对记录的修改都会把旧的版本记录到undo日志中,下面我们说MVCC的具体实现原理

MVCC是如何实现的

MVCC实现组成主要有三个关键部分

隐藏字段:我们知道innodb存储引擎中每一条行记录都有两个隐藏字段trx_idroll_pointer,如果表中没有主键和非NULL唯一键时,则还会有第三个隐藏的主键列row_id

trx_id:每次事务对某条记录进行更新时,都会把该事务的id赋值给trx_id

roll_pointer:每次事务对某条记录进行更新时,都会把旧的版本写入到undo日志中,然后这个隐藏列相当于指针,可以通过它找到之前版本数据信息

row_id:单调递增的行ID,不是必需的(在没有主键且没有唯一非空字段时innodb自动生成的作为主键),占用6个字节。

undo log版本链

多个事务并行操作某一行数据时,不同事务对该行数据的修改会产生多个版本,然后通过回滚指针(roll_pointer),连成一个链表,这个链表就称为版本链 就像下图

在这里插入图片描述

这样就保证了我们可以通过回滚指针找到该条记录的旧版本进行回滚或者查询

ReadView

ReadView是解决了什么问题呢

ReadView就是事务A在使用MVCC机制进行快照读操作时产生的读视图。当事务启动时,会生成当前数据库系统快照。innodb为每一个事务构造了一个数组,用来记录并维护系统当前活跃事务ID(启动但未提交的事务)

ReadView的主要属性

createor_trx_id:创建这个ReadView的事务ID

min_limit_id:活跃的事务中最小的事务ID

max_limit_id:系统中应该分配给下一个事务的id值

m_ids:活跃的事务ID列表构成一个list

ReadView的匹配条件

1.如果数据库事务trx_id<min_limit_id,表示生成该版本的事务在生成ReadView前就已经提交所以可以查询到该条记录

2.如果数据库事务trx_id>max_limit_id,表示生成该版本的事务在ReadView生成之后才提交,所以不可以查询到这条记录

3.如果min_limit_id<=trx_id<max_limit_id分为以下三种

1.如果m_ids包含trx_id则代表Read View生成时刻,这个事务还未提交,但是如果数据的trx_id等于creator_trx_id的话,表明数据是自己生成的,因此是可见的。

2.如果m_ids包含trx_id,并且trx_id不等于creator_trx_id,则Read View生成时,事务未提交,并且不是自己生产的,所以当前事务也是看不见的;

3.如果m_ids不包含trx_id,则说明你这个事务在Read View生成之前就已经提交了,修改的结果,当前事务是能看见的。

基于MVCC的查询流程

1.获取当前事务自己id trx_id

2.获取ReadView(不同的隔离级别下获取的时机不同)

3.查询得到的数据和Read View中的事务版本号进行比较

4.如果不符合Read View的可见性规则, 即就需要Undo log中历史快照

5.最后返回符合规则的数据

InnoDB 实现MVCC,是通过 Read View+ Undo Log 实现的,Undo Log 保存了历史快照,Read View可见性规则帮助判断当前版本的数据是否可见。

获取Read View的时机:

在读已提交的隔离级别下:事务中每一次select都会生成一次Read View,会导致不可重复读问题

在可重复的的隔离级别下:只有事务中第一次select会生成Read View,由于每一次select都会复用旧的Read View所以不存在不可重复读问题

如何解决幻读问题

假设表中只有student一条数据

在这里插入图片描述

现在事务A B并发事务A的id为20,事务B的id为30

步骤一:事务A开启第一次select语句

select *from student where id>=1

在开始执行select之前,MySQL会为事务A生成一个ReadView,则此时ReadView的内容是m_ids=[20,30],min_liimit_id=[20],max_limit_id=[31],creator_trx_id=[20]

由于此时表中只有一条数据且满足查询条件,因此接下来根据ReadView机制判断数据能否被查询到,此时数据的trx_id<min_liimt_id,则表示该条数据在ReadView之前已经提交所以可以查询到,第一次查询结果为“张三”

步骤二:事务B(trx_id=30)插入两条数据,并提交事务

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

则此时的undo如下图

在这里插入图片描述

步骤三:此时事务开始第二次查询,,根据可重复读隔离级别不会再生成ReadView,内容是m_ids=[20,30],min_liimit_id=[20],max_limit_id=[31],creator_trx_id=[20],此时表中三条数据都满足查询条件,则开始ReadView机制判断数据是否可见

首先id=1,可见

id=2,它的trx_id=30,在min_limit_id和max_limit_id之间,因此判断trx_id在是否在m_ids中,显然在则不能查询到该记录

id=3同理

总结:两次查询结果相同,所以在RR隔离级别下解决了幻读问题

MVCC小结

MVCC解决了什么问题

1.读写之间的阻塞问题:MVCC可以使读写互不阻塞,提高并发能力

2.降低了死锁的概率:这是因为MVCC读取数据时不需要加锁,对于写操作也只是进行行锁

3.解决了快照读问题:解决了快照读问题

MVCC是在RC和RR这两种隔离级别的事务在执行快照读操作访问版本链查询到的对当前事务可见的数据

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

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

相关文章

Node.js 万字教程

0. 基础概念 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;使用了一个事件驱动、非阻塞式 I/O 模型&#xff0c;让 JavaScript 运行在服务端的开发平台。 官方地址&#xff1a;https://nodejs.org/en 中文地址&#xff1a;https://nodejs.org/zh-cn 代…

连接备份1128

深度学习—分类识别篇&#xff1a;http://tr.daheng-imaging.com/watch/1050636http://tr.daheng-imaging.com/watch/1050636 深度学习—目标检测篇&#xff1a;http://tr.daheng-imaging.com/watch/1101141http://tr.daheng-imaging.com/watch/1101141 深度学习—缺陷分割篇&a…

判断数组中每个元素是否为负数 numpy.signbit()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断数组中每个元素是否为负数 numpy.signbit() [太阳]选择题 请问以下代码中最后输出结果是&#xff1f; import numpy as np a np.array([-1, 0, 1]) print("【显示】a ",a) pr…

Opencv 极坐标变换

变换后图片 代码 // 以Center为极坐标原点&#xff0c;将RowFrom到RowTo的圆环&#xff0c;仅仅变换该范围内的点&#xff0c;忽略掉其他部分。 #include "polar_transeforme.hpp" #include <string>using namespace cv;void calculate_map(int rouFrom, int …

AcWing 3555:二叉树(北京大学考研机试题)→公共父结点

【题目来源】https://www.acwing.com/problem/content/description/3435/【题目描述】 如下图所示&#xff0c;由正整数 1, 2, 3, … 组成了一棵无限大的&#xff08;满&#xff09;二叉树。 1/ \2 3/ \ / \4 5 6 7 /\ /\ /\ /\ ... ... 从任意一个结点到根结点&…

【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

文章目录 行为型模式1、模板方法模式&#xff08;1&#xff09;概述&#xff08;2&#xff09;结构&#xff08;3&#xff09;案例实现&#xff08;4&#xff09;优缺点&#xff08;5&#xff09;适用场景&#xff08;6&#xff09;JDK源码解析&#xff08;7&#xff09;模板方…

Lambda表达式与方法引用

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 引子 先来看一个案例 …

什么是供应链攻击?

随着企业越来越依赖技术、连接性和第三方&#xff0c;供应链攻击变得越来越普遍。这些攻击旨在通过供应商和业务合作伙伴损害公司。 供应链攻击可能对企业和组织构成重大威胁&#xff0c;损害其安全以及向客户提供的产品和服务的安全。 在本文中&#xff0c;我们将探讨供应链…

排序算法基本原理及实现2

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 &#x1f324;️冒泡排序 &#x1…

37 - 数据库参数设置优化,失之毫厘差之千里

MySQL 是一个灵活性比较强的数据库系统&#xff0c;提供了很多可配置参数&#xff0c;便于我们根据应用和服务器硬件来做定制化数据库服务。如果现在让你回想&#xff0c;你可能觉得在开发的过程中很少去调整 MySQL 的配置参数&#xff0c;但我今天想说的是我们很有必要去深入了…

CONTROLLING VISION-LANGUAGE MODELS FOR MULTI-TASK IMAGE RESTORATION

CONTROLLING VISION-LANGUAGE MODELS FOR MULTI-TASK IMAGE RESTORATION (Paper reading) Ziwei Luo, Uppsala University, ICLR under review(6663), Cited:None, Stars: 350, Code, Paper. 1. 前言 像CLIP这样的视觉语言模型已经显示出对零样本或无标签预测的各种下游任务…

血的教训--kail系统免密centos7的坑【高版本ssh免密低版本ssh的坑】

血的教训–kail系统免密centos7的坑【高版本ssh免密低版本ssh的坑】 最近下载了一个2023版本的kail系统&#xff0c;但是经过几次设置免密后&#xff0c;ssh过去一直让提供密码&#xff0c;所以就仔细的分析了一下&#xff0c;果然还是发现了点猫腻 接上一个博客&#xff0c;大…

TZOJ 1373 求多项式的和

答案&#xff1a; #include <stdio.h> int main() {int m 0;scanf("%d", &m); // 读取测试实例的个数 while (m--) //循环m次{int n 0, i 0;scanf("%d", &n); // 读取求和项数n double sum 0.0;for (i 1; i < n; i) //分…

项目demo —— GPT 聊天机器人

本文介绍我的开源项目 TelegramChatBot&#xff0c;这是一个基于 OpenAI GPT API 开发的 telegram 机器人&#xff0c;具有多模态交互能力&#xff0c;求 star&#xff01;感谢大家&#xff01;在 telegram jokerController_bot 立即体验&#xff01;欢迎对 GPT 应用开发或对 t…

Web安全漏洞分析-XSS(下)

随着互联网的迅猛发展&#xff0c;Web应用的普及程度也愈发广泛。然而&#xff0c;随之而来的是各种安全威胁的不断涌现&#xff0c;其中最为常见而危险的之一就是跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;简称XSS&#xff09;。XSS攻击一直以来都是Web安全领…

【Python】yaml.safe_load()函数详解和示例

在Python中&#xff0c;PyYAML库提供了对YAML&#xff08;YAML Ain’t Markup Language&#xff09;文件的强大支持。YAML是一种直观的数据序列化标准&#xff0c;可以方便地存储和加载配置文件、数据日志等。 yaml.safe_load和yaml.load是Python的PyYAML库提供的两个函数&…

Node.js案例 - 记账本

目录 项目效果 项目的搭建 ​编辑 响应静态网页 ​编辑 ​编辑 结合MongoDB数据库 结合API接口 进行会话控制 项目效果 该案例实现账单的添加删除查看&#xff0c;用户的登录注册。功能比较简单&#xff0c;但是案例主要是使用前段时间学习的知识进行实现的&#xff0c…

Java后端开发——SpringMVC商品管理程序

Java后端开发——SpringMVC商品管理程序 今日目标 Spring MVC框架介绍掌握SpringMVC的核心类的原理及配置掌握SpringMVC的常用注解掌握SpringMVC的增删改查编程 Spring MVC框架介绍 Spring MVC&#xff08;Model-View-Controller&#xff09;是一个基于Java的开源框架&#x…

移动开发新风向?HarmonyOS、车载、音视频、flutter

目前&#xff0c;移动开发已经处于饱和的阶段&#xff0c;Android开发也不如当年盛况&#xff0c;已经不再像前几年前那么火爆。正如一种编程语言如果经历过盛极一时&#xff0c;那么必然有这样的一条曲线&#xff0c;像我们学的正弦曲线先急速上升&#xff0c;然后到达顶点&am…

拼图 游戏

运行出的游戏界面如下&#xff1a;按住A不松开&#xff0c;显示完整图片&#xff1b;松开A显示随机打乱的图片 User类 package domain;/*** ClassName: User* Author: Kox* Data: 2023/2/2* Sketch:*/ public class User {private String username;private String password;p…