IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> MySQL事务 -> 正文阅读

[大数据]MySQL事务

目录

一、事务的特性

二、事务的分类

1. 扁平事务

2. 带有保存点的扁平事务

3. 链事务

4. 嵌套事务

5. 分布式事务

三、事务的实现

1. 重做日志文件(redo log file)?

? ? ? ? ①. 基本概念

? ? ? ? ②. 重做日志格式

? ? ? ? ③. 日志块(log block)?

? ? ? ? ④. 日志组(log group)

? ? ? ? ⑤. 日志序列编号(LSN)

????????⑥. 恢复

2. undo日志(undo log)

????????①. 基本概念

? ? ? ? ②. undo日志格式

? ? ? ? ③. undo存储管理?

3. purge操作

4. 组提交(group commit)

三、事务的隔离级别

四、隐式提交的SQL

五、参考资料


一、事务的特性

????????事务有ACID特性:A原子性、C一致性、I隔离性、D持久性。InnoDB存储引擎中,redo log(重做日志文件,称为日志)实现原子性和持久性;锁实现隔离性;undo log(回滚日志)实现一致性。

? ? ? ? 如下表所示,ACID特性的对比。事务的持久性则采用Force Log at Commit机制实现,即:事务提交时,必须先将该事务的所有日志写入到redo log(重做日志文件)进行持久化,然后事务提交后才算真正完成。

特性概念实现

原子性

(A _ Atomicity)

1. 事务中的所有SQL语句,要么都成功或失败;

2. 事务是不可分割的工作单位

redo log

一致性

(C _ Consistency)

1. DB从一种状态转到另一个一致的状态;

2. 事务是一致性的单位。

undo log

隔离性

(I _ Isolation)

事务提交之前对其他事务都不可见lock

持久性

(D _ Durability)

事务提交后即使发生宕机,则也是永久性的redo log

二、事务的分类

????????InnoDB存储引擎支持扁平事务、保存点的扁平事务、链事务、分布式事务,原生不支持嵌套事务,下图事务分类总结。

类型特点
扁平事务

1. 所有操作处于同一层次,不能提交部分操作,其是最频繁的事务;

2. 应用程序中原子操作的基本组成模块

带有保存点的扁平事务1. 支持扁平事务外,还支持回滚到某个保存点
链事务

1. 事务提交后隐式地开启下一个事务;

2. 事务提交和开启下一个事务为一个原子操作

3. 链事务回滚仅限于当前事务,即:只能回滚到最近一个保存点;

4. 链事务:提交后释放当前事务所持有的锁; ? ?

? ? 带有保存点的扁平事务:不影响迄今为止所持有的锁。

嵌套事务

1. 顶层事务控制子事务;

2. 任何子事务都在顶层事务提交后才真正的提交

3. 子事务仅保留A、C、I特性,不具有D特性;

4. 嵌套事务中任意一个事务回滚,则所有子事务一同回滚。

分布式事务

1.?多个独立的事务资源参与到一个全局事务中;

2. InnoDB存储引擎支持XA事务(主从复制)

1. 扁平事务

????????扁平事务(Flat Transaction)指所有操作处于同一层次中,由BEGIN开始,COMMIT或ROLLBACK结束,实际生产中使用最频繁的事务。因此,扁平事务是应用程序成为原子操作的基本组成模块。

? ? ? ? 如下图所示,扁平事务中的三种情况。看出,扁平事务的主要限制不能提交或回滚事务的一部分

2. 带有保存点的扁平事务

????????带有保存点的扁平事务(Flat Transaction?with Savepoint) 指事务执行过程中回滚到同一事务中较早的一个状态,也支持扁平事务。

????????保存点(Savepoint)用来通知系统记住当前事务的状态,以便之后发生错误时,事务能回滚到保存点当时的状态。注意,保存点在事务内部是单调递增,即使回滚后再开始操作,也不影响保存点的计数。如下图所示。

事务中使用保存点

????????事务开始时,隐式地设置一个保存点。那么在扁平事务中,只有一个保存点,因此只能回滚到事务的开始状态。

3. 链事务

????????链事务(Chained?Transaction)指当前事务提交和开始下一个事务合并为一个原子操作。在当前事务提交后,释放数据对象,将必要的处理上下文隐式地传给下一个事务,即:下一个事务会看到上个事务的处理结果

????????链事务与带有保存点的扁平事务的区别:

  • 回滚:带有保存点的扁平事务能回滚到任意正确的保存点;链事务只能回滚最近的一个保存点
  • 锁:带有保存点的扁平事务不影响迄今为止所持有的锁;链事务提交后释放当前事务持有的锁

4. 嵌套事务

????????嵌套事务(Nested Transaction)指事务中嵌套事务,顶层事务(父事务)控制着各个层次的事务(子事务)

? ? ? ? 嵌套事务的特点:

  • 位于根节点的事务称为顶层事务(父事务),其他事务称为子事务;
  • 任何子事务提交后不是立即提交,而是顶层事务提交后才真正提交
  • 任何事务回滚都会引起其他事务一同回滚,故子事务有A、C、I特性,不具有D特性。

5. 分布式事务

????????分布式事务(Distributed Transaction)指在多个独立的事务资源参与到一个全局事务中。InnoDB存储引擎对XA事务的支持。

? ? ? ? XA事务由一个或多个资源管理器、一个事务管理器、一个应用程序组成:

  • 资源管理器(Resource Managers):提供访问事务资源的方法(DB就是资源管理器)
  • 事务管理器(Transaction Manager):协调参与全局事务中的各个事务
  • 应用程序(Application Program):定义事务边界,指定全局事务的操作

????????XA分布式事务使用的是两阶段提交方式:

  • 第一阶段:所有参与全局事务的节点开始准备(Prepare)_ 告诉事务管理器准备好提交;
  • 第二阶段:事务管理器告诉资源管理器执行事务提交或回滚。

? ? ? ? MySQL数据库中还存在另外一种分布式事务,不同存储引擎之间的事务,称为内部XA事务。最常见的内部XA事务存在于binlog与InnoDB存储引擎之间。在事务提交时,先写二进制日志,再写InnoDB重做日志,两个写入要求是原子操作,否则主从数据库存在数据不一致。如下图所示,数据库宕机发生在①、②之后,③之前,则会导致主从数据库存在数据不一致。

? ? ? ? 为了解决这个问题,如下图所示,采用XA事务。当事务提交时,InnoDB存储引擎会先做一个PREPARE操作,将事务xid写入。数据库发生宕机恢复后,先检查准备的UXID事务是否已经提交,若没有,InnoDB存储引擎层会再一次执行提交操作

三、事务的实现

1. 重做日志文件(redo log file)?

? ? ? ? ①. 基本概念

????????重做日志文件(redo log file)记录提交事务修改页的操作,是物理日志(默认数据目录下:ib_logfile0、ib_logfile1)。其目的:实现事务的原子、持久特性,数据库的恢复使用。

? ? ? ? 事务由两部分组成:

  • 重做日志缓冲(redo log buffer):内存存储;易丢失、写入快
  • 重做日志文件(redo log file):物理文件;持久存储,写入慢

? ? ? ? 事务日志的产生过程:

  • step1:事务开始时,产生对页修改的操作日志,写入重做日志缓冲中;
  • step2:事务提交时,重做日志缓冲写入文件系统缓存;
  • step3:写入文件系统缓存后,InnoDB调用一次fsync确保日志写入到redo log file

????????需要注意的是:step3写入磁盘执行时间最慢,磁盘的性能决定事务提交的性能,也决定DB的性能。参数innodb_flush_log_at_trx_commit控制重做日志刷新到磁盘的策略,默认1(事务提交同步一次fsync)?。

????????事务的持久性则采用Force Log at Commit机制实现:事务提交时,必须先将该事务的所有日志写入到redo log file(重做日志文件)进行持久化,然后事务提交后才算真正完成,即:事务提交时,先写重做日志再提交事务

????????重做日志(redo log)与二进制日志(binlog)的区别,如下表所示。

区别redo logbinlog
产生层次InnoDB存储引擎层MySQL数据库层 (任何引擎都会产生)
内容形式物理日志,记录页的修改逻辑日志,记录对应的SQL或行
写入磁盘的时机

1. 事务进行中不断的被写入磁盘,不是事务提交的顺序写入;

2. 每个事务对应多条日志,写入是并发的

1.事务提交后完成一次写入;

2.按事务提交顺序写入,一个事务只能对应一个日志

? ? ? ? 如下图所示,二进制日志对每一个事务仅保存一个日志,且按事务提交的顺序写入;重做日志对每个事务则对应多个日志条目(不同的页修改操作)且事务并发写入,不是事务提交的顺序写入

redo log和binlog写入的时间点不同

? ? ? ? ②. 重做日志格式

? ? ? ??重做日志格式组成如下图所示,可以看出redo log是记录页的修改操作

????????根据不同的重做日志类型,会有不同的redo log body,如下图所示。

插入和删除的重做日志格式

? ? ? ? ③. 日志块(log block)?

????????InnoDB存储引擎中,重做日志以512字节(块)存储,即:重做日志缓存、重做日志文件都是以块的形式进行保存,称之为“重做日志块”(redo log block)。重做日志块大小与磁盘扇区大小一样都是512字节,因此重做日志写入可以保证原子性,无需doublewrite技术。若修改页的重做日志大于512字节,则需要分割多个重做日志块进行存储。

????????重做日志块的组成:块512字节 = 头部12字节 + 内容 492(512-12-8)字节 + 尾部8字节,如下图所示。内容存储重做日志(重做日志格式见上小节)。

????????注意:其中LOG_BLOCK_FIRST_REC_GROUP表示块中第一个事务开始位置的日志偏移量, 如下图所示。

? ? ? ? ④. 日志组(log group)

????????重做日志组(log group)是个逻辑概念,由多个重做日志文件组成。组内的文件大小相同,默认总大小512GB。默认情况下,一个InnoDB存储引擎只有一个日志组。

????????重做日志文件存储的就是重做日志缓冲里面的重做日志块,也是以块的形式管理。InnoDB存储引擎运行过程中,重做日志缓存刷新到磁盘的时机如下:

  • 事务COMMIT时
  • log buffer中一半内存空间已被占用时
  • log buffer的Checkpoint时

? ? ? ? 日志块追加到重做日志文件的尾部,当文件被写满时,则写入下一个重做日志文件,即:采用round-robin方式写入。? ? ? ?

? ? ? ? ⑤. 日志序列编号(LSN)

????????日志序列编号(Log Sequence Number _ LSN)表示写入重做日志的字节总数,占用8字节且单调递增。

????????LSN不仅在重做日志,而且还在每个页中。LSN的含义如下:

  • 重做日志写入的字节总量
  • Checkpoint的位置
  • 页的版本(判定页是否刷新、是否需要进行恢复)

????????⑥. 恢复

????????InnoDB存储引擎启动时,不管上次是否正常关闭,则都会尝试进行恢复数据操作。读取重做日志文件,根据数据页Checkpoint的LSN与重做日志文件中修改页的LSN进行比较,来判定数据页是否需要恢复操作

? ? ? ? 重做日志是物理日志,则幂等。而二进制日志是逻辑日志,恢复慢。所以,重做日志恢复速度比二进制日志恢复快。

2. undo日志(undo log)

????????①. 基本概念

????????对数据库修改时,不仅会产生redo log,而且还会产生undo log。回滚日志(undo log)记录修改行的操作,是逻辑日志,存放在共享表空间的undo段(undo segment)。其目的:事务回滚,MVCC技术来实现事务一致性。

? ? ? ? 当InnoDB存储引擎回滚时,实际做的事与先前相反的工作,如下所示。

  • INSERT操作:回滚则完成一个DELETE? ? ? ? ? ? ? ? ? ??
  • DELETE操作:回滚则完成一个INSERT? ? ? ? ? ? ? ? ? ? ?
  • UPDATE操作:回滚则完成一个相反的UPDATE

????????MVCC技术是通过undo log完成,当读取行时,判断该行是否被其他事务占用,若是则当前事务通过undo读取之前的行版本信息,实现非锁定读。

? ? ? ? 事务提交对undo log的处理:

  • 将undo log放入链表中,供purge操作
  • 判断undo log所在页是否可以重用,若可以分配下一个事务

????????需要注意的是,写入undo log日志的过程,也伴随着产生redo log,即:undo log也需要通过redo log来持久化

? ? ? ? ②. undo日志格式

????????回滚日志格式分类,如下:

  • insert undo log:INSERT操作;事务提交后直接删除,无需purge操作
  • update undo log:DELETE/UPDATE操作;事务提交后不直接删除,放入链表等purge操作

? ? ? ? 注意,对于INSERT操作回滚时,则直接删除,符合事务的隔离性(只对当前事务可见,其他事务不可见),而DELETE/UPDATE操作,则放入链表等purge操作真正删除或修改;undo log是逻辑日志,只是将数据逻辑的恢复之前的样子,则回滚被逻辑的取消,但是表空间大小不会因回滚而收缩。

? ? ? ? ③. undo存储管理?

? ? ? ? InnoDB存储引擎对undo segment的管理采用段的方式,支持同时在线的事务数量为:128 * 1024

回滚段(rollback segment):一个undo段(undo segment)支持128个rollback segment

undo日志段(undo log segment):每个rollback segment有1024个undo log segment,在该段中进行undo页的申请

? ? ? ? 与rollback segment相关的参数有:

  • innodb_undo_directory:rollback segment所在的路径,默认./(ibdata1)
  • innodb_undo_logs:rollback segment的个数,默认128
  • innodb_undo_tablespaces:undo日志空间数量,即:构成rollback segment的文件数

? ? ? ? 事务提交时,判定undo页是否重用

  • step1:事务提交时,undo log放入链表中
  • step2:判断所在页使用空间是否小于3/4
  • step3:若可以重用,则之后的undo log记录在当前undo log的后面

3. purge操作

????????当DELETE删除一条记录时,将记录delete flag设置为1,记录并没有删除,还存在于B+树中。所以DELETE和UPDATE操作并不直接删除或修改原有数据,而是“延迟”在purge操作中完成。因此purge用于完成DELETE、UPDATE操作

????????purge用于完成DELETE、UPDATE操作,这样的设计InnoDB存储引擎支持MVCC,若该行记录不被其他事务引用,则可以真正删除操作。根据之前undo log的介绍,一个undo页有多个事务的undo log存在,后面的事务总在最后,但不是事务提交顺序。因此,InnoDB存储引擎有个history list,目的是按事务提交的顺序,将undo log进行链接(先提交放在尾端)

purge操作的过程

? ? ? ? 如上图所示,?purge操作的过程如下。清除undo page,避免大量随机读取操作,提高purge效率

  • step1:从history list找到第一个需被清理的记录,如:trx1;
  • step2:清理step1的记录后,该记录所在页中继续找需被清理的记录,如:trx3、trx7,而trx5被其他事务引用,不能删除;
  • step3:记录所在页没有被清理的记录后,再次去history list找下一个记录,如:trx2。

? ? ? ? 与purge有关的相关参数,innodb_purge_batch_size越大,每次回收undo页就越大,但是太大会导致CPU和磁盘过于集中处理导致性能下降。

参数描述
innodb_purge_batch_size每次purge操作需要清理的undo page的数量,默认300
innodb_max_purge_lag控制history list的最大长度,默认0(不对history list做任何限制)
innodb_max_purge_lag_delay更新行,最大延迟的毫秒数,默认0

4. 组提交(group commit)

????????对于非只读事务时,每次提交事务后需调用一次fsync操作,来保证redo日志已经写入磁盘,而对磁盘的操作效率很慢。因此MySQL提供组提交的功能,其目的是一次fsync刷新多个事务日志写入重做日志文件(提高磁盘fsync效率)

????????MySQL5.6版本之前,开启二进制日志后,group commit功能会失效,而MySQL5.6采用BLGC(Binary Log Group Commit)实现方式。提交顺序放入队列,第一个为leader,其他follower,leader控制follower的行为,如下图所示。BLGC的三个阶段

  • Flush阶段:每个事务的二进制日志写入内存中
  • Sync阶段:内存中的binlog刷新到磁盘,若队列有多个事务,则仅一次fsync(BLGC)
  • Commit阶段:leader根据顺序调用InnoDB事务提交(支持group commit)
BLGC的三阶段

????????当有一组事务在进行Commit阶段时,其他新事务可以进行Flush阶段,从而使group commit不断生效。参数binlog_max_flush_queue_time控制group commit时的flush阶段中等待时间,默认0(不等待),当一组事务完成提交,当前一组事务也不马上进入Sync阶段,而是等待一段时间。

三、事务的隔离级别

????????SQL标准定义的四个隔离级别为:

  • READ UNCOMMITTED:读未提交,会产生脏读(会读取删除/修改的数据)
  • READ COMMITTED:读已提交,会产生不可重复读
  • REPEATABLE READ:可重复读,会产生幻读(读到被事务提交删除的数据)
  • SERIALIABLE:序列化读,并发量低

????????REPEATABLE READ是2.9999?的隔离,没有幻读的保护;而SERIALIABLE称为隔离,或是3?的隔离。SQL和SQL2标准默认事务隔离级别是SERIALIABLE。

? ? ? ? 需要注意的是InnoDB存储引擎默认事务隔离级别是REPEATABLE READ,与SQL标准不同的是,InnoDB存储引擎在该级别下使用Next-Key Lock锁的算法,避免的不可重复读,已经达到了事务的隔离性要求,即达到了SERIALIABLE的隔离性要求。

? ? ? ? InnoDB存储引擎的隔离性是通过锁实现的。READ COMMITTED隔离级别,则采用Record Lock算法,关闭了Gap Lock;REPEATABLE READ隔离级别时,采用Next-Key Lock(Record Lock + Gap Lock);SERIALIABLE隔离级别时,对每个SELECT语句自动加上LOCK IN SHARE MODE,加共享锁,因此读占用了锁,对一致性非锁定读不支持,此时隔离级别符合数据库理论的要求。

四、隐式提交的SQL

????????隐式提交是指执行完这些SQL语句后,会有一个隐式COMMIT操作。如下所示,列出隐式提交有哪些SQL语句。注意TRUNCATE TABLE与DELETE一样,但是不能回滚。

MySQL隐式提交的SQL

五、参考资料

MySQL锁_爱我所爱0505的博客-CSDN博客

SQL提交数据三种类型 - 走看看

数据库事务的四种隔离级别 - Nausicaa0505 - 博客园

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:22:24  更:2022-10-22 21:26:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年5日历 -2025/5/11 5:13:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码