前言

《MySQL事务详解》一文中详细讲解了事务的概念,包括ACID特性,事务并发引起的问题,事务的四种隔离级别。
在事务的四种特性中,原子性、一致性、持久性通过数据库的redo log和undo log来完成,redo log称为重做日志,用来保证事务的原子性和持久性,undo log称为回滚日志,用来保证事务的一致性。事务的隔离性通过锁机制来实现。
这篇文章主要讲解redo log和undo log实现一致性、原子性和持久性。

redo 和 undo的作用都可以视为是一种恢复操作,redo恢复提交事务时修改的页操作,而undo回滚行记录到某个特定版本。因此两者记录的内容不同,redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。

redo log

redo log称为重做日志,用来保证事务的原子性和持久性。重做日志即innodb存储引擎产生的日志,默认在mysql/data目录下面有两个文件ib_logfile0和ib_logfile1。当MySQL的实例和介质失败的时候,Innodb存储引擎就会使用重做日志文件进行恢复,保证事务的持久性。

重做日志由两部分组成:

  • 内存中的重做日志缓冲(redo log buffer),易丢失
  • 重做日志文件(redo log file),持久的

InnoDB存储引擎首先将重做日志信息放入重做日志缓冲区中,然后按一定的频率将其刷新到重做日志文件。该缓冲区不会设置得很大,因为一般每一秒刷新一次到日志文件中。

下图显示MySQL5.6下该缓冲区默认为8M:

一般会在一下三种情况刷新重做日志缓冲到重做日志磁盘文件中:

  • 主线程每一秒刷新一次重做日志缓冲到重做日志磁盘文件中(同步fsync方式)
  • 每个事务提交时由innodb_flush_log_at_trx_commit参数控制,其值取0表示事务提交时不触发写磁盘,而是等待主线程每秒的刷新操作,其值取1(默认值)表示同步写磁盘,其值取2表示异步写磁盘,即不能保证commit时一定会刷新重做日志缓冲到重做日志磁盘文件中,只是有这个动作发生

innodb_flush_log_at_trx_commit对事物提交性能的影响

由于innodb_flush_log_at_trx_commit默认值为1,所以默认情况下,当事务commit时,必须先将该事务的所有日志从重做日志缓冲中同步写入到重做日志文件进行持久化,该事物的commit操作才算完成。重做日志文件没有使用O_DIRECT选项,因此重做日志先写入文件系统缓存。为了确保重做日志写入磁盘,必须进行一次fsync操作,该操作的效率取决于磁盘的新能,进而影响了数据库的性能。

  • O_DIRECT: 任何读写操作都只在用户态地址空间和磁盘之间传送而不经过page cache。
  • O_SYNC: 只影响写操作,block当前写进程,先从用户态内存写入page cache, 再从page cache写入磁盘,然后才返回到用户进程。

下面比较innodb_flush_log_at_trx_commit对事物提交性能的影响:

先创建表t1和存储过程p_load:

在innodb_flush_log_at_trx_commit参数为1的情况下,执行命令CALL p_load(50 000),即向表t1插入50万行记录,并执行50万次fsync操作,所需时间接近2分钟:

在innodb_flush_log_at_trx_commit参数为0的情况下,所需时间大概为13秒:

innodb_flush_log_at_trx_commit设置不同值对于插入速度的影响:

因此,为了提高事务的提交性能,应该将大批量的数据放在事务中一次性commit,而且还有个好处是还可以使事务回滚时回到最开始的状态。

log block

在InnoDB存储引擎中,重做日志是以512字节(也是一个扇区的大小)进行存储的。这意味着重做日志缓存、重做日志文件都是以块的方式进行保存的,称之为重做日志块,每块的大小为512字节。若一个页中产生的重做日志数量大于512字节,则需要分割为多个重做日志块进程存储。

undo log

重做日志记录了事务的行为,可以很好的通过其对页进行“重做”操作,但是事务有时还需要回滚操作,这是就需要undo,将数据回滚到修改之前的样子。redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。
上面说过redo存放子重做日志文件中,默认在mysql/data目录下面的两个文件ib_logfile0和ib_logfile1中。而undo存放在数据库内部的一个特殊段中,这个段称为undo段。

一个事务在修改当前一个页中某几条记录,同时还可能存在别的事务在对同一个页中另几条记录进行修改,因此,不能将一个页回滚到事务开始的样子,因为这样会影响到其他事务正在进行的工作。

undo log如何实现回滚?

用户执行了一个INSERT 10W条记录的数据,这个事务会导致分配一个新的段,即表空间会增大,但是事务ROLLBACK时,只是将插入操作的事务进行回滚,并没有缩减表的大小。因此,事务回滚实际做的是和之前相反的工作。对于INSERT,INSERT,对于DELETE,InnoDB存储引擎会完成一个INSERT操作,对于UPDATE,InnoDB存储引擎会完成一个相反的UPDATE操作。

这就实现了InnoDB存储引擎的回滚机制。

undo log的另一个作用

undo log的另一个作用是实现MVCC(多版本并发控制)。当用户读取被其他事务占用的记录时,可以通过undo读取之前的版本信息(即快照读),以此实现非锁定读。

此外,undo log会产生redo log,因为undo log也需要被记录下来,需要持久性的保护。

MySQL事务原子性、一致性和持久性以及回滚是如何实现的?相关推荐

  1. MySQL怎么运行的系列(八)14张图说明白MySQL事务原子性和undo日志原理

    本系列文章目录 展开/收起 MySQL怎么运行的系列(一)mysql体系结构和存储引擎 MySQL怎么运行的系列(二)Innodb缓冲池 buffer pool 和 改良版LRU算法 Mysql怎么运 ...

  2. Spring 事务 状态信息的创建、回滚、清理、提交

    为什么80%的码农都做不了架构师?>>>    Spring 的事务是依据AOP来实现的,通过AOP从切面来抓捕异常判断是否回滚以及如何回滚,若是正常的返回则是清理事务信息,实施事务 ...

  3. mysql 事务原子性_数据库事务原子性、一致性是怎样实现的?

    先借用前辈的一句话:数据库事务有不同的隔离级别,不同的隔离级别对锁的使用是不同的,锁的应用最终导致不同事务的隔离级别. 隔离性分为四个级别: 1读未提交:(Read Uncommitted) 2读已提 ...

  4. (MYSQL学习笔记4)事务的开启、提交、回滚

    使用事务要注意以下三点: 1.在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务. 2.事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执 ...

  5. mysql 删除最后100条_sql-如何回滚我在MySQL中的最后一个删除命令?

    sql-如何回滚我在MySQL中的最后一个删除命令? 我不小心从表中删除了很多行... 如何退回? 我使用PuTTY执行查询. 如果您能安全地指导我,我将不胜感激. 10个解决方案 96 votes ...

  6. MySQL 技术篇- linux下mysql数据库利用binlog文件进行数据回滚实例演示,binlog恢复数据库的两种方式

    MySQL 数据库数据回滚 第一章:利用 binlog 进行数据回滚 ① 查看 binlog 文件所在位置 ② 查看主数据正在存储数据的 binlog 文件名 ③ 在控制台查看 binlog 文件内容 ...

  7. Spring事务方法与非事务方法执行相互调用不回滚,你踩过这个坑没?

     作者:西风一任秋 blog.csdn.net/m0_38027656/article/details/84190949 写这篇文章的初衷呢就是最近遇到了一个spring事务的大坑.与其说是坑,还不如 ...

  8. Spring事务抛出Exception异常不回滚

    今天有个业务逻辑流程为: 1.访客预约确认先更新预约状态为"预约确认" 2.调用http接口发短信.更新预约状态为"预约成功"等一系列操作 这里面有个问题,如果 ...

  9. sqlserver事务怎么开启 怎么提交 怎么回滚

    1.自动transaction 每句statement都是一个transaction.例一个update指令更新多笔纪录, 要就全部成功, 只要失败,全部会回复原值. 2.ExplicitTransa ...

  10. redis mysql 事务_Mysql与Redis事务

    Mysql事务ACID基于日志 AC:回滚日志实现回滚(原子性) D:重做日志实现持久化 I:加锁实现隔离级别  (MVVC无锁机制也可实现可重复读) 读未提交 存在问题:脏读(外部select事务内 ...

最新文章

  1. UIWebView内存泄露问题解决方法
  2. android 请求参数打印,Android开发-----关于解决Retrofit打印HttpLog和设置连接超时的问题...
  3. 一探即将到来的 C# 10
  4. java7和java8切换_仍不切换到Java 8的6个理由
  5. window 快捷键使用 + idear 编辑器使用
  6. 程序-进程-线程 ( 多线程 )
  7. vs code 问题:preLaunchTask“build”已终止,退出代码为 1。解决办法
  8. 必须包含数字和字母,字符随意的正则表达式
  9. 正则表达式re中的group含义
  10. 知识图谱(以金融知识图谱为例)
  11. 植物大战僵尸修改植物攻击力
  12. matlab初值随机扰动,GRAPES区域集合预报系统模式不确定性的随机扰动技术研究
  13. 网站设计65条原则 作者:小柯
  14. 范莎学院 计算机,加拿大范莎学院
  15. 北京交通大学云平台实验虚拟机踩坑
  16. scrum立会报告+燃尽图(第三周第四次)
  17. Python学习0——基础知识1
  18. [PCB]这里带你了解何为PCB?
  19. Java实现QQ窗口自动输入
  20. 从两道基础二分算法题谈check函数的写法

热门文章

  1. “工欲善其事,必先利其器”-- 教你几招如何选择合适的数据可视化工具
  2. 创建计算机桌面快捷方式图标异常,桌面图标显示异常怎么解决
  3. 电商巨头角逐付费会员制,新零售生态或成为决胜关键?
  4. 前端项目使用阿里巴巴icon font的具体过程
  5. 两种无密码解锁iPhone锁屏密码的方法
  6. 奔驰c260语言设置方法图解,奔驰C260L灯光使用方法,C260L灯光开关图解说明
  7. ant design vue table 高度自适应_对比1万2千个Vue.js开源项目发现最实用的 TOP45!火速拿来用!...
  8. Chrome隐私设置错误,您的链接不是私密连接
  9. 程序员有趣的面试智力题
  10. 专访深度学习之父Geoffrey Hinton:人工智能的向量之舞