MySQL 全量备份用 mysqldump
还是 xtrabackup
?
生产环境强烈建议用
Percona XtraBackup做全量备份,
mysqldump仅适合小库或逻辑导出场景。原因很实际:
mysqldump是单线程、锁表(即使加
--single-transaction也依赖事务隔离级别和长事务)、备份大库极慢且影响业务;而
xtrabackup支持物理热备、无锁、增量快照、压缩与流式备份。
实操建议:
确认 MySQL 使用InnoDB引擎(
xtrabackup不支持纯
MyISAM热备) 安装对应版本的
percona-xtrabackup-80(MySQL 8.0 用 80 版本,5.7 用 24 版本) 备份命令示例:
xtrabackup --backup --target-dir=/backup/full_$(date +%F_%H%M%S) --user=backup_user --password=xxx执行前确保
backup_user有
RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT权限
MySQL 差异备份(增量备份)必须基于上一次全量或增量
xtrabackup没有“差异备份”概念,只有“增量备份”,但它实际效果等价于差异:每次只记录从指定
LSN(日志序列号)之后的数据页变更。关键点在于——你不能随便挑一个时间点做“差异”,必须明确指定
--incremental-basedir指向上次全量或上次增量的目录。
常见错误现象:
误把两个不同全量基础的增量合并,恢复时直接报错Log sequence number check failed增量备份后没保留
xtrabackup_checkpoints文件,导致后续无法判断 LSN 起点 用
mysqldump+
binlog模拟“差异”,但没校验
binlog是否开启、格式是否为
ROW、是否跳过 DDL 导致恢复失败
正确做法:
第一次增量:xtrabackup --backup --incremental --target-dir=/backup/inc1 --incremental-basedir=/backup/full_2024-06-01_100000 --user=u --password=p第二次增量(基于第一次增量):
xtrabackup --backup --incremental --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1 --user=u --password=p每次备份后检查
/backup/xxx/xtrabackup_checkpoints中的
to_lsn,它是下一次
--incremental-basedir的依据
恢复时必须按顺序 apply 全量 + 所有增量,且不能跳步
物理备份恢复不是“拷回去就能用”。
xtrabackup的恢复分三步:prepare(合并日志、回滚未提交事务)、copy-back(拷贝到数据目录)、chown 启动。其中
--apply-log-only是关键开关——除最后一次 prepare 外,所有中间步骤都必须加它,否则会把未提交事务前滚,破坏一致性。
典型流程:
准备全量:xtrabackup --prepare --apply-log-only --target-dir=/backup/full_2024-06-01_100000合并第一次增量:
xtrabackup --prepare --apply-log-only --target-dir=/backup/full_2024-06-01_100000 --incremental-dir=/backup/inc1合并第二次增量(最后一次,不加
--apply-log-only):
xtrabackup --prepare --target-dir=/backup/full_2024-06-01_100000 --incremental-dir=/backup/inc2停止 MySQL,清空
datadir,执行:
xtrabackup --copy-back --target-dir=/backup/full_2024-06-01_100000
漏掉
--apply-log-only或顺序颠倒,会导致
mysqld启动失败,报错如
Tablespace is not found或
InnoDB: Trying to access page number ... in space 0。
binlog 是差异备份链条里最容易被忽略的一环
即使你用
xtrabackup做了全量+增量,如果恢复后没重放
binlog,就只能回到最后一次增量的时间点,中间的 DML 全丢。真正的 RPO(恢复点目标)保障靠的是“物理备份 + binlog 流式追平”。
操作要点:
全量备份时记下binlog位置:
mysql -e "SHOW MASTER STATUS\G" > /backup/full_2024-06-01_100000/binlog_pos.txt增量备份也要记录对应
binlog位点(通过
mysqlbinlog --base64-output=decode-rows -v查找最近的
GTID或
position) 恢复完物理备份后,用
mysqlbinlog从全量备份位点开始重放,直到故障前一秒:
mysqlbinlog --skip-gtids --include-gtids='...' /var/lib/mysql-bin.000001 | mysql -u root -p若开启 GTID,优先用
--include-gtids,避免 position 错位;否则必须严格按
binlog文件顺序 + position 追加
没做这一步,所谓“差异备份”只是心理安慰——你根本不知道丢了最后几分钟的数据。
