
MySQL PITR 恢复必须依赖二进制日志(binlog)
没有开启 binlog,就不可能做基于时间点的恢复。不是“不推荐”,是根本做不到。检查是否启用:
SHOW VARIABLES LIKE 'log_bin';返回
ON 才能继续。同时确认 binlog_format 是 ROW 或 MIXED——STATEMENT 在某些函数(如 NOW()、UUID())下会导致主从不一致,也影响时间点定位精度。
如何找到目标时间点对应的 binlog 文件和位置
不能靠猜,也不能只看系统时间。实际恢复时,你要定位的是「事件写入 binlog 的精确位置」,而不是「你执行 SQL 的那一刻」。常用方法:
- 用
mysqlbinlog --base64-output=DECODE-ROWS -v解析最近的binlog文件,搜索### UPDATE或### DELETE前的关键操作(比如误删表前的DROP TABLE) - 用
mysqlbinlog --start-datetime="2024-05-20 14:23:00" --stop-datetime="2024-05-20 14:23:30"截取可疑时间段,再人工确认边界 - 如果启用了
log_slave_updates且有从库,可先在从库上用SHOW SLAVE STATUS\G查Exec_Master_Log_Pos和Relay_Master_Log_File辅助定位
用 mysqlbinlog 恢复时最常踩的三个坑
即使 binlog 存在、时间也找对了,恢复仍可能失败或跳过关键事件:
- 没加
--database=your_db参数,导致跨库语句混入,误恢复其他库的数据 - 用
mysqlbinlog | mysql直接管道恢复时,遇到SET @@SESSION.GTID_NEXT报错:说明开启了 GTID,必须改用--skip-gtids或先SET SESSION GTID_NEXT='AUTOMATIC' - 恢复过程中 MySQL 服务重启过,
binlog文件名序号变化(如从mysql-bin.000012跳到mysql-bin.000014),漏掉中间文件就会丢数据
完整 PITR 流程中不可跳过的验证环节
从全量备份 + binlog 恢复完,不代表数据就对了。尤其要注意:
- 全量备份时间点必须早于目标恢复时间点,否则中间有 gap
- 恢复后立刻查
SELECT COUNT(*) FROM table_name和SELECT MIN(id), MAX(id) FROM table_name,比对误操作前的记录范围 - 如果业务依赖自增主键,检查
SHOW CREATE TABLE中的AUTO_INCREMENT值是否被意外重置(常见于INSERT ... SELECT后未显式设置) - 不要在生产库直接恢复;务必先在隔离环境(同版本、同参数)跑通整套流程
真正难的不是命令怎么写,而是搞清「哪条 binlog 事件对应哪次业务动作」,以及「哪些事件该跳过、哪些必须保留」。线上出问题时,日志里混着 DDL、DML、事务拆分、XA 信息,靠时间戳硬切很容易切歪。










