全量备份必须使用--single-transaction(innodb)或--lock-all-tables(myisam)保证一致性,推荐命令:mysqldump --all-databases --master-data=2 --single-transaction --routines --triggers;备份文件需存于独立路径并记录对应binlog位置,严禁与binlog共存同一磁盘。

全量备份怎么选时间点和存储方式
滚动恢复的前提是有一份可靠的全量备份,它必须带 --single-transaction(InnoDB)或 --lock-all-tables(MyISAM),否则备份期间写入会导致数据不一致。别用 mysqldump 默认参数直接跑,它不保证一致性。
- 全量备份建议用
mysqldump --all-databases --master-data=2 --single-transaction --routines --triggers,--master-data=2会把备份时刻的 binlog 文件名和位置写进 dump 文件注释里,这是后续增量衔接的关键 - 备份文件必须保存在独立路径,比如
/backup/full_20240510.sql,不能覆盖旧备份;同时要记录对应binlog位置,例如CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=198765 - 别把全量备份和 binlog 放在同一块磁盘上——万一磁盘故障,两者一起丢,滚动恢复就断链了
增量日志怎么提取和校验
增量靠 binlog,但不是所有 binlog 都能直接用。MySQL 5.7+ 默认开启 binlog_format=ROW,这是安全前提;如果还是 STATEMENT,某些函数(如 NOW()、UUID())会导致主从不一致,滚动恢复后数据可能错位。
- 用
mysqlbinlog --base64-output=DECODE-ROWS --verbose查看 binlog 内容是否可读,确认没有Unknown error code或乱码 - 提取指定时间段的增量:先查出全量备份对应的
binlog文件和 position,再用mysqlbinlog --start-position=198765 --stop-datetime="2024-05-11 14:30:00" mysql-bin.000012 mysql-bin.000013 > incremental.sql - 增量文件必须做语法校验:
mysql --no-defaults -e "source /backup/incremental.sql" 2>/dev/null || echo "SQL syntax error detected",避免导入时报错中断
恢复时怎么控制顺序和冲突
滚动恢复不是简单地按时间顺序倒数据。全量恢复后,必须先关闭 binlog 写入(SET SQL_LOG_BIN=0),否则增量里的 DML 会被再次记录进当前 binlog,造成循环写入或主键冲突。
- 全量导入后执行
SET SQL_LOG_BIN=0;,再 source 增量 SQL;完成后记得SET SQL_LOG_BIN=1; - 如果增量里包含
DROP TABLE或TRUNCATE,而全量备份里该表已存在,会报错ERROR 1051 (42S02)—— 这类语句得人工过滤或加IF EXISTS修饰 - 跨多个 binlog 文件恢复时,确保
--stop-position和下一个文件的--start-position严格衔接,差 1 字节都可能跳过一条事务,用mysqlbinlog --base64-output=DECODE-ROWS -v对比相邻文件末尾和开头的end_log_pos值
如何验证滚动恢复是否真正可用
恢复完不代表数据可用。很多团队只检查 mysql 进程是否起来、库是否存在,结果发现某张表少了几万行,或者时间戳全变成 0000-00-00。
- 用
SELECT COUNT(*) FROM table_name对比备份前后的行数,对关键表做CHECKSUM TABLE(注意大表会锁表) - 查
SHOW MASTER STATUS确认当前 binlog 位置已更新,且Executed_Gtid_Set(如果启用 GTID)与预期一致 - 最易被忽略的是字符集:全量备份里如果没显式指定
--default-character-set=utf8mb4,而目标库是utf8mb4,中文可能变成问号——恢复后立刻查几个含中文字段的记录











