Mysql——三大日志

Redo log 重做日志

作用:redo log为innodb独有,用于崩溃恢复,保证数据的持久性和完整性。

刷盘时机

  1. 根据innodb_flush_log_at_trx_commit:
    • 0:每次事务提交不进行刷盘
    • 1:每次事务提交都进行刷盘
    • 2:每次事务提交,将log buffer中的redo log写入page cache
  2. 当log buffer中缓存的redo log占其容量约一半时,进行刷盘
  3. 当事务日志缓冲区(transaction log buffer)满时,触发刷盘
  4. innodb定期执行检查点操作,将内存中脏数据刷新到磁盘,并将对应redo log一并刷新
  5. innodb有一个后台线程,周期性地(1秒)将脏页与相关redo log刷新到磁盘
  6. mysql服务器关闭时,会刷新
image-20250312112041112

存储形式

redo log以日志文件组的形式存储在磁盘上,每个日志文件组包含多个日志文件,每个文件大小一样。

采用环形数组形式,从头循环写。

image-20250312112217377
  • write pos:当前记录的位置,一边写一边后移
  • checkpoint:当前要擦出的位置,一边擦一边后移

每次刷盘 redo log 记录到日志文件组中,write pos位置就会后移更新。

每次 MySQL 加载日志文件组恢复数据时,会清空加载过的 redo log 记录,并把 checkpoint后移更新。

如果 write pos追上 checkpoint,表示日志文件组满了,这时候不能再写入新的 redo log 记录,MySQL 得停下来,清空一些记录,把 checkpoint推进一下。

Binlog

作用:

  1. 主从同步和数据备份
  2. 数据恢复,可以通过binlog恢复到任意时间点的数据
  3. 审计与数据分析

记录格式

  1. statement:记录sql语句原文,对于now()、random()等无法保持一致。
  2. row:记录sql语句和操作的具体数据,row格式的记录需要通过mysqlbinlog工具进行解析。row可以保持一致性,但占据空间,影响性能。
  3. mixed:先判断sql语句是否会引起数据不一致,决定用row还是statement。
image-20250312112610370 image-20250312112617451

写入机制

事务执行过程中,binlog写入binlog cache,每个线程都有单独的binlog cache,以保证一个事物的binlog不会被拆开。

当事务提交时,再写入pagecache(write),以及之后刷盘(fsync)。

根据sync_binlog参数:

  • 0:每次提交事务只write,由系统决定何时执行fsync
  • 1:每次提交事务都会fsync
  • N:积累N个事务后再一并fsync

两阶段提交

image-20250312113240348

事务执行期间,更新数据先是写入redo log的prepare阶段;提交事务后,写入binlog,再将redo log的prepare阶段改为commit阶段。

  1. 当写入binlog时发生异常,恢复时由于发现redo log还在prepare阶段且没有对于binlog,因此回滚事务即可。
  2. 当设置commit时发生异常,由于能找到binlog,直接提交事务即可。

Undo log

作用:

  1. 事务回滚,保证原子性
  2. 在MVCC中提供数据的历史版本

undo log属于逻辑日志,对于每一条sql语句,记录其相反的操作。