xtrabackup 准备与恢复
导学
xtrabackup 备份出来的文件不是"立即可用"的状态——备份过程中数据文件可能正在被修改,redo log 记录了这些变更。prepare(准备)阶段就是模拟 InnoDB 崩溃恢复,将备份文件变为一致性状态。之后才能 copy-back 到 MySQL 数据目录启动。
定义
Prepare(准备):对 xtrabackup 备份文件应用 redo log,使数据文件恢复到备份结束时的一致状态。类似于 InnoDB 启动时的自动崩溃恢复。Copy-back(复制回):将准备完毕的备份文件复制到 MySQL 数据目录,替代原有文件。Move-back(移回):与 copy-back 类似,但使用移动而非复制,速度更快但会删除备份文件。
场景一:全备的 prepare
前置条件:已完成全量备份 /backup/full_backup。
ls /backup/full_backup/
# 包含 ibdata1、.ibd 文件、xtrabackup_logfile 等
操作语句:
xtrabackup --prepare --target-dir=/backup/full_backup
输出关键片段:
240115 02:10:00 Starting to apply log...
240115 02:10:01 xtrabackup: starting shutdown with innodb_fast_shutdown = 1
240115 02:10:02 InnoDB: Shutdown completed; log sequence number 12345678
240115 02:10:02 completed OK!
验证准备后的目录:
ls -la /backup/full_backup/
预期变化:
xtrabackup_logfile被应用后可能变小或消失- 新增
xtrabackup_binlog_info(记录 binlog 位置) ib_logfile0、ib_logfile1被重建为正常大小
结果解读:
--prepare读取xtrabackup_logfile中的 redo log,将其应用到数据文件- 同时回滚未提交的事务(如果这是最终恢复点)
- 准备后的备份目录相当于 InnoDB 正常关闭后的数据目录,可以直接复制到 MySQL 数据目录启动
- 注意:prepare 后的备份目录不能再用于增量备份的 base(因为 LSN 已推进)。如需保留原始备份,应先复制一份再 prepare。
场景二:全备 + 增量的 prepare
备份链:
/backup/sunday_full/ # 全备
/backup/monday_incr/ # 增量 1
/backup/tuesday_incr/ # 增量 2
操作语句:
# 步骤 1:prepare 全备(加 --redo-only,保留未提交事务,以便后续增量合并)
xtrabackup --prepare --apply-log-only --target-dir=/backup/sunday_full
# 步骤 2:合并周一增量到全备
xtrabackup --prepare --apply-log-only \
--target-dir=/backup/sunday_full \
--incremental-dir=/backup/monday_incr
# 步骤 3:合并周二增量到全备(最后一个增量不加 --apply-log-only)
xtrabackup --prepare \
--target-dir=/backup/sunday_full \
--incremental-dir=/backup/tuesday_incr
验证合并后的全备目录:
cat /backup/sunday_full/xtrabackup_checkpoints
预期 to_lsn 已推进到周二增量的结束 LSN:
backup_type = full-prepared
from_lsn = 0
to_lsn = 12347000
结果解读:
--apply-log-only只应用 redo log,不回滚未提交事务。这是增量合并的中间步骤必须加的参数- 最后一个增量合并时不加
--apply-log-only,让 InnoDB 正常回滚未提交事务,完成崩溃恢复 - 合并后
/backup/sunday_full已包含所有增量数据,成为一个完整的全备 - 增量备份目录(
monday_incr、tuesday_incr)在合并后不再需要使用
场景三:copy-back 恢复
前置条件:
- MySQL 已停止(
systemctl stop mysqld) - 原数据目录已清空或备份(
mv /var/lib/mysql /var/lib/mysql_old) - 新数据目录已创建并设置正确权限(
mkdir /var/lib/mysql && chown mysql:mysql /var/lib/mysql)
操作语句:
# 将准备完毕的备份复制到数据目录
xtrabackup --copy-back --target-dir=/backup/sunday_full
# 设置权限(xtrabackup 复制后文件属主是 root)
chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL
systemctl start mysqld
验证恢复:
mysql -u root -p -e "USE company; SELECT emp_name FROM employees;"
预期输出:
+----------+
| emp_name |
+----------+
| 大翔 |
| 白歌 |
| 孔蓝 |
+----------+
结果解读:
--copy-back将备份目录中的所有文件复制到my.cnf中datadir指定的目录- 复制后必须
chown mysql:mysql,否则 MySQL 无法读写数据文件 - 启动后数据应恢复到备份时的状态
- 如需恢复到备份后的某个时间点,还需配合 binlog 做 point-in-time 恢复
场景四:move-back(快速恢复)
操作语句:
# 停止 MySQL
systemctl stop mysqld
# 清空数据目录
rm -rf /var/lib/mysql/*
# 直接移动备份文件到数据目录(比 copy 快,但会删除备份)
xtrabackup --move-back --target-dir=/backup/sunday_full
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld
结果解读:
--move-back用mv而非cp,大库恢复时速度明显更快- 代价:备份目录被清空,无法再次用于恢复
- 适合紧急恢复场景,或备份目录和数据目录在同一文件系统时(
mv只是改 inode,瞬间完成)
场景五:恢复到新实例(克隆)
操作语句:将备份恢复到另一台服务器,用于搭建从库或测试环境。
# 在目标服务器上
# 1. 安装相同版本 MySQL
# 2. 停止 MySQL
systemctl stop mysqld
# 3. 清空数据目录
rm -rf /var/lib/mysql/*
# 4. 从备份服务器 scp 备份目录(已 prepare 完毕)
scp -r backup_server:/backup/sunday_full /tmp/
# 5. copy-back
xtrabackup --copy-back --target-dir=/tmp/sunday_full
chown -R mysql:mysql /var/lib/mysql
# 6. 启动
systemctl start mysqld
# 7. 查看 binlog 位置(用于搭建从库)
cat /var/lib/mysql/xtrabackup_binlog_info
预期输出:
mysql-bin.000015 1234
结果解读:
- 克隆后的实例数据与备份时完全一致
xtrabackup_binlog_info记录了备份时的 binlog 文件名和位置- 如需搭建从库,执行
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000015', MASTER_LOG_POS=1234;
常见误区
| 误区 | 正解 |
|---|---|
| "备份完直接 copy-back 就行" | 不行。必须先 prepare,否则数据文件不一致,MySQL 启动时会崩溃恢复失败或数据损坏。 |
| "prepare 可以多次执行" | 可以,但第一次 prepare 后备份就不能再作为增量 base。多次 prepare 无意义,且可能损坏备份。 |
| "copy-back 会覆盖现有数据目录" | 会。如果数据目录不为空,xtrabackup 会报错。必须先清空或移走原有数据。 |
| "恢复后不需要改权限" | 必须改。xtrabackup 以 root 运行,copy-back 后的文件属主是 root,MySQL 无法启动。 |
面试考点
Q:xtrabackup 恢复的完整流程?
- 停止 MySQL;2. 清空数据目录;3.
xtrabackup --prepare --target-dir=/backup(全备)或先合并增量再 prepare;4.xtrabackup --copy-back --target-dir=/backup;5.chown -R mysql:mysql /var/lib/mysql;6. 启动 MySQL。
Q:--apply-log-only 什么时候用?
增量备份合并的中间步骤必须用。它只应用 redo log 而不回滚未提交事务,保留事务状态以便下一个增量继续合并。最后一个增量合并时不加,让 InnoDB 正常回滚未提交事务。
Q:prepare 后的备份还能再做增量吗?
不能。prepare 会推进 LSN 并回滚事务,备份状态已改变。如需保留增量能力,应先复制一份备份再 prepare。
小结
- 备份后必须经过
prepare才能恢复,prepare应用 redo log 使数据一致 - 全备直接
prepare;全备 + 增量时,前几次加--apply-log-only,最后一次不加 copy-back复制到数据目录,move-back移动(更快但删除备份)- 恢复后必须
chown mysql:mysql,否则 MySQL 无法启动 - 克隆实例时利用
xtrabackup_binlog_info快速搭建从库
下一章引子:xtrabackup 恢复到备份时刻的状态,但如果误操作发生在备份之后,还需要 binlog 来填补备份到误操作之间的数据空白。