mysql中的全量备份与差异备份的操作方式

1次阅读

生产环境全量备份应选Percona XtraBackup而非mysqldump,因其支持物理热备、无锁、增量快照;而mysqldump单线程锁表,仅适合小库或逻辑导出。

mysql中的全量备份与差异备份的操作方式

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_userRELOAD, 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 foundInnoDB: Trying to access page number ... in space 0

binlog 是差异备份链条里最容易被忽略的一环

即使你用 xtrabackup 做了全量+增量,如果恢复后没重放 binlog,就只能回到最后一次增量的时间点,中间的 DML 全丢。真正的 RPO(恢复点目标)保障靠的是“物理备份 + binlog 流式追平”。

操作要点:

  • 全量备份时记下 binlog 位置:
    mysql -e "SHOW MASTER STATUSG" > /backup/full_2024-06-01_100000/binlog_pos.txt
  • 增量备份也要记录对应 binlog 位点(通过 mysqlbinlog --base64-output=decode-rows -v 查找最近的 GTIDposition
  • 恢复完物理备份后,用 mysqlbinlog 从全量备份位点开始重放,直到故障前一秒:
    mysqlbinlog --skip-gtids --include-gtids='...' /var/lib/mysql-bin.000001 | mysql -u root -p
  • 若开启 GTID,优先用 --include-gtids,避免 position 错位;否则必须严格按 binlog 文件顺序 + position 追加

没做这一步,所谓“差异备份”只是心理安慰——你根本不知道丢了最后几分钟的数据。

text=ZqhQzanResources