Redo Log详解
Redo Log,即重做日志,是MySQL InnoDB存储引擎中用于保证数据持久性和一致性的一种重要机制。它基于WAL(Write-Ahead Logging)预写式日志技术,通过先写日志再更新数据的方式,提高了数据写入的性能和安全性。
一、Redo Log的基本概念
Redo Log包括两部分:内存中的日志缓冲(redo log buffer)和磁盘上的日志文件(redo log file)。当MySQL执行DML语句(如INSERT、UPDATE、DELETE)时,会先将这些操作的记录写入redo log buffer。随后,在某个时间点,这些记录会被一次性写入到redo log file中。当系统发生故障导致内存数据丢失时,InnoDB可以在重启时通过重放redo log,将数据库恢复到崩溃前的状态,从而实现事务的持久性。
二、Redo Log数据落盘流程
脏页落盘机制:
脏页是指修改了Buffer Pool中的数据页后,导致内存中的数据页和磁盘中的数据页不一致。
当进行数据页的修改操作时,首先修改缓冲池中的页,然后再以一定的频率刷新到磁盘上。
页从缓冲池刷新回磁盘的操作并不是在每次页发生更新时触发,而是通过Checkpoint机制来实现。
Checkpoint机制:
Checkpoint技术主要用于缩短数据库的恢复时间、在缓冲池不够用时刷新脏页到磁盘,以及在重做日志不可用时刷新脏页。
通过Checkpoint,InnoDB可以定期将内存中的脏页刷新到磁盘上,从而确保在发生故障时,可以通过重做日志和磁盘上的数据页快速恢复数据库。
三、Redo Log持久化
- 缓冲区数据一般情况下无法直接写入磁盘,中间必须经过操作系统缓冲区(OS Buffer)。
- 因此,redo log buffer写入redo log file实际上是先写入OS Cache,然后再通过系统调用fsync()将其刷到redo log file。
- InnoDB_flush_log_at_trx_commit参数可以控制redo log的持久化策略。一般建议选择取值2,因为MySQL挂了数据没有损失,整个服务器挂了才会损失1秒的事务提交数据。
四、Redo Log日志格式
- Redo log属于物理日志,记录的是事务对数据库做了哪些修改,而不是数据变化的过程或SQL语句的逻辑。
- 物理日志记录的是每一个page页中具体存储的值是多少,以及在这个数据页上做了什么修改。
五、Redo Log写入机制
- redo log buffer是用来缓存写入到redo log文件中的数据内容的。
- 并不是每次redo log buffer产生内容就立即写入到磁盘进行持久化。因为即使事务执行期间MySQL宕机了,redo log缓冲区中的内容丢失了也不会有损失(因为事务并没有提交)。
- redo log有三种状态:存在于redo log buffer内存区域中、向磁盘写入但保存在文件系统缓存中、持久化到磁盘。
- 触发真正的fsync写盘的场景包括:redo log buffer占用的空间即将达到innodb_log_buffer_size一半时,后台线程会主动写盘;并行的事务提交时,顺带将某个未提交的事务的redo log buffer写盘。
六、组提交与日志文件循环写入
- MySQL为了优化磁盘持久化的开销,会有一个组提交(group commit)的机制。每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组下至少有两个重做日志文件。
- InnoDB以环型方式(circular fashion)写入数据到重做日志文件。当文件满了的时候,会自动切换到下一个日志文件。当所有日志文件都写满时,会再从头开始循环写入。
- write pos表示日志当前记录的位置。当某个日志文件写满后,会从下一个日志文件从头开始记录。
- checkpoint表示将日志记录的修改写进磁盘,完成数据落盘。数据落盘后,checkpoint会将日志上的相关记录擦除掉。因此,write pos到checkpoint之间的部分是redo log空着的部分,用于记录新的记录;checkpoint到write pos之间是redo log待落盘的数据修改记录。
七、总结
Redo Log是MySQL InnoDB存储引擎中用于保证数据持久性和一致性的一种重要机制。它通过将事务的修改记录先写入日志再更新数据的方式,提高了数据写入的性能和安全性。同时,通过Checkpoint机制、持久化策略、组提交以及日志文件循环写入等机制,确保了数据的可靠性和系统的稳定性。