事务的原理、MVCC的原理

事务特性

数据库事务具有以下四个基本特性,通常被称为 ACID 特性:

  1. 原子性(Atomicity):事务被视为不可分割的最小工作单元,要么全部执行成功,要么全部失败回滚。这意味着如果事务执行过程中发生了错误,所有的修改都将被回滚,数据库状态将回到事务执行前的状态。

  2. 一致性(Consistency):事务执行前后,数据库从一个一致性状态转换到另一个一致性状态。事务的执行不会破坏数据库的完整性约束,例如主键、外键约束等。数据库会保持数据的完整性和一致性。

  3. 隔离性(Isolation):每个事务的操作都相互隔离,一个事务的中间结果对其他事务是不可见的。这意味着一个事务的修改在提交之前对其他事务是不可见的,防止了并发事务之间的相互影响,保证了数据的正确性。

  4. 持久性(Durability):一旦事务提交成功,对数据库的修改就会永久保存,即使系统故障或崩溃也不会丢失。数据库会将事务的结果持久化到非易失性存储器中,以保证即使系统发生故障,数据也不会丢失。

这些特性确保了数据库事务的可靠性和稳定性。它们是数据库管理系统中设计用于支持可靠性和并发控制的重要概念。通过保证事务具有这些特性,数据库可以提供稳定、可靠、高效的数据管理和处理能力。

事务的隔离级别

事务的隔离性

事务完全的串行会严重的降低系统的吞吐量和资源利用率,仔细发现,引发事务一致性问题的根本原因在于多个事务访问了相同的数据,更合理的做法是,在某个事务访问某个数据时,对其他想要访问该数据的事务进行限制,当该事务提交后,其他事务才能继续访问这个数据

事务并发执行引发的一致性问题

脏读

一个事务读取了另一个未提交事务修改过的数据,意味着发生了脏读,脏读引发的事务一致性问题。T1事务读取了T2事务未提交的数据。
幻读和不可重复读是并发事务中可能出现的两种问题,它们在数据库事务隔离级别较低的情况下会更容易发生。它们之间的区别在于以下几点:

幻读(Phantom Read)

幻读指的是在同一个事务内多次执行同样的查询,但在查询中返回了不同的数据行的现象。这种情况通常发生在一个事务中插入数据后,另一个并发事务再执行相同的查询,发现结果集中出现了之前不存在的行。

不可重复读(Non-repeatable Read)

不可重复读指的是在同一个事务内多次执行同样的查询,但在查询中返回了不同的数据行的现象。与幻读不同的是,不可重复读是由于其他并发事务对数据进行了修改导致的。

总的来说,**幻读侧重于事务在查询中发现了之前不存在的数据行,而不可重复读侧重于事务在多次读取相同数据时发现数据被其他事务修改。**两者的根本区别在于幻读关注的是新增或者删除的数据行,而不可重复读关注的是已经存在的数据行发生了改变

SQL标准中的四种隔离级别

设置隔离级别的目的是,舍弃一部分隔离性换取一部分性能,SQL标准中的4个隔离级别:

隔离级别脏读不可重复读幻读
READ UNCOMMITTED允许允许允许
READ COMMITTED不允许允许允许
REPEATABLE READ不允许不允许允许
SERIALIZABLE不允许不允许不允许

MySQL中支持的4中隔离级别

MySQL中的默认隔离级别是:REPEATABLE READ
MySQL8查询事务隔离级别

SELECT @@GLOBAL.transaction_isolation;

修改隔离级别语句

set [global | session] transaction isolation level 隔离级别;

各种隔离级别适用的场景

  1. READ UNCOMMITTED (读未提交): 这个隔离级别适用于某些特定的报表查询场景,对数据的实时性要求非常高,而对数据一致性要求较低。例如,在某些实时监控系统中,可以使用读未提交隔离级别来获取最新的数据,即使数据可能尚未被完全提交。

  2. READ COMMITTED (读已提交): 这个隔离级别适用于大多数在线交易处理系统(OLTP),如电子商务网站。在这种场景下,用户只需要读取已经提交的数据,以避免看到其他事务未提交的数据。一个典型的例子是在线购物系统中的库存管理,确保每个用户看到的库存数据是准确的。

  3. REPEATABLE READ (可重复读): 这个隔离级别适用于某些需要对数据进行长时间读取或计算的场景,比如报表生成或复杂的分析。在这些情况下,确保事务在执行期间不受其他事务的影响是非常重要的,以避免数据不一致性。例如,某些财务报表的生成过程中,需要保证数据的完整性和一致性。

  4. SERIALIZABLE (可串行化): 这个隔离级别适用于某些极端要求数据完全一致性的场景,如金融交易系统。在这种系统中,任何数据的不一致性都可能导致严重的后果。因此,确保所有事务按顺序逐个执行是至关重要的,即使在高并发情况下也要保证数据的完整性。

MVCC原理(多版本并发控制)

版本链

在InnoDB存储引擎中的表,聚簇索引中的记录都包含两个隐藏列,
trx_id: 一个事务都某条聚簇索引记录进行修改时,都会把该事务的事务id赋值给trx_id
roll_pointer: 每次对聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中,相当于一个指针,通过它可以找到该记录修改前的信息
image.png

ReadView(读视图)

用READ UNCOMMITTED 隔离级别的事务来说,可以读取未提交事务修改的记录,因此直接读取版本链中的最新版本就可以了;对于SERIALIZABLE隔离级别的事务来说,InnoDB中使用加锁的方式访问记录,对于READ COMMITED和REPEATABLE READ隔离级别的事务来说,都必须保证读到的记录是已经提交的事务修改过的记录,因此核心问题就是:需要判断版本链中的哪个版本对于当前事务是可见的,InnoDB给出的解决方案是,生成ReadView,ReadView包含下列四个重要内容:

m_ids:生成ReadView时,当前系统中活跃的事务id列表

min_trx_id:m_ids中的最小事务id

max_trx_id:在生成ReadView时,系统分配个下一个事务的事务id(max_trx_id+1)

creator_trx_id:生成该ReadView的事务的事务id

生成了ReadView之后,我们就可以借助它来判断当前版本的记录对当前事务是否可见:

  • 如果当前记录的trx_id与creator_trx_id相同,意味着当前事务在访问自己修改过的记录,可以访问
  • 如果当前记录的trx_id小于min_trx_id,说明生成该版本记录的事务已经提交了,可以访问
  • 如果当前记录的trx_id 大于max_trx_id,说明生成该版本的事务在当前事务生成ReadView之后才开启,所以该版本不可以被当前事务访问
  • 如果被访问版本的trx_id 在 min_trx_id 和 max_trx_id之间,则需进一步判断trx_id是否在m_ids列表中,如果在说明事务为提交,该版本不可见,如果不在,说明可见

在MySQL中,READ COMMITED和REPEATABLE READ 隔离级别之间一个非常答的区别就是他们生成ReadView的时机不同

READ COMMITED 每次读取数据前都生成一个ReadView

例如,现在系统中有两个事务id为T100,T200的事务正在执行,T80是已经提交的事务。100的事务修改a=1,200的事务修改a=2,下面是表信息,其中第一行索引中的记录。

idatrx_idroll_point
11100100
1110080
1080

假设现在有一个使用READ COMMITED隔离级别的新事物开始执行:
执行语句为

select a from t where id=1;

select语句执行过程如下:

  • 执行select语句时生成一个ReadView,m_ids列表为[100,200],min_trx_id为100,max_trx_id为201,creator_trx_id为0

因为这个新开启的事务只进行了select操作,并没有对记录进行修改,所以系统没有为其分配事务id,默认为0

  • 顺序版本链寻找符合要求的版本,返回的是a为"0"的版本

之后,将事务id为100的事务提交事务 200 事务中更新表 hero number 的记录

update t set a = "2" where id=1

然后再到刚才使用 READ COMMITTED隔离级别的事务执行select语句,继续查找number为1 的记录,执行步骤如下:

  • 生成ReadView,m_ids列表[200],min_trx_id为200,max_trx_id为200,creator_trx_id为0
  • 顺序版本链,查找符合要求的版本,最终返回的是"1"

REPEATABLE 在第一次读取数据时生成一个ReadView

假设现在有一个使用 REPEATABLE READ 隔离级别的新事务开始执行:
第一次select操作时:

  • 生成ReadView,执行select语句时生成一个ReadView,m_ids列表为[100,200],min_trx_id为100,max_trx_id为201,creator_trx_id为0
  • 找到符合条件的版本"0"

之后将事务id为100的事务提交后,再到事务id为200的事务中更新表中id为1的记录
然后再次执行select:

  • 沿用(或者说复制)第一次select时生成的ReadView
  • 最终的返回版本还是"0"

总结,在REPEATABLE READ隔离级别下,事务的两次查询结果是一样的,因此可以说在REPEATABLE READ级别下避免了不可重复读的发生,同时也很大程度上避免了幻读的发生

MVCC小结

所谓的MVCC指的就是在使用READ COMMITED 和 REPEATABLE READ这两种隔离级别的事务在执行select操作时,访问记录版本链的过程,这样可以使不同事务的读-写操作并发执行,从而提升系统性能。READ COMMITED 和 REPEATABLE READ的最大区别在于,生成Read View的时机不同,READ COMMITED 每次执行select前都会生成一个新的ReadView,而REPEATABLE READ只在第一次执行select前生成一个ReadView

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

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

相关文章

别玩了!软考初级网络管理员无非就这23页纸!背完稳!

添加图片注释,不超过 140 字(可选) 添加图片注释,不超过 140 字(可选) 考点2、子网划分 【考法分析】 本考点的基本考法是给出一个IP网段,同时提出需要划分多少个子网,或每个子网…

技术干货|如何巧妙利用数字孪生技术助力口腔保健分析

行业: 口腔医疗 挑战: 传统方法缺乏预测口腔内受力状态,也很难从患者方面获得反馈,因此将口腔扫描、牙齿形状/位置识别和正畸数字模型生成的过程数字化是一个重大机会。 正畸治疗是牙科中最大的类别之一,随着病例的…

WPF+MVVM案例实战(十一)- 环形进度条实现

文章目录 1、运行效果2、功能实现1、文件创建与代码实现2、角度转换器实现3、命名空间引用3、源代码下载1、运行效果 2、功能实现 1、文件创建与代码实现 打开 Wpf_Examples 项目,在Views 文件夹下创建 CircularProgressBar.xaml 窗体文件。 CircularProgressBar.xaml 代码实…

从壹开始解读Yolov11【源码研读系列】——Data.Base.py.BaseDataset:可灵活改写的数据集加载处理基类

目录 一、base.BaseDataset 1.__init__类初始化 2.get_img_files根据地址获得图片详细地址 3.get_labels(自定义)获取标签数据 4. update_labels指定类别和单分类设定 5.set_rectangle开启批量矩阵训练 6.cache_images加载图片进程可视化 7.load_image内…

超出人类思维的「系统0」:AI正在创造一种新的思维方式吗?

在大众的认知中,人类的思维分为系统 1(System 1,直觉的、快速的、无意识的、自动思考)和系统 2(System 2,有逻辑的、缓慢的、有意识的、计划和推理)。 如今,一种不同于 System 1 和…

华为ICT题库-云服务部分

1651、关于创建数据盘镜像的约束条件,以下说法错误的是?(云服务考点) (A)使用云服务器的数据盘创建数据盘镜像时,要确保该云服务器必须有系统盘 (B)通过外部文件创建数据盘镜像必须明确指定操作系统类型 (C)使用云服务…

阿里旺旺ActiveX控件ImageMan溢出

Welcome to Windows pwn~ 环境搭建: 虚拟机:winxp sp3 32位 再装一些常用的tools,olldby,immundbg,windbg这些。 漏洞版本的软件:AliIM2010_taobao(6.50.00C) PoC crash 分析 运行PoC,win…

新闻记者职业资格考试备考资料包分享(重要考点)!

24年新闻记者职业资格考试时间:11月2日,今天给大家整理的是新闻记者职业资格考试备考资料包(重要考点)23版,可以更有重点的进行复习~ 「新闻记者职业资格」 资料链接: https://pan.quark.cn/s/965044c95…

三菱FX5U CPU 存储卡引导运行操作

在CPU模块的电源0FF->ON时或复位时,将保存在SD存储卡内的文件传送至CPU模块自动判别的传送目标存储器。 引导运行的步骤如下所示。 1、进行引导文件设置。 2、安装SD存储卡。 3、将引导文件设置及引导文件写入至SD存储卡中。 4、CPU模块的电源0FF→>0N或复位…

【学习】ZLMediaKit试用

服务端准备 下载ZLMediaKit压缩包,解压 /linux/Release路径下启用MediaServer ./MediaServer -d &/linux/Release路径下config.ini更改配置 也可以将进入web控制台 rtmp默认端口1935, rtsp默认端口554,http默认端口80, SSL默认端口443 进入web控制台 http…

域渗透AD渗透攻击利用 python脚本攻击之IPC连接 以及 python生成exe可执行程序讲解方式方法

Python脚本批量检测ipc连接 import os, timeips [192.168.1.121,192.168.1.8 ] users {administrator,hack,hack1,test, } passs {123qq.com,456qq.com,Admin12345 } for ip in ips:for user in users:for mima in passs:exec1 "net use \\" "\\" i…

基于springboot小区物联网平台源码

小区物联网平台是一个专为小区硬件管理设计的物联网管理平台,其核心功能在于与各大厂商的门禁设备、道闸设备、监控设备、智能锁以及充电桩等进行高效对接。该平台支持HTTP、MQTT、ComNet等多种协议,以便轻松实现与各大小区云平台的互联互通。 目前&…

Moveit-轨迹优化

mvoeit轨迹周期不固定的问题,以及我们希望对moveit规划出来的轨迹进一步优化的项目需求 首先看一个关节角运动的python函数,通过这个函数我们可以实现机械臂从当前位姿运动到设定位姿的功能 #用于控制机械臂移动到目标位置,接受三个参数 #t…

高效实现用友BIP与吉客云的数据集成方案案例

用友BIP数据集成到吉客云的技术案例分享 在企业信息化建设中,数据的高效流动和准确对接是实现业务协同的重要基础。本文将重点介绍一个实际运行的系统对接集成案例:如何通过轻易云数据集成平台,将用友BIP的数据无缝集成到吉客云中&#xff0…

Golang高级语法-工具链

Golang工具链是一个强大的工具集,可以帮助开发人员管理和构建Golang应用程序,包括编译、链接、测试、代码分析、文档生成等。本文将介绍Golang工具链的基本用法和示例代码,让您更好地了解和使用它。 1 环境 在开始之前,您需要安装…

中间件安全(三)

本文仅作为学习参考使用,本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言: 本文主要讲解apache命令执行漏洞(cve_2021_41773)。 靶场链接:Vulfocus 漏洞威胁分析平台 一,漏洞简介。 cve_2021_41773漏洞…

双十一我都入手了啥大件?这几款超值好物分享给你

​马上就到一年一度的“双11”大促,简单与大家分享,最近自己买过或者是看好的生活好物。以数码为主,平常的一点生活会提及一些。 耳机党必备,听歌不伤耳朵!——南卡OE MIX开放式耳机 一句话推荐:百元旗舰…

PHP海外矿物矿机理财投资源码-金融理财投资源码

PHP海外矿物矿机理财投资源码/金融理财投资源码 海外矿物矿机理财投资源码 测试不错,可以做其他产品理财,功能都没啥太大问题

持续更新...记录

一、Random类 1、构造方法: ①有参:通过指定种子数进行创建 (使用相同的种子数创建多个Random对象,这些对象生成的随机数序列将完全相同‌) (适用于需要可重复生成相同随机数序列的场景,如科学…

Redis项目中应用

1. Redis简介 Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件。 官网:https://redis.io 中文网:Redis中文网 2. Redis下载与安装 2.1 Redis下载 Redis安装包分为windows版和Linux版: Wind…