Redolog 刷盘时机
事务修改数据时,如果 buffer pool 中存在,则更新 buffer pool。同时,会将操作写入 redo log buffer。
刷盘,是将 redo log buffer 的数据写入磁盘,即从 redo log buffer 到 os page cache 到 磁盘 的过程。
redo log 刷盘的时机:
- 事务提交:当事务提交时,log buffer 里的 redo log 会被刷新到磁盘(可以通过
innodb_flush_log_at_trx_commit参数控制,后文会提到)。 - log buffer 空间不足时:log buffer 中缓存的 redo log 已经占满了 log buffer 总容量
innodb_log_buffer_size的大约一半左右,就需要把这些日志刷新到磁盘上。 - 事务日志缓冲区满:InnoDB 使用一个事务日志缓冲区(transaction log buffer)来暂时存储事务的重做日志条目。当缓冲区满时,会触发日志的刷新,将日志写入磁盘。
- Checkpoint(检查点):InnoDB 定期会执行检查点操作,将内存中的脏数据(已修改但尚未写入磁盘的数据)刷新到磁盘,并且会将相应的重做日志一同刷新,以确保数据的一致性。
- 后台刷新线程:InnoDB 启动了一个后台线程,负责周期性(每隔 1 秒)地将脏页(已修改但尚未写入磁盘的数据页)刷新到磁盘,并将相关的重做日志一同刷新。
- 正常关闭服务器:MySQL 关闭的时候,redo log 都会刷入到磁盘里去。
InnoDB 存储引擎提供的 innodb_flush_log_at_trx_commit 参数,支持三种策略:
- 0 :每次事务提交时不进行刷盘操作
- 1 :每次事务提交时都将进行刷盘操作(默认),调用
fsync对 redo log 进行刷盘 - 2 :每次事务提交时都只把
redo log buffer内容写入page cache
刷盘的时机和策略使得 redo log 可能在事务未提交时就存储到磁盘上。
三种策略对应的故障结果:
- 0 :如果
MySQL挂了或宕机可能会有1秒数据的丢失。 - 1 :只要事务提交成功,
redo log记录就一定在硬盘里,不会有任何数据丢失。如果事务执行期间MySQL挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损失。 - 2 :只要事务提交成功,
redo log buffer中的内容只写入文件系统缓存(page cache)。如果仅仅只是MySQL挂了不会有任何数据丢失,但是宕机可能会有1秒数据的丢失。
通常我们说 MySQL 的“双 1”配置,指的就是
sync_binlog和innodb_flush_log_at_trx_commit都设置成 1。也就是说,一个事务完整提交前,需要等待两次刷盘,一次是 redo log(prepare 阶段),一次是 binlog。