XtraBackup全量备份中提取单库恢复,本质是文件系统级操作而非逻辑还原,需prepare后复制目标库目录+mysql/等必要子目录,并确保版本一致、停机操作。

从XtraBackup全量备份中提取单个数据库目录
物理备份恢复指定库,本质不是“还原某个库”,而是“把整个数据目录里的某几个子目录拎出来,塞进当前实例”。XtraBackup的全量备份是打包后的数据文件集合,不含SQL逻辑,所以不能像 mysqldump 那样靠过滤语句实现;必须操作文件系统层级。
常见错误现象:直接用 cp -r 把备份里 target_db/ 目录复制到运行中的 /var/lib/mysql/ 下,MySQL 启动失败或报错 Table 'xxx' doesn't exist —— 这是因为 InnoDB 表空间 ID 不匹配、ibdata1 未同步、或者 .frm/.ibd 文件状态不一致。
- 确认备份已 prepare 完成:
xtrabackup --prepare --target-dir=/path/to/backup/,否则文件不可用 - 目标库必须使用 InnoDB 且启用了
innodb_file_per_table=ON(默认 5.6+),否则所有表共用 ibdata1,无法单独提取 - 只提取
.ibd和.cfg(如有)文件不够,还必须有对应.frm(MySQL 5.7 及更早)或mysql.ibd+ 数据字典(8.0+)——但 8.0+ 的数据字典无法单独导出,所以该方法仅适用于 5.7 及之前版本 - 提取后需在目标实例上先创建空库:
CREATE DATABASE target_db;,再停 MySQL,替换对应目录,最后重启
为什么不能直接 restore 单个库而必须整实例 prepare
XtraBackup 的全量备份不是“快照式”拷贝,而是带事务日志的最终一致性镜像。它依赖 ibdata1、ib_logfile* 和每个 .ibd 的内部页校验与事务ID对齐。即使你只想要 db1,它的表空间也和全局系统表空间(ibdata1)存在隐式关联,比如外键约束、回滚段引用、undo log 记录等。
所以跳过 prepare 直接复制子目录,等于把一辆拆掉发动机的车轮安到另一辆没熄火的车上——表面能转,但随时会卡死。
- prepare 过程实际做了三件事:重放 redo log、清除未提交事务、校验页 checksum —— 缺一不可
- 如果你的备份是压缩包(
.xbstream或.tar.gz),必须先解压再--prepare,不能边解边 prepare - prepare 后的备份目录可多次复用,但每次用于恢复前,仍需确保目标 MySQL 实例版本与备份时一致(尤其注意 5.7 → 8.0 不兼容)
误删数据库后,用物理备份恢复的真实操作链路
核心原则:不碰线上实例的数据目录,先在隔离环境验证恢复流程。哪怕只是恢复一个库,也要走完整路径,否则上线即翻车。
- 在空机或 Docker 中启动同版本 MySQL,挂载 prepare 好的备份为
/var/lib/mysql,启动服务并验证target_db是否可查 - 确认无误后,在生产机上:停止 MySQL → 备份当前
/var/lib/mysql(重命名)→ 创建新空目录 → 仅复制target_db/子目录 +mysql/(必须,含权限表)+performance_schema/(可选但建议)→ 修复属主:chown -R mysql:mysql /var/lib/mysql - 切记不要复制
ibdata1、ib_logfile*、auto.cnf等全局文件,它们属于原实例上下文,强行覆盖会导致启动失败 - 启动 MySQL 后,立刻执行:
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'target_db';,确认表数量与备份时一致;再抽样查几条数据
比“提取目录”更稳的替代方案:用 XtraBackup 做定向恢复
与其手动 cp 子目录,不如用 XtraBackup 自带的 --export + --import 流程,专为单表/单库设计,且支持 5.7 和 8.0(8.0 需配合 DATA DIRECTORY)。
但它不适用于“已 DROP DATABASE”的场景,因为 --export 要求原表结构仍在。所以真正能用上的,其实是 “DROP TABLE” 后的恢复 —— 对于 DROP DATABASE,你唯一能依赖的,就是 prepare 后的完整备份目录本身。
- 如果备份是增量链(full + inc1 + inc2),恢复指定库前,必须按顺序 apply 所有增量,再整体 prepare,不能只对某个库子目录做增量
- 物理备份没有“时间点”概念,binlog 也无法对接 XtraBackup 导出的文件 —— 想做 PITR,必须搭配
mysqlbinlog解析并重放,且只能从 prepare 后的全量起点开始 - 最易被忽略的一点:恢复后,所有用户权限不会自动还原。你需要单独从备份的
mysql/目录里导出user.MYD(MyISAM)或用mysqldump --no-data --routines --triggers mysql提前备好权限脚本


















