滴滴滴,请看MYSQL事务的四大特征(ACID)的实现原理:晓其原理而通其实现。

news2024/10/7 1:23:56

一.什么是事务的四特征

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

接下来,我们将对四大特性的具体概念以及其底层实现原理来进行剖析:
在讲述具体的四大特性之前,我们先补充一点前置知识 :

1.逻辑架构和存储引擎

如上图,我们可以将mysql服务器的逻辑架构整体分为三层:

①第一层:负责客户端的连接和授权认证

②第二层:服务器层:负责查询语句的解析,优化以及缓存,内置函数的实现和存储等

③第三层:存储引擎:负责数据库中数据的存储和读取,mysql服务器层不管理事务,事务是由存储引擎实现的。其中支持事务的存储引擎有innoDB和NDB Cluster等,其中比较应用广泛的是innoDB。

我们进行四大特性的具体介绍:

一.原子性

1. 定义

原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。

2.实现原理:redolog

在具体讲述redolog日志之前,我们先对mysql中存在的事务日志进行解释:mysql中存在很多类型的事务日志:包括二进制日志,错误日志以及查询日志等。除此之外,innoDB还提供了两个的日志:undolog(回滚日志) 和redolog(重做日志),其中undolog是数据的原子性和一致性的重要保证,而redolog用于保证事务的持久性。

UNDOLOG

undolog是实现事务原子性的重要保证,undolog能使一个事务中已经执行成功的所有sql语句进行回滚操作,其具体的工作流程如下:当事务修改数据库中的数据时,innoDB会对应生成具体的UNDO log ,一旦事务执行失败或者触发rollback操作时,就能使用redolog中的信息对数据库修改之前的数值进行恢复。

undolog是一种逻辑性日志,在触发rollback或者事务执行失败时,innoDB会根据undolog中记录的信息对数据库进行相反方向的操作,比如:之前的操作时insert语句,这时调用执行delete语句;如果之前执行的update语句,则会执行反方向的update语句。

二.持久性

1. 定义

持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

2.实现原理

redolog

在进行事务持久性的讲述之前,我们首先来说一下redolog存在的背景以及其存在的必要性:

对数据库的读写操作是对数据库中的数据进行操作,也就是说需要对数据库进行IO操作,但是对数据库频繁的IO效率很低,为此,innoDB提供了缓存层(BufferPool),BufferPool中储存着数据库部分数页的映射,作为数据库数据的缓冲:当我们需要从数据库汇总读入数据时,这时我们先从BufferPool中查找,在BufferPool中找不到,这时候从数据库中获取数据然后将其放入BufferPool,往数据库中写入数据也是先将数据写入到BufferPool,然后定期刷新到磁盘中(这一过程称为脏刷)。

但是带来便利的同时也存在一定的风险和弊端,如果在某刻数据库突然宕机,而这时在BufferPool中仍存在数据或者修改的数据没有刷入磁盘中,必然会导致数据丢失的问题,也无法保证数据的持久性,为了解决这个问题,redolog日志应运而生。redolog同样也是innoDB中的日志,它的实现原理如下:当数据写入到BufferPool之前或者对BufferPool中的数据进行修改之前,首先会先在redolog中记录此次操作,当事务提交时,会使用fsync接口对redolog进行刷盘,而如果数据库发生宕机问题,数据库会读取redolog中的信息,对数据库的数据进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有数据在写入BufferPoo或者在BufferPool中修改数据之前,都会先写入redolog ,保证了数据不会因mysql宕机而丢失,从而保证了数据的持久性。

那么既然redolog也是在数据提交时将数据写入数据库,那么它为什么比通过BufferPool写入数据库的效率要高呢?

主要是以下两方面的原因:

1.redolog是顺序IO,而BufferPool是随机IO,进行数据读写的位置随机生成,速度相对顺序IO较慢

2.BufferPool写入数据的方式是以一个数据页为单位,一般mysql的page大小为为16kb,而一旦一个页有任何数据的修改,都需要整页数据重写写入,而redolog是真正的有效写入:只写入新添加的或者修改的数据,无效IO大大减少

三.隔离性

1.定义:

隔离性是研究事务之间的相互影响,隔离性是指事务内部的操作和其他事务之间是隔离的,在并发环境中,各个事务互不干扰,严格的隔离性,对应了事务隔离级别中的Serializable (可串行化),但实际应用中出于性能方面的考虑很少会使用可串行化。

2.实现原理

隔离性追求的是并发事务中彼此之间不相互影响,而在我们日常的操作中最主要考虑的是读操作和写操作:
1.一个写操作对另一个写操作的影响:通过锁机制进行解决

2.一个写操作对另一个读操作的影响:通过MVCC机制进行解决

1.锁机制:在写操作要求中,在同一时间只能允许一个事务对同一部分数据进行写操作,innoDB实现的锁机制的实现原理可以这样理解:事务在对数据进行写操作之前,要先获取锁资源,然后此时才能对数据进行写操作,其他事务想要获取锁资源必须等待当前事务进行事务的回滚或者提交写操作之后释放锁。

行锁和表锁:按照锁的粒度,可以将锁分为行锁和表锁以及介于两者之间的锁,表锁是在事务进行操作数据时锁定整张表,进行数据的操作时并发性能差,而行锁是在事务操作数据时只锁定被操作的数据,并发性能好,但是考虑到锁的创建,检查以及销毁都需要消耗资源,所以一般而言,表锁相对于行锁能节省部分资源,但是考虑到业务和性能需求,所以在一般情况下都使用行锁,但是sql中不同的存储引擎对表锁和行锁的支持也有所不同,对于innoDB而言,其支持行锁和表锁。

有关事务的隔离性以及不同隔离性可能会产生的问题,推荐大家看我另一篇文章,在这里就不进重复的赘述了:



关于对事务隔离性的深入理解_努力努力再努力mlx的博客-CSDN博客

2.MVCC机制:在sql的隔离级别中默认的隔离级别是可重复读(Repeatly Read),一般而言,RR不能解决幻读的问题,但是innoDB实现的RR能够避免幻读问题的产生,RR解决脏读、不可重复读、幻读等问题,使用的是MVCC:MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。MVCC具有以下特点:在同一时间,不同事务所读取的数据可能是不同的(不同的版本中的数据不同),如下图能比较好的体现这一特点:在T5时刻,事务A和事务C可以读取到不同版本的数据。

MVCC最大的好处是可以不加读锁,因此读写不冲突,而innoDB实现的MVCC,可以允许多个版本共存,其功能的实现主要是基于以下的技术和 数据结构:
1.隐藏列:数据库中的每条数据都有隐藏列,隐藏列有指向本行数据事务的id和指向undolog的指针

2.基于undolog的版本链:每条数据的隐藏列中都有指向undolog的指针,而每条undolog的指针也会指向更早版本的undolog,从而形成一条undolog版本链

3.ReadView:通过隐藏列和版本链,能将数据恢复到之前的版本,但是具体要恢复到哪个版本,则需要具体的ReadView来确定。所谓的ReadView ,是指事务(事务A)在某一时刻对整个事务系统(trx_sys)打快照,等之后再进行读操作时,会将读取到的事务id和trx_sys作比较,从而判断想读取的数据对该ReadView是否有效,即对事务A是否有效。

trx_sys中的主要内容,以及判断可见性的规则如下:

low_limit_id:表示生成的ReadView 中系统应分配给事务的下一个id.如果事务的id大于等于该low_limit_id,则对该ReadView不可见。

up_limit_id:表示在生成ReadView时在系统中活跃的事务,如果活跃事务的id小于up_limit_id,,则对该ReadView 可见

rw_trx_ids:表示在生成ReadView时在系统中活跃事务的id列表,如果查询数据的id在low_limit_id和up_limit_id之间,则需要看事务是否在rw_trx_ids中,如果在,则说明生成ReadView时事务仍在活跃中,则对该ReadView不可见,如果不在,说明生成ReadView时事务已经提交了,因此数据对ReadView可见。

3.MVCC是如歌规避脏读、不可重复读和幻读等问题的呢?
3.1脏读:

当事务A在T3时刻读取zhangsan的余额前,会生成ReadView,由于此时事务B没有提交仍然活跃,因此其事务id一定在ReadView的rw_trx_ids中,因此根据前面介绍的规则,事务B的修改对ReadView不可见。接下来,事务A根据指针指向的undo log查询上一版本的数据,得到zhangsan的余额为100。这样事务A就避免了脏读。

3.2不可重复读

当事务A在T2时刻读取zhangsan的余额前,会生成ReadView。此时事务B分两种情况讨论,一种是如图中所示,事务已经开始但没有提交,此时其事务id在ReadView的rw_trx_ids中;一种是事务B还没有开始,此时其事务id大于等于ReadView的low_limit_id。无论是哪种情况,根据前面介绍的规则,事务B的修改对ReadView都不可见。

当事务A在T5时刻再次读取zhangsan的余额时,会根据T2时刻生成的ReadView对数据的可见性进行判断,从而判断出事务B的修改不可见;因此事务A根据指针指向的undo log查询上一版本的数据,得到zhangsan的余额为100,从而避免了不可重复读。

3.3幻读

 

 

MVCC避免幻读的机制与避免不可重复读非常类似。

当事务A在T2时刻读取0<id<5的用户余额前,会生成ReadView。此时事务B分两种情况讨论,一种是如图中所示,事务已经开始但没有提交,此时其事务id在ReadView的rw_trx_ids中;一种是事务B还没有开始,此时其事务id大于等于ReadView的low_limit_id。无论是哪种情况,根据前面介绍的规则,事务B的修改对ReadView都不可见。

当事务A在T5时刻再次读取0<id<5的用户余额时,会根据T2时刻生成的ReadView对数据的可见性进行判断,从而判断出事务B的修改不可见。因此对于新插入的数据lisi(id=2),事务A根据其指针指向的undo log查询上一版本的数据,发现该数据并不存在,从而避免了幻读。

加锁读在查询时会对查询的数据加锁(共享锁或排它锁)。由于锁的特性,当某事务对数据进行加锁读后,其他事务无法对数据进行写操作,因此可以避免脏读和不可重复读。而避免幻读,则需要通过next-key lock。next-key lock是行锁的一种,实现相当于record lock(记录锁) + gap lock(间隙锁);其特点是不仅会锁住记录本身(record lock的功能),还会锁定一个范围(gap lock的功能)因此,加锁读同样可以避免脏读、不可重复读和幻读,保证隔离性。

四.一致性

 

1.概念:致性是指事务执行结束后,数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。

2.实现:一致性是数据库最终追求的目的,原子性,隔离性和持久性,都是为了满足一致性而存在的,除了数据库层面用于保证数据的一致性,一致性的实现在应用层也有所保障。

实现一致性的措施:

1.使用原子性,持久性和隔离性保证一致性,如果这三个特征无法保证,一致性也无法保证

2.数据库本身做出保障,例如不允许向整形数据中插入字符串信息,字符串的长度不允许超过列的最大长度

3.应用层面进行保障,例如如果转账操作只扣除转账者的余额,而没有增加接收者的余额,无论数据库实现的多么完美,也无法保证状态的一致性

五.总结:

  • 原子性:语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log
  • 持久性:保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log
  • 隔离性:保证事务执行尽可能不受其他事务影响;InnoDB默认的隔离级别是RR,RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)
  • 一致性:事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障

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

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

相关文章

本地快速搭建Kubernetes单机版实验环境(含问题解决方案)

Kubernetes是一个容器编排系统&#xff0c;用于自动化应用程序部署、扩展和管理。本指南将介绍Kubernetes的基础知识&#xff0c;包括基本概念、安装部署和基础用法。 一、什么是Kubernetes&#xff1f; Kubernetes是Google开发的开源项目&#xff0c;是一个容器编排系统&…

长沙基层公务员待遇调查结果

之前发放了1000份调查问卷&#xff0c;统计过长沙各个行业&#xff08;其中一半是信息产业从业人员&#xff09;的待遇情况&#xff0c;发现很多人对长沙公务员&#xff08;包含有编制/合同工&#xff09;的待遇很感兴趣。我随手翻了翻几个基层政府单位的财政决算公开说明&…

MySQL笔记2

MySQL笔记2一、CRUD操作1.修改数据&#xff1a;update2.删除数据&#xff1a;delete二、数据库中表的约束1.非空约束 not null2.唯一性约束 unique3.主键约束 primary key4.外键约束三、索引1**什么是索引**&#xff1f;2**MySQL中最经典的两种存储引擎**3**为何需要索引**&…

Linux项目日志管理log4cpp的安装与使用【结合sample】

文章目录前言log4cpp安装log4cpp的使用设置类别输出的&#xff08;category&#xff09;和日志优先级&#xff08;priority&#xff09;定义一个宏用于输出日志配置文件使用log4cpp的栗子结语前言 我们都清楚对于一个项目来说它的日志信息是非常重要的&#xff0c;那么我们应该…

springcloud微服务架构搭建过程

项目地址&#xff1a;源代码 仅作为学习用例使用&#xff0c;是我开发过程中的总结、实际的一部分使用方式 开发环境&#xff1a; jdk11 springboot2.7.6 springcloud2021.0.5 alibabacloud 2021.0.4.0 redis6.0 mysql8.0 一、项目搭建 wdz-api&#xff1a;存放远程服务调用相关…

VS for Qt 向MySql 数据库中插入中文

问题&#xff1a; 今天我想向数据库中插入中文&#xff0c;但是&#xff0c;插入的时候会报错&#xff1a; 首先先看报错&#xff1a; QSqlError("1054", "QMYSQL: Unable to execute query", "Unknown column 韩红 in field list")如果错误码…

将Linux服务器上的项目上传至Github

使用git上传项目到github常规的步骤继续上传注意事项参考文章常规的步骤 初始化git空间 git init向缓冲区添加想要上传的文件 git add -f /data/xuhongbo/xuhongbo.code/unbiased_sgg_xuhongbo_BCL/maskrcnn_benchmark/*添加备注信息告诉机器&#xff0c;你真的要添加上述文…

elasticsearch-7.17.9

1、ElasticSearch 1.1、概念 1.1.1、分片(shard) 1、分片 在ES中所有数据的文件块&#xff0c;也是数据的最小单元块&#xff0c;整个ES集群的核心就是对所有分片的分布、索引、负载、路由等达到惊人的速度。 实列场景&#xff1a; 假设 IndexA 有2个分片&#xff0c;向 I…

数据结构 - 计数排序 | C

什么是计数排序 如上图&#xff0c;统计数组中值的个数&#xff1a; 2个[1]&#xff1a;1&#xff0c;1 1个[2]&#xff1a;2 3个[3]&#xff1a;3&#xff0c;3&#xff0c;3 2个[4]&#xff1a;4&#xff0c;4 传给原数组&#xff1a;&#xff08;即完成排序↓&#xff09; …

Fast R-CNN

目录 1. 关于 R-CNN 的缺点 2. Fast R-CNN 3. Fast R-CNN 算法的流程 3.1 CNN 特征提取 3.2 ROI pooling 3.3 Fast R-CNN 的输出 3.4 损失函数 4. Fast R-CNN的不足 1. 关于 R-CNN 的缺点 RCNN算法流程如下 RCNN算法分为四个步骤&#xff1a; SS 算法生成2000个候选框…

解除游戏多开限制,关闭互斥体句柄

游戏限制多开有很多种方法 比如说遍历窗口,遍历进程,配置文件,注册表,互斥体,mac地址,ip,公共文件,内存映射等等.方法很多.但是绝大部分游戏限制多开都是采用的互斥体.这节课我们来讲解一下关闭互斥体句柄来实现多开.例子为CQYH(这里的防护建议是,增加多种多开限制的方法 以及 …

系统安全与应用【上】

文章目录1.账号安全控制1.1 系统账号清理1.2 密码安全控制1.3 命令历史限制1.4 终端自动注销2.系统引导和登录控制2.1 使用su命令切换用户2.2 限制使用su命令的用户3.可插拔式认证模块PAM3.1 linux中的PAM安全认证3.2 PAM认证原理3.3 PAM认证的构成3.4 PAM安全认证流程3.5 使用…

(八)【软件设计师】计算机系统—浮点数

浮点数 浮点数。当机器字长为n时&#xff0c;定点数的补码和移码可表示2的n方个数&#xff0c;而其原码和反码只能表示2"-1个数&#xff08;0的表示占用了两个编码)&#xff0c;因此&#xff0c;定点数所能表示的数值范围比较小&#xff0c;在运算中很容易因结果超出范围而…

实力爆表,日日新成为AI领航者

目录正式发布自建算力SenseChat编程能力图像生成后言上周五&#xff0c;阿里发布大模型通义千问&#xff0c;正式开始邀请内测。本周一&#xff0c;人工智能巨头商汤科技正式发布“日日新”大模型体系&#xff0c;全面丰富的产品体系&#xff0c;多个功能表现超预期&#xff0c…

MobTech MobPush|不同手机厂商推送问题

配置了华为厂商推送&#xff0c;为什么有的华为设备无法接收离线消息 首先&#xff0c;排查配置的华为厂商参数是否正确&#xff1b; 其次&#xff0c;检查华为设备EMUI版本&#xff0c;低于5.0可能不支持&#xff0c;如果低于5.0&#xff0c;可以尝试升级设备里的‘华为移动服…

Google代码覆盖率最佳实践

软件质量保障: 所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。谷歌一直倡导的领域之一是使用代码覆盖率数据评估风险并识别测试中的真空。然而&#xff0c;代码覆盖率的价值一直是个争议的话题。每次聊到代码覆盖率时&#xff0c;似乎都会引发无尽的争论。由于大家固…

微信小程序开发 | 小程序开发框架

小程序开发框架7.1 小程序模块化开发7.1.1 模块7.1.2 模板7.1.3 自定义组件7.1.4插件7.2 小程序基础样式库—WeUI7.2.1 初识WeUI7.2.2【案例】电影信息展示7.3 使用vue.js开发小程序7.3.1 初识mpvue7.3.2 开发工具7.3.3 项目结构7.3.4【案例】计数器7.4 小程序组件化开发框架7.…

Ztree树状的处理

1.用一个div进行包裹ztree结构&#xff0c;引用相关的js代码和css样式&#xff0c;这里用的样式是awesome.css 所引用的js文件&#xff0c;css文件可以在网上下载&#xff08;这里所用到的jquery-ztree文件放在网盘了&#xff09; <ul id"tree" class"ztre…

企业即时通讯软件开发基本功能有哪些?

即时通讯是基于互联网技术的新型交流沟通方式&#xff0c;是目前最流行的通讯方式&#xff0c;广泛的应用市场使得各种各样的即时通讯软件系统也层出不穷&#xff0c;企业即时通讯就是其中的一种延伸。是一种面向企业终端使用者的网络营销、网络沟通和内容管理的工具服务&#…

mysql基础安装以及问题

mysql 基础安装以及问题安装MySQL8.0的安装&#xff1a;MySQL5.7 版本的安装、配置卸载服务的启动与停止图形化工具推荐安装 官网&#xff1a;https://www.mysql.com MySQL8.0的安装&#xff1a; 这里是写你直接要安装的目录&#xff1a; 之后配置mysql8.0 注意&#x…