关于事务、redolog 写入的两个问题分析
一 背景
某个讨论群内,有朋友提出这样两个问题:
转文字:
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 状态。
所以,未提交事务修改的数据并不会写 redolog。
事务提交流程:
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 成功。但二者缺一不可。
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 参数,取值如下:
设置为 0 时,表示每次事务提交时都只是把 redo log 留在 redo log buffer 中;
设置为 1 时,表示每次事务提交时都将 redo log 直接持久化到磁盘;
设置为 2 时,表示每次事务提交时都只是把 redo log 写到 page cache。
InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘。
更详细的相关资料可参考:
MySQL的WAL(Write-Ahead Logging)机制
MySQL · 引擎特性 · InnoDB redo log漫游
版权声明: 本文为 InfoQ 作者【程序员架构进阶】的原创文章。
原文链接:【http://xie.infoq.cn/article/a0524f9df0d1b9fff8b0af42f】。文章转载请联系作者。
评论