【在 csview 上这条八股题目被命名为 “MySQL 三种日志?”,但 DeepSeek 给出的答案我个人认为更加完整,csview 中总结的 undo log、redo log 和 bin log 应该被称为 MySQL 的三个核心日志,此外还有error log、slow query log 和 general query log 等辅助日志】
首先总结三种核心日志。
作用:记录所有修改数据库的 SQL 语句(逻辑日志),用于主从复制和数据恢复。
特点:属于 MySQL Server 层的日志,与存储引擎无关。
作用:确保事务的持久性,主要用于掉电等故障恢复。记录物理页的修改,用于崩溃恢复时重放未持久化到磁盘的操作。
特点:属于 InnoDB 引擎层日志,采用循环写入模式。
作用:提供事务回滚能力(原子性)。支持 MVCC(多版本并发控制),实现非锁定读。
特点:属于 InnoDB 引擎层日志,记录事务前的数据旧版本。事务提交后不会立即删除,可能被其他事务的 MVCC 读取依赖。
Binlog 用于数据恢复与数据复制;Redo Log 保障崩溃恢复(比如掉电恢复);Undo Log 用于事务回滚与 MVCC。
redo log 记录的是此次事务完成后的数据状态,undo log 记录的是此次事务开始前的数据状态。
对于读提交和可重复读隔离级别,快照读是通过 Read View + undo log 来实现的。这两种隔离级别下快照读的主要区别是建立 Read View 的时机不同:
通过对比事务的 Read View 当中字段和记录的隐藏列 trix_id 和 roll_pointer,如果不满足版本可见行,就会顺着 undo log 版本链找到满足可见性的记录,从而控制并发事务访问同一个记录时的行为。
早期版本的 MySQL 以 MyISAM 作为默认的数据引擎,它没有 crash-safe 的能力,binlog 日志仅用于归档。InnoDB 数据引擎可以通过 redo-log 实现 crash-safe 能力。
基于 redo log 和 WAL 技术,InnoDB 可以保证即使数据库异常重启,之前已经提交的数据也不会丢失。
WAL 指的是,MySQL 的写操作不是立刻写到磁盘上,而是先写日志,然后在合适的时间写到磁盘。
需要。开启事务后,InnoDB 更新记录前,首先要记录相应的 undo log,如果是更新操作,也就是要生成一条 undo log,undo log 会写入 Buffer Pool 中的 Undo 页面。在内存修改该 Undo 页面后,需要记录对应的 redo log。
分别是 STATEMENT(默认格式)、ROW、MIXED;
如果 redo log 是完整的(commit 状态),那么直接使用 redo log 恢复;
如果 redo log 是预提交 prepare 而不是 commit 状态,此时要去判断 binlog 是否完整,完整就提交 redo log,再用 redo log 恢复,不完整就回滚事务。
不是。直接写入磁盘会产生大量 I/O,redo log 会先写入 redo log buffer,每当产生一条 redo log,先写入 buffer,后续再持久化到磁盘。
以上是 csview 整理的答案,而根据 DeepSeek 给出的回答,实际上 redo log 是否直接落盘取决于 MySQL 的配置策略,由参数innodb_flush_log_at_trx_commit
控制。
innodb_flush_log_at_trx_commit = 1
时,每次事务提交,log buffer 中的 redo log 都会立即直接写入操作系统缓存并调用fsync
刷盘,确保事务提交后数据不丢失,但会降低吞吐量;innodb_flush_log_at_trx_commit = 0
时,log buffer 每秒写入 OS 缓存并刷盘一次,事务提交时不主动触发写盘。风险是最多都是 1 秒的事务数据;innodb_flush_log_at_trx_commit = 2
时,事务提交时 log buffer 写入 OS 缓存,但每秒调用 fsync
落盘一次。风险是 OS 崩溃时丢失 1 秒数据,硬件故障也可能丢失。redo log 的写方式使用了追加,日志操作是顺序写,磁盘操作是随机写,MySQL 的写操作从磁盘的随机写变成了顺序写,提升语句的执行性能。
由 ib_logfile0
、ib_logfile1
等文件组成(默认2个,可配置)。每个文件大小固定(如48MB),以循环写入(Circular Buffer)方式复用。
日志块(Log Block):每个块512字节(与磁盘扇区对齐);
日志记录(Log Record):每个事务的修改操作记录。包含表空间ID、页号、修改内容等元数据。
全局递增的唯一序列号,标记日志写入位置,用于崩溃恢复时定位数据一致性点。
修改操作先写入内存中的 redo log buffer,根据 innodb_flush_log_at_trx_commit
(0 / 1 / 2)配置决定刷盘策略。
将 redo log buffer 中的日志按 LSN 顺序写入文件。写入时追加到当前活跃的日志文件(如ib_logfile0)。若文件写满,切换到下一个文件(循环覆盖旧日志)