MySQL作为广泛使用的关系数据库,其事务处理机制中的Redo Log和Undo Log是实现这些目标的关键组件。本文将深入探讨Redo Log和Undo Log的概念、实现原理、数据格式及其在数据库中的重要作用。
一、Redo Log的概念与实现原理
1.1 什么是Redo Log?
Redo Log,也称为重做日志,是MySQL用来记录事务对数据库所做的修改的日志。当事务提交时,Redo Log确保所有已提交的更改可以持久化到数据库中,以应对意外宕机等故障。
1.2 实现原理
Redo Log采用追加写的方式,记录在磁盘上的特定文件中。当一个事务对数据进行修改时,系统会将修改操作记录到Redo Log中。在实际的数据页写入之前,Redo Log会被先写入磁盘。这样,即使在事务提交后,如果发生系统崩溃,MySQL仍然能够使用Redo Log恢复数据到最近的状态。
redo log(重做日志):
redo log 记录的是事务提交时的操作信息。在事务提交时,Redo log 会被写入磁盘,这样即使系统崩溃,重新启动后也能通过 Redo log 恢复到最后一个已提交的状态。
redo log分为两个部分:存储在内存中的重做日志、存储在磁盘上的重做日志。
redo log写入时机:
当一个事务执行并修改了数据,MySQL会将这些修改的日志信息写入redo log,而不是直接修改数据文件
redo log写入磁盘重做文件时机:
(1)redo log buffer的日志占据redo log buffer总容量的一半时,将redo log写入磁盘。
(2)一个事务提交时,redo log都刷入磁盘,这样可以保证数据绝不丢失。
(3)有一个后台线程每过一秒就将redo log写入磁盘。
(4)MySQL关闭时,redo log写入磁盘。
redo log重做过程:
(1)将原始数据读入内存,对加载到内存中的数据进行修改
(2)生成redo log并写入重做日志缓冲区,redo log中存储的是修改后的新值。
(3)事务提交时,将重做日志缓冲区中的内容刷新到重做日志文件。
(4)随后正常将内存中的脏页刷回磁盘。
Force Log at Commit机制:
Force Log at Commit机制实现了事务的持久性。在内存中操作时,日志被写入重做日志缓冲区。但在事务提交之前,必须首先将所有日志写入磁盘上的重做日志文件。
为了确保每个日志都写入重做日志文件,必须使用一个fsync系统调用,确保OS buffer中的日志被完整地写入磁盘上的log file。
innodb_flush_log_at_trx_commit参数控制日志刷新到磁盘的策略。
二、Undo Log的概念与实现原理
2.1 什么是Undo Log?
Undo Log,也称为撤销日志,是用于记录事务对数据所做的修改的“反向操作”的日志。Undo Log的主要目的是在事务回滚时,能够将数据恢复到事务开始之前的状态。
2.2 实现原理
在MySQL中,每当一个事务对数据进行修改时,Undo Log会记录下相应的操作。与Redo Log不同,Undo Log是以链表的形式存储的,每个修改操作都可以找到其对应的撤销操作。当事务需要回滚时,MySQL会遍历Undo Log,将每个操作反向执行,从而恢复数据到之前的状态。
undo log(回滚日志):
undo log就是MySQL内存中一段内存空间,undo log 是存放在FIL_PAGE_UNDO_LOG类型的页中。用于记录事务操作之前的数据状态。
undo log可大致分为两大类:TRX_UNDO_INSERT、TRX_UNDO_UPDATE
undo log是采用行记录格式和数据页结构存储方式。
undo log日志行记录格式包含:DB_TRX_ID(事务id)、DB_ROLL_PTR(回滚指针)、DB_RWO_ID(主键id)、数据行、delete_mask标识。
前面在一个事务中增删改产生的一系列 undo log,都有 undo no 编号的。在回滚的时候,就可以应用这个事务中的 undo log,根据 undo no 从大到小开始进行撤销操作,就将数据还原为原来的样子了。
undo log 默认是存放在系统表空间中的一个特殊段(segment)中,这个段称为回滚段(Rollback Segment),链表中的页面都是从这个回滚段里边申请的。一个 Rollback Segment Header 页面中包含1024个undo slot,128*1024=131072个undo slot,也就是说最多同时支持131072个并发事务执行。