关于事务、redolog 写入的两个问题分析

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 1、那就是如果未提交的时候,redolog写满了,此时是阻塞还是覆盖呢2、如果未提交然后写满了此时落盘了,你磁盘不是有脏数据了么,这二个问题不明白

一 背景

某个讨论群内,有朋友提出这样两个问题:

转文字:

1、那就是如果未提交的时候,redolog写满了,此时是阻塞还是覆盖呢

2、如果未提交然后写满了此时落盘了,你磁盘不是有脏数据了么,这二个问题不明白

关于问题大家在群内做了简单讨论,我再翻阅资料确认一些细节后,得到的分析结果如下。老规矩,先分析、分解问题,【先问是不是,再问为什么】,然后再去寻找、确定答案。

二 问题1

首先,分析了一下问题1的描述:

【未提交】指的是当前存在一个未提交的事务,【redolog写满了】指此时redolog文件此时是写满的状态,所以最终我们的问题是:

1-1 这个未提交事务是否会写redolog

1-2 如果要写redolog,是立即覆盖写入,还是需要阻塞一段时间,然后再写入。

1-1 未提交事务是否会写redolog

涉及事务提交流程和redolog的写入机制:

有binlog情况下,commit动作开始时,会有一个Redo XID 的动作记录写到redo,然后写data到binlog,binlog写成功后,会将binlog的filename,日志写的位置position再写到redo(position也会写到pos文件里),此时才表示该事务完成(committed)。如果只有XID,没有后面的filename和position,则表示事务为prepare状态。


事务提交流程:

     commit; --> write XID to redo. --> write data to Binlog. --> write filename,postsion of binlog to redo. --> commited.

  记录Binlog是在InnoDB引擎Prepare(即Redo Log写入磁盘)之后,这点至关重要。

 


crash发生在不同阶段时的事务状态和事务结果:

总结起来说就是如果一个事务在prepare阶段中落盘成功,并在MySQL Server层中的binlog也写入成功,那这个事务必定commit成功。但二者缺一不可。

不过上面描述还是没有明确,事务还没提交的时候,redolog 能不能被持久化到磁盘?

主要有三种可能的原因:

(1)InnoDB 有一个后台线程,每隔 1 秒轮询一次,具体的操作是这样的:调用 write 将 redolog buffer 中的日志写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。而在事务执行中间过程的redolog 都是直接写在 redolog buffer 中的,也就是说,一个没有提交的事务的 redolog,也是有可能会被后台线程一起持久化到磁盘的

(2)innodb_flush_log_at_trx_commit 设置是 1,也就是每次事务提交时,都执行 fsync 将 redolog 直接持久化到磁盘(设置为0表示每次事务提交的时候,都只是把 redolog 留在 redolog buffer 中;设置为2表示每次事务提交的时候,都只执行 write 将 redolog 写到文件系统的 page cache )。例如,假设事务 A 执行到一半,已经写了一些 redolog 到 redolog buffer 中,这时候有另外一个事务 B 提交,按照 innodb_flush_log_at_trx_commit = 1 的逻辑,事务 B 要把 redolog buffer 里的日志全部持久化到磁盘,这时候,就会带上事务 A 在 redolog buffer 里的日志一起持久化到磁盘;

(3)redolog buffer 占用的空间达到 innodb_log_buffer_size的一半大小时(默认是 8MB),后台线程会主动写盘。不过由于这个事务并没有提交,所以这个写盘动作只是 write 到了文件系统的 page cache,仍然是在内存中,并没有调用 fsync 真正落盘。

1-2 事务提交且当redolog文件满时,是否可以立即覆盖写入

   如果确定需要写redo log文件,这时要看checkpoint。redo log文件是循环写入的,覆盖写之前,总要保证对应的(即将被覆盖的)脏页已经刷到了磁盘。所以如果要覆盖的脏页已经被刷到磁盘,那么久直接覆盖;如果还没刷到磁盘,就需要阻塞等待脏页完成刷到磁盘后再执行覆盖。


二 问题2

   在事务提交之前,重做日志写入了redolog文件;但事务回滚了,那么后续是怎么处理的?

   通过问题1的分析,可以得出结论,问题2中:【在事务提交之前,重做日志写入了redolog文件】是不存在的。至于事务回滚,是利用undo log来恢复/还原数据,当用户在commit之后通过rollback执行回滚时,或异常失败时,undo日志讲数据库“逻辑地”恢复到原来的样子(所有的修改都被逻辑取消,但数据结构和页本身在回滚之后可能大不相同)。我们将在后续文章中进行详细分析,事务的提交和回滚过程。

三 相关资料

   借此问题,再回顾一下redolog的概念和写入机制(资料来自《MySQL技术内幕 InnoDB存储引擎 第2版》):

   事务的执行过程中,生成的 redo log 先写redo log buffer,后根据需要落磁盘(redo log文件);

redo log 三种状态:

  • 存在 redo log buffer 中,物理上是在 MySQL 进程内存中
  • 写到磁盘(write),但是没有持久化(fsync),物理上是在文件系统的 page cache 里
  • 持久化磁盘,对应的是 hard disk

日志写到 redo log buffer 是很快的,write 到 page cache 也差不多,但是持久化到磁盘的速度就慢多了。

InnoDB 提供了 innodb_flush_log_at_trx_commit 参数,取值如下:

  1. 设置为 0 时,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中;
  2. 设置为 1 时,表示每次事务提交时都将 redo log 直接持久化到磁盘;
  3. 设置为 2 时,表示每次事务提交时都只是把 redo log 写到 page cache。

InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。


更详细的相关资料可参考:

MySQL的WAL(Write-Ahead Logging)机制

MySQL · 引擎特性 · InnoDB redo log漫游

MySQL事务提交流程


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
存储 SQL 关系型数据库
binlog,undolog,redolog
binlog,undolog,redolog
43 3
|
5月前
|
存储 缓存 关系型数据库
认真学习MySQL的事务日志-Redo日志
认真学习MySQL的事务日志-Redo日志
44 0
|
5月前
|
缓存 数据库 索引
什么情况下容易发生锁表及如何处理
什么情况下容易发生锁表及如何处理
60 0
|
9月前
|
SQL 存储 关系型数据库
什么是binlog,redolog,两阶段提交
什么是binlog,redolog,两阶段提交
148 0
|
9月前
|
存储 SQL 关系型数据库
【MySQL进阶-10】深入理解redolog,undolog和binlog的底层原理
【MySQL进阶-10】深入理解redolog,undolog和binlog的底层原理
408 0
|
SQL 存储 缓存
【ACID底层实现原理、一致性非锁定读(MVCC的原理)、BufferPool缓存机制、重做日志刷盘策略、隔离级别】
【ACID底层实现原理、一致性非锁定读(MVCC的原理)、BufferPool缓存机制、重做日志刷盘策略、隔离级别】
51495 1
【ACID底层实现原理、一致性非锁定读(MVCC的原理)、BufferPool缓存机制、重做日志刷盘策略、隔离级别】
|
SQL 缓存 关系型数据库
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
MySQL日志(undo log 和 redo log 实现事务的原子性/持久性/一致性)
|
存储 SQL 缓存
跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现
跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现
181 0
跟面试官侃半小时MySQL事务,说完原子性、一致性、持久性的实现
|
存储 关系型数据库 MySQL
【分布式事务】面试官问我:MySQL中的XA事务崩溃了如何恢复??
前段时间搭建了一套MySQL分布式数据库集群,数据库节点有12个,用来测试各种分布式事务方案的性能和优缺点。测试MySQL XA事务时,正当测试脚本向数据库中批量插入数据时,强制服务器断电!注意:是直接拔电源,使其瞬间断电,再次重启服务器后,MySQL数据库报错了。特此记录MySQL XA事务的恢复。
189 0