讲解

MySQL 有几类日志各司其职:错误日志记录启动关闭和异常;慢查询日志记录慢 SQL(前面学过);二进制日志 binlog 记录所有对数据的变更(DDL 和 DML),它有两个使命——主从复制的数据源、时间点恢复的素材。InnoDB 内部还有 redo log(崩溃恢复)和 undo log(事务回滚与 MVCC),属于引擎内部机制,日常管理不直接操作。

binlog 有三种格式:STATEMENT 记 SQL 原文(有不确定性函数时主从不一致的风险)、ROW 记每一行的变化(默认、最可靠、体积大)、MIXED 混合。保留时长由 binlog_expire_logs_seconds 控制(默认 30 天)。FLUSH BINARY LOGS 切换到一个新的 binlog 文件,SHOW MASTER STATUS 看当前写到哪个文件、什么位置,SHOW BINLOG EVENTS 可以翻看日志里的事件。

时间点恢复(PITR)解决的是这类事故:昨晚 2 点做了全量备份,今天下午 3 点有人误删了表。恢复流程是:① 恢复昨晚的全量备份;② 用 mysqlbinlog 工具把备份之后到误删之前这段时间的 binlog 导出成 SQL(--start-datetime/--stop-position 划定区间);③ 重放这段 SQL。这样数据回到误删前一秒,比「只能回到昨晚」少损失近一天的数据。这也是主从复制的底层原理,后面的复制章节会再见到 binlog。

示例

查看 binlog 的当前状态:写到哪个文件、格式、保留策略:

SHOW MASTER STATUS;

SHOW BINARY LOGS;

SHOW VARIABLES LIKE 'binlog_format';

SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

制造一些变更,然后用 FLUSH BINARY LOGS 切换到新文件(模拟「备份后产生的增量」落进了新的 binlog):

CREATE TABLE recovery_demo (id INT PRIMARY KEY, note VARCHAR(50));

INSERT INTO recovery_demo VALUES (1, '全量备份时已有的数据'), (2, '备份之后新增的数据');

FLUSH BINARY LOGS;

SHOW MASTER STATUS;

时间点恢复的关键一步:用 mysqlbinlog 把指定时间段的 binlog 导出成 SQL 再重放(服务器端工具,示意流程):

# 仅示意:mysqlbinlog 需直接读取 binlog 文件,本验证容器的镜像未包含该工具
# 导出 14:00 到误操作前(14:30)之间的所有变更
mysqlbinlog --start-datetime="2026-08-10 14:00:00" \
            --stop-datetime="2026-08-10 14:30:00" \
            /var/lib/mysql/binlog.000003 > /tmp/recover.sql

# 在恢复出的全量备份之上重放增量
mysql -uroot -p shop < /tmp/recover.sql

不用任何工具,也可以直接翻看 binlog 里记录的事件类型:

SHOW BINLOG EVENTS LIMIT 5;

常见坑

  • 根本没开 binlog:8.0 默认开启(log_bin=ON),但老版本或某些精简配置默认关闭。出了事才发现没 binlog,PITR 无从谈起。部署时第一件事确认 log_bin。
  • binlog 和数据同盘:磁盘损坏时数据文件和 binlog 一起没了。重要系统把 binlog 目录放到独立磁盘。
  • 保留期设太短:binlog_expire_logs_seconds 设成一天,遇到「上周的数据想找回」就没素材了。保留期要覆盖备份周期。
  • 恢复时业务还在写:PITR 重放期间没有暂停写入,新旧数据交叉污染。恢复操作必须先停业务或切流量。

小结

binlog 记录全部变更,是复制与时间点恢复的基础:全量备份 + mysqlbinlog 截取重放 = 恢复到任意时间点;ROW 格式默认且最可靠,保留期要覆盖备份周期。下一章换个话题:数据的批量导入导出。