MySQL日志
MySQL 日志主要包括 Redo Log、Binlog 和 Undo Log,用于保证事务的持久性和一致性。
适用场景:崩溃恢复、数据备份与恢复、主从复制搭建、误操作后数据回滚、性能瓶颈定位。
核心要点
MySQL日志系统,包括Redo Log、Binlog、Undo Log的原理与使用
Redo Log(重做日志)
Redo Log 是 InnoDB 存储引擎独有的,让 MySQL 拥有了崩溃恢复能力。它遵循 WAL(Write-Ahead Logging,预写日志) 机制:先写日志、后改数据页。事务修改数据页前,先把改动写入 redo log 并落盘;数据页本身可以稍后再刷盘。这样即使数据页尚未落盘就发生宕机,重启时也能按 redo log 把已提交事务的修改重放到数据页上,保证提交即持久。
刷盘策略
innodb_flush_log_at_trx_commit 参数控制刷盘行为:
| 值 | 说明 |
|---|---|
| 0 | 每次事务提交时不进行刷盘操作 |
| 1 | 每次事务提交时都进行刷盘操作(默认值) |
| 2 | 每次事务提交时只把 redo log buffer 内容写入 page cache |
默认值为 1,事务提交时会调用 fsync 对 redo log 进行刷盘。另外,InnoDB 后台线程每隔 1 秒会把 redo log buffer 中的内容写到文件系统缓存,然后调用 fsync 刷盘。
日志文件组
硬盘上存储的 redo log 日志文件以日志文件组形式出现,每个文件大小相同,采用环形数组形式,从头开始写,写到末尾又回到头循环写。
Binlog(二进制日志)
MySQL 的数据备份、主备、主主、主从都离不开 binlog,需要依靠 binlog 来同步数据保证数据一致性。binlog 会记录所有涉及更新数据的逻辑操作,并且是顺序写。
三种记录格式
| 格式 | 记录内容 | 优点 | 缺点 |
|---|---|---|---|
| STATEMENT | 记录原始 SQL 语句 | 体积小 | 依赖上下文函数(如 NOW()、UUID())在主从执行结果不一致 |
| ROW | 记录每行数据的前后变化 | 数据准确,主从最安全(MySQL 8.0 默认) | 体积大,批量更新时日志暴涨 |
| MIXED | 两种混合,自动选择 | 兼顾体积与准确 | 逻辑复杂 |
生产环境推荐 ROW 格式:虽然体积大,但保证了主从数据完全一致,也便于误操作时基于 binlog 精确恢复。
两阶段提交(为什么需要)
Redo Log 属于 InnoDB 引擎层、Binlog 属于 MySQL Server 层,写的是两个独立文件。如果先写 redo 后写 binlog,中间崩溃就会出问题:主库按 redo 恢复了已提交事务,但从库只收到尚未写出的 binlog,两边数据不一致。
两阶段提交(Prepare → 写 Binlog → Commit)的作用是对齐两个日志的写入边界:binlog 写入成功,事务才提交;崩溃恢复时,以 binlog 中是否存在该事务的记录作为判定依据——有记录则补提交,没有则回滚。这样主库与从库、数据页与 binlog 永远站在同一条线上。
常用命令
-- 查看 binlog 是否开启
SHOW VARIABLES LIKE '%log_bin%';
-- 获取 binlog 文件列表
SHOW BINARY LOGS;
-- 查看当前写入的 binlog
SHOW MASTER STATUS;数据恢复
# 导出指定时间范围的 binlog
mysqlbinlog --base64-output=DECODE-ROWS \
--start-datetime='2024-01-01 10:00:00' \
--stop-datetime='2024-01-01 11:00:00' \
-v /var/lib/mysql/mysql-bin.000001 > recovery.sql
# 基于位置恢复
mysqlbinlog mysql-bin.000001 \
--start-position=85527 \
--stop-position=87252 | mysql -uroot -pUndo Log(回滚日志)
保证事务原子性的机制。所有事务进行的修改都会先记录到回滚日志中,然后再执行相关操作。如果执行过程中遇到异常,利用回滚日志将数据回滚到修改之前的状态。
回滚日志会先于数据持久化到磁盘上,即使数据库突然宕机,再次启动时也能通过查询回滚日志来回滚未完成的事务。
| 操作类型 | 记录内容 |
|---|---|
| INSERT | 记录插入的主键 |
| DELETE | 记录删除的数据 |
| UPDATE | 记录更新的原始值 |
当事务执行出错时,利用 Undo Log 将数据恢复到事务开始前的状态。