深入浅出 MySQL 物理热备份:XtraBackup 全量、增量备份与恢复全指南及底层原理剖析
1. 为什么选择 XtraBackup (xbk)?
在 MySQL 的备份方案中,mysqldump 属于逻辑备份,虽然通用但恢复速度极慢,且备份期间可能会对数据库性能造成显著影响。
Percona XtraBackup (简称 xbk) 是一款开源的物理热备份工具。它的核心优势在于:
- 物理备份:直接拷贝底层数据文件(
.ibd),恢复速度极快(受限于磁盘 IO)。 - 热备份:在备份 InnoDB 存储引擎的数据时,不会阻塞数据库的读写操作。
🎯 终极目标:本文不仅要教你“怎么敲命令”,更要拆解 xbk “为什么能做到不锁表热备”,以及增量备份背后的“黑魔法”。
2. XtraBackup 核心底层原理 (必读)
在开始动手之前,我们必须先理解 xbk 是如何工作的。xbk 的“热备”能力,完全建立在 InnoDB 的崩溃恢复机制(Crash Recovery) 之上。
2.1 备份时的底层动作:一场与时间的赛跑
当你执行备份命令时,xbk 会做以下几件事:
- 启动 Redo Log 监听线程:xbk 首先会在后台启动一个线程,不断地监视并复制 MySQL 的
redo log(重做日志)。这是热备的灵魂! - 拷贝数据文件:在监听 redo log 的同时,xbk 开始按部就班地拷贝 InnoDB 的数据页(
.ibd文件)。这个过程可能需要几小时(取决于数据量),在此期间,数据库依然在处理写入请求。 - 加短暂的全局锁 (FTWRL 或 Backup Locks):当 InnoDB 数据文件拷贝完成后,xbk 会对数据库加一个极短的锁(MySQL 8.0+ 通常使用轻量级的 Backup Locks,旧版本使用
FLUSH TABLES WITH READ LOCK),用来拷贝非 InnoDB 表(如 MyISAM、系统表)以及获取当前的 Binlog 位点信息。 - 释放锁并停止监听:非事务数据拷贝完成后,立即释放锁,并停止收集 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,核心在于理解以下三句话:
- 热备的本质是“文件物理拷贝 + 拷贝期间的 Redo Log 抓取”。
--prepare的本质是触发 InnoDB 的 Crash Recovery 机制,让杂乱的文件组合成一个时间点一致的数据。- 增备的本质是基于 LSN (Log Sequence Number) 的增量页面抓取;合并增备时,一定要警惕跨越备份边界的事务,善用
--apply-log-only防止误回滚。
浙公网安备 33010602011771号