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

一.什么是事务的四特征

  • 原子性(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.mfbz.cn/a/5626.html

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

相关文章

java中File转为MultipartFile的问题解决

今天为了需要&#xff0c;把File需要转为MultipartFile&#xff0c;下列代码&#xff0c;编译启动都没有问题 public static MultipartFile getMultipartFile(File file){FileInputStream fileInputStream;MultipartFile multipartFile;try {fileInputStream new FileInputSt…

《JavaEE初阶》计算机网络之网络原理(应用层)

《JavaEE初阶》计算机网络之网络原理(应用层) 文章目录《JavaEE初阶》计算机网络之网络原理(应用层)前言:应用层:自定义应用层协议:如何进行自定义应用层协议自定义应用层协议的格式选择:应用层的现成协议.前言: 本章主要讲解计算机网络原理中的应用层概念以及如何自定义应用层…

centos7 安装photoprism部署私人相册

1、安装docker; 这个是前置条件&#xff0c;也很简单&#xff0c;暂且不表。 2、安装docker-compose&#xff1b; curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose #下载docker-co…

如何让你的blynk服务器随ubuntu系统启动?

昨天在ubuntu系统搭建了blynk服务器&#xff0c;无奈每次重启都要手动去启动&#xff0c;麻烦&#xff01; 今天就把它加入系统服务里面运行&#xff0c;一劳永逸 首先用WINSCP连接ubuntu在/root/文件夹下新建一个blynk文件夹 把blynk服务器文件放到文件夹中 在/etc/systemd/…

黑马程序员Java教程学习笔记(六)

学习视频&#xff1a;https://www.bilibili.com/video/BV1Cv411372m 如侵权&#xff0c;请私信联系本人删除 文章目录黑马程序员Java教程学习笔记&#xff08;六&#xff09;File概述、File对象创建File类的常用方法方法递归非规律化递归问题&#xff1a;文件搜索IO前置内容&am…

P1003 [NOIP2011 提高组] 铺地毯

题目描述 为了准备一个独特的颁奖典礼&#xff0c;组织者在会场的一片矩形区域&#xff08;可看做是平面直角坐标系的第一象限&#xff09;铺上一些矩形地毯。一共有 &#xfffd;n 张地毯&#xff0c;编号从 11 到 &#xfffd;n。现在将这些地毯按照编号从小到大的顺序平行于…

C语言试题生成与考试系统的设计与实现

当前&#xff0c;网络教学方兴未艾。网上考试已在其中扮演了重要的角色&#xff0c;传统试卷考试方式有待提高。网络教学已从其规范性、科学性及考试工作组织、管理的统一性&#xff0c;影响到教学质量的好坏。基于此&#xff0c;本系统开发实现了基于B/S模式的c试题生成与考试…

经典毕设项目-博客系统(spring boot、spring mvc、mybatis) gitee开源源码

目录 项目背景 核心技术 项目页面设计 注册页面 登录页面 博客列表页 博客详情页 个人博客列表页 个人博客发布页 个人博客修改页 项目模块与需求分析 AOP 处理模块 用户模块 文章模块 项目创建 实现 AOP 模块 实现登录拦截器 拦截器 拦截注册 实现统一数据…

补充C语言

1.关键字 前言: C90一共有32个关键字,C99比C90多了5个关键字,但主流的编译器对C99关键字支持的不是特别好, 所以后面主要以C90的32个关键字为标准1.1认识auto关键字 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int i 0;auto int j 0;retur…

为什么要参加软考?软考如何备考?

软考是指软件工程师职业资格考试&#xff0c;它是由国家人力资源和社会保障部颁发的国家级职业资格证书&#xff0c;是目前我国最具权威性的计算机职业资格证书之一。软考考试内容丰富&#xff0c;包括软件工程、软件测试、软件项目管理、数据库等多个方面&#xff0c;考试难度…

Java分布式事务(七)

文章目录 🔥Seata提供XA模式实现分布式事务_业务说明🔥Seata提供XA模式实现分布式事务_下载启动Seata服务🔥Seata提供XA模式实现分布式事务_搭建聚合父工程构建🔥Seata提供XA模式实现分布式事务_转账功能实现上🔥Seata提供XA模式实现分布式事务_转账功能实现下🔥Se…

Qt-Web混合开发-CEF加载网页简单示例(12)

Qt-Web混合开发-CEF加载网页简单示例&#x1f499;&#x1f353; 文章目录Qt-Web混合开发-CEF加载网页简单示例&#x1f499;&#x1f353;1、概述&#x1f41b;&#x1f986;2、实现效果&#x1f605;&#x1f64f;3、实现功能&#x1f42e;&#x1f434;4、Qt部分关键代码&am…

2023/4/2总结

题解 线段树OR树状数组 - Virtual Judge (vjudge.net) 正如这道题目一样&#xff0c;我的心情也如此。 1.这道题是线段树问题&#xff0c;更改学生值即可&#xff0c;不需要用到懒惰标记。 2.再去按照区间查找即可。&#xff08;多组输入&#xff0c;拿20多次提交换来的&am…

2023大数据开发就业前景怎么样?

大数据开发就业班正在火热招生中。 大数据开发做什么&#xff1f; 大数据开发分两类&#xff0c;编写Hadoop、Spark的应用程序和对大数据处理系统本身进行开发。大数据开发工程师主要负责公司大数据平台的开发和维护、相关工具平台的架构设计与产品开发、网络日志大…

【算法基础】(一)基础算法 --- 位运算

✨个人主页&#xff1a;bit me ✨当前专栏&#xff1a;算法基础 &#x1f525;专栏简介&#xff1a;该专栏主要更新一些基础算法题&#xff0c;有参加蓝桥杯等算法题竞赛或者正在刷题的铁汁们可以关注一下&#xff0c;互相监督打卡学习 &#x1f339; &#x1f339; &#x1f3…

C语言函数大全--d开头的函数

C语言函数大全 本篇介绍C语言函数大全–d开头的函数 1. detectgraph 1.1 函数说明 函数声明函数功能void detectgraph(int *graphdriver, int *graphmode);通过检测硬件确定图形驱动程序和模式 1.2 演示示例 #include <graphics.h> #include <stdlib.h> #incl…

【Java 并发编程】一文读懂线程、协程、守护线程

一文读懂线程、协程、守护线程1. 线程的调度1.1 协同式线程调度1.2 抢占式线程调度1.3 设置线程的优先级2. 线程的实现模型和协程2.1 内核线程实现2.2 用户线程实现2.3 混合实现2.4 Java 线程的实现2.5 协程2.5.1 出现的原因2.5.2 什么是协程2.5.3 Java19 虚拟线程 - 协程的复苏…

Activiti7与Spring、Spring Boot整合开发

Activiti整合Spring 一、Activiti与Spring整合开发 1.1 Activiti与Spring整合的配置 1)、在pom.xml文件引入坐标 如下 <properties><slf4j.version>1.6.6</slf4j.version><log4j.version>1.2.12</log4j.version> </properties> <d…

【源码教程案例】AI绘画与安全在未来主要方向有哪些?

AI绘画在未来有许多潜在的发展方向,以下是一些可能的重点领域 高质量图像生成:随着生成模型的不断改进,未来的AI绘画可能会产生更高质量、更真实的图像,以满足各种应用场景的需求。 个性化创作:AI绘画可以通过用户的个性化偏好和需求来定制艺术作品。这种定制可能包括颜…

【gitlab部署】centos8安装gitlab(搭建属于自己的代码服务器)

这里写目录标题部署篇序言要求检查系统是否安装OpenSSH防火墙问题准备gitlab.rb 配置坑点一忘记root密码重置使用篇gitlab转换成中文git关闭注册入口创建用户部署篇 序言 在团队开发过程中&#xff0c;想要拥有高效的开发效率&#xff0c;选择一个好的代码开发工具是必不可少的…
最新文章