MySQL三大日志详解
大约 4 分钟
MySQL三大日志详解
前言
MySQL 的日志机制是保障数据安全、优化性能的核心部分。主要包含以下三种日志:
- redo log:用于恢复已提交的事务,保证事务的持久性。
- binlog:记录数据库的更改操作,支持数据恢复和主从复制。
- undo log:用于事务回滚和多版本并发控制(MVCC)。
1. redo log(重做日志)
1.1 什么是 redo log?
- redo log 是 MySQL 的 InnoDB 存储引擎的日志,记录数据修改的物理操作,用于恢复事务。
- 作用:
- 保证事务的 持久性(Durability,ACID)。
- 即使数据库发生宕机,提交的事务也能通过 redo log 恢复。
1.2 刷盘时机
InnoDB 的数据写入是 “先写日志,再写数据”(WAL:Write Ahead Logging),redo log 提供了较快的刷盘效率。
刷盘的三个时机:
- 事务提交时:
- 日志写入磁盘,但数据可能仍在缓冲区。
- 缓冲池(Buffer Pool)满时:
- 将缓冲区的脏页(已修改但未刷盘的页)写入磁盘。
- 后台线程定期刷新:
- 默认每秒刷新一次(通过
innodb_flush_log_at_timeout参数配置)。
- 默认每秒刷新一次(通过
1.3 redo log 文件组
- redo log 由多个日志文件组成,组成一个 循环写日志文件组。
- 示例:
innodb_log_file_size = 512M -- 单个日志文件大小 innodb_log_files_in_group = 2 -- 日志文件组数量 - 日志文件写满后,循环覆盖旧日志。
1.4 redo log 小结
- redo log 是 物理日志,记录数据页的物理修改。
- 场景:
- 事务已提交但数据尚未持久化时,通过 redo log 恢复数据。
- 系统崩溃后,重放 redo log 以保证数据完整性。
2. binlog(二进制日志)
2.1 什么是 binlog?
- binlog 是 MySQL 的 逻辑日志,记录 SQL 语句或数据的更改操作。
- 作用:
- 数据恢复:通过重放 binlog 恢复数据。
- 主从复制:将 binlog 发送到从库,实现数据同步。
2.2 记录格式
binlog 有三种记录格式,分别适应不同场景。
| 格式 | 特点 |
|---|---|
| STATEMENT | 记录 SQL 语句,体积小,但可能引发非幂等问题(如 NOW())。 |
| ROW | 记录行数据的变化,体积大,但最可靠(无幂等问题)。 |
| MIXED | 结合 STATEMENT 和 ROW,按需选择最优记录格式。 |
- 推荐使用:ROW 格式,适合大多数场景。
2.3 写入机制
- 先写内存缓冲区,再定期写入磁盘。
- 刷盘时机:
- 事务提交时将 binlog 写入磁盘(由
sync_binlog参数控制)。 - 主从复制时实时传递 binlog。
- 事务提交时将 binlog 写入磁盘(由
2.4 两阶段提交
两阶段提交用于协调 redo log 和 binlog 的写入顺序,避免数据不一致。
过程:
- 预提交:先写 redo log 的 prepare 状态。
- 写 binlog:将事务的变更操作写入 binlog。
- 提交:将 redo log 的状态标记为 commit。
- 作用:
- 如果发生宕机,数据库可以通过 redo log 和 binlog 协同恢复数据。
3. undo log
3.1 什么是 undo log?
- undo log 是 MySQL 的 逻辑日志,记录数据被修改前的旧值。
- 作用:
- 事务回滚:未提交的事务可以通过 undo log 恢复到修改前的状态。
- MVCC:多版本并发控制,支持事务隔离级别(如
REPEATABLE READ)。
3.2 undo log 的类型
- 插入 undo log:
- 用于回滚
INSERT操作。 - 事务提交后可立即删除。
- 用于回滚
- 更新 undo log:
- 用于回滚
UPDATE或DELETE操作。 - 提交后可能被 MVCC 用于快照读。
- 用于回滚
4. redo log 与 binlog 的对比
| 特性 | redo log | binlog |
|---|---|---|
| 层级 | InnoDB 引擎内部 | MySQL Server 层 |
| 记录方式 | 物理日志,记录数据页的修改 | 逻辑日志,记录 SQL 或行级变更 |
| 作用 | 用于崩溃恢复 | 数据恢复、主从复制 |
| 刷盘时机 | 事务提交时 | 配置由 sync_binlog 控制 |
| 文件存储机制 | 循环写 | 追加写 |
| 存储位置 | redo log 文件组 | binlog 文件 |
5. 正确使用日志的建议
5.1 配置 redo log 刷盘频率
- 默认每秒刷盘一次(
innodb_flush_log_at_trx_commit = 1)。 - 如果追求性能,可以配置为每秒刷盘一次(
innodb_flush_log_at_trx_commit = 2),但可能会丢失事务。
5.2 配置 binlog 的刷盘频率
- 默认事务提交时同步写入磁盘(
sync_binlog = 1)。 - 如果追求性能,可设置为异步写入(
sync_binlog = 0),但可能会丢失 binlog。
5.3 定期清理 binlog
- binlog 默认会一直存储,需要定期清理。
- 配置自动清理:
SET GLOBAL expire_logs_days = 7; -- 自动清理 7 天前的 binlog
6. 总结
redo log(重做日志):
- 保证事务的持久性,即使宕机也能恢复已提交的事务。
- 在事务提交时写入磁盘。
binlog(二进制日志):
- 用于数据恢复和主从复制。
- 记录逻辑 SQL 或行数据变更。
undo log(回滚日志):
- 用于事务回滚和 MVCC。
- 记录修改前的数据版本。
两阶段提交:
- redo log 和 binlog 协同工作,保证数据一致性。
