深入浅出 MySQL 物理热备份:XtraBackup 全量、增量备份与恢复全指南及底层原理剖析

1. 为什么选择 XtraBackup (xbk)?

在 MySQL 的备份方案中,mysqldump 属于逻辑备份,虽然通用但恢复速度极慢,且备份期间可能会对数据库性能造成显著影响。
Percona XtraBackup (简称 xbk) 是一款开源的物理热备份工具。它的核心优势在于:

  • 物理备份:直接拷贝底层数据文件(.ibd),恢复速度极快(受限于磁盘 IO)。
  • 热备份:在备份 InnoDB 存储引擎的数据时,不会阻塞数据库的读写操作

🎯 终极目标:本文不仅要教你“怎么敲命令”,更要拆解 xbk “为什么能做到不锁表热备”,以及增量备份背后的“黑魔法”。


2. XtraBackup 核心底层原理 (必读)

在开始动手之前,我们必须先理解 xbk 是如何工作的。xbk 的“热备”能力,完全建立在 InnoDB 的崩溃恢复机制(Crash Recovery) 之上。

2.1 备份时的底层动作:一场与时间的赛跑

当你执行备份命令时,xbk 会做以下几件事:

  1. 启动 Redo Log 监听线程:xbk 首先会在后台启动一个线程,不断地监视并复制 MySQL 的 redo log(重做日志)。这是热备的灵魂!
  2. 拷贝数据文件:在监听 redo log 的同时,xbk 开始按部就班地拷贝 InnoDB 的数据页(.ibd 文件)。这个过程可能需要几小时(取决于数据量),在此期间,数据库依然在处理写入请求。
  3. 加短暂的全局锁 (FTWRL 或 Backup Locks):当 InnoDB 数据文件拷贝完成后,xbk 会对数据库加一个极短的锁(MySQL 8.0+ 通常使用轻量级的 Backup Locks,旧版本使用 FLUSH TABLES WITH READ LOCK),用来拷贝非 InnoDB 表(如 MyISAM、系统表)以及获取当前的 Binlog 位点信息。
  4. 释放锁并停止监听:非事务数据拷贝完成后,立即释放锁,并停止收集 redo log。

🚨 此时的备份目录状态:
备份出来的 .ibd 数据文件是不一致的!因为在拷贝文件的前半小时,文件 A 被拷走了,但在后半小时,业务可能又修改了文件 A 的数据。但是,我们手里有一份完整的、涵盖了整个备份期间的 redo log

2.2 恢复前的准备(Prepare):化腐朽为神奇

拿到不一致的数据文件不能直接用,必须经过 prepare(准备)阶段。
prepare 阶段,xbk 会利用 InnoDB 的崩溃恢复机制:

  • 前滚(Apply Redo):把备份期间收集到的 redo log 应用到拷贝出来的数据文件上。
  • 回滚(Undo):把在备份结束时还未提交(Uncommitted)的事务进行回滚。

经过 prepare 之后,备份目录里的数据文件就达到了一个绝对一致的时间点(即备份结束的那一瞬间)。


3. 实验环境准备

  • 数据库:MySQL 5.7 / 8.0
  • 工具:Percona XtraBackup (版本需与 MySQL 匹配,MySQL 8.0 需使用 xbk 8.0 版本)
  • 目录约定:
    • /var/lib/mysql:MySQL 真实数据目录
    • /data/backup/full:全量备份目录
    • /data/backup/inc1:第一次增量备份目录

4. 全量备份与恢复实战

4.1 执行全量备份

xtrabackup --defaults-file=/etc/my.cnf \
           --backup \
           --target-dir=/data/backup/full \
           --user=root --password='YourPassword'

⚙️ 参数解析:

  • --backup:告诉 xbk 当前执行的是备份操作。
  • --target-dir:指定备份文件存放的物理目录。

👀 观察底层文件:
备份完成后,查看 /data/backup/full 目录,你会发现一个重要文件 xtrabackup_checkpoints,内容如下:

backup_type = full-backuped
from_lsn = 0
to_lsn = 12345678    # 备份结束时的 LSN (Log Sequence Number)
last_lsn = 12345680

(LSN 是 InnoDB 内部记录数据修改的一个递增编号,非常重要,后续增量备份全靠它!)

4.2 准备阶段 (Prepare) - 核心逻辑生效

xtrabackup --prepare --target-dir=/data/backup/full

⚙️ 参数解析与原理:

  • --prepare:执行崩溃恢复逻辑。如前文所述,此步骤读取备份目录下的 xtrabackup_logfile,将已提交的事务写入数据文件,回滚未提交的事务。执行完毕后,该目录下的数据就是立即可用的干净数据了。

4.3 恢复阶段 (Restore)

注意: 恢复前必须停止 MySQL 服务,并清空原数据目录!

# 1. 停止 MySQL
systemctl stop mysqld

# 2. 清空原数据目录 (危险操作,请确认路径)
rm -rf /var/lib/mysql/*

# 3. 执行恢复
xtrabackup --copy-back --target-dir=/data/backup/full

# 4. 修改权限 (极其重要,否则 MySQL 起不来)
chown -R mysql:mysql /var/lib/mysql

# 5. 启动 MySQL
systemctl start mysqld

⚙️ 参数解析:

  • --copy-back:xbk 会读取 /etc/my.cnf 中的 datadir 参数,将准备好的备份文件原封不动地物理拷贝回 MySQL 数据目录。

5. 增量备份与恢复实战(高阶原理)

💡 增量备份原理(LSN的接力赛):
InnoDB 的每个数据页都有一个 LSN(日志序列号)。增量备份时,xbk 会去读取上一次备份的 xtrabackup_checkpoints 文件里的 to_lsn。然后,xbk 只拷贝当前数据库中 LSN 大于 to_lsn 的数据页

5.1 执行增量备份

假设业务运行了一段时间,我们基于刚才的全备做一个增量备份:

xtrabackup --defaults-file=/etc/my.cnf \
           --backup \
           --target-dir=/data/backup/inc1 \
           --incremental-basedir=/data/backup/full \
           --user=root --password='YourPassword'

⚙️ 参数解析:

  • --incremental-basedir:指定基准备份的目录。xbk 会去该目录找 LSN 信息。
    打开 /data/backup/inc1/xtrabackup_checkpoints 会看到:
backup_type = incremental
from_lsn = 12345678    # 正好等于全备的 to_lsn
to_lsn = 12349999

5.2 增量备份的 Prepare 阶段 (🌟 最易踩坑的地方)

增量备份的 Prepare 必须按顺序进行,且参数极度讲究!

步骤 A:Prepare 全量备份(仅应用日志,不回滚!)

xtrabackup --prepare --apply-log-only --target-dir=/data/backup/full

🔥 底层原理解析 (--apply-log-only 的作用):

  • 为什么要加 --apply-log-only
    在全量备份结束时,可能有一些事务处于“未提交(Uncommitted)”状态。如果你不加这个参数,xbk 就会把这些事务回滚掉。但是!这些事务很可能在随后的增量备份期间被提交了。如果提前回滚了,这部分数据就永远丢失了。
    加了这个参数,xbk 就只做前滚(应用 Redo),不做回滚,保留那些跨越备份边界的未提交事务。

步骤 B:将增量合并到全量中

xtrabackup --prepare --target-dir=/data/backup/full --incremental-dir=/data/backup/inc1

⚙️ 参数解析与原理:

  • --incremental-dir:将指定的增量备份数据(被修改过的数据页)覆盖到全量目录中,并应用增量备份期间的 redo log。
  • 注意这里没有加 --apply-log-only:因为这是最后一次增量合并,合并完成后,我们需要把所有最终未提交的事务彻底回滚掉,以保证数据的一致性。(如果你还有 inc2, inc3,那么在 inc1 合并时依然要加该参数,只有最后一个增量不需要加)。

5.3 增量恢复阶段

经过上述复杂的 Prepare 之后,所有的增量数据已经全部融合进了 /data/backup/full 目录中。现在的 full 目录就相当于一个包含了最新数据的完整全备。

接下来的恢复步骤与全量恢复一模一样

systemctl stop mysqld
rm -rf /var/lib/mysql/*
xtrabackup --copy-back --target-dir=/data/backup/full  # 注意这里依然指向 full 目录
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

6. 总结与精华提炼

理解 XtraBackup,核心在于理解以下三句话:

  1. 热备的本质是“文件物理拷贝 + 拷贝期间的 Redo Log 抓取”。
  2. --prepare 的本质是触发 InnoDB 的 Crash Recovery 机制,让杂乱的文件组合成一个时间点一致的数据。
  3. 增备的本质是基于 LSN (Log Sequence Number) 的增量页面抓取;合并增备时,一定要警惕跨越备份边界的事务,善用 --apply-log-only 防止误回滚。
posted on 2026-05-10 11:04  LeeHang  阅读(110)  评论(0)    收藏  举报