xtrabackup 2.4 单库备份恢复 (指定数据库备份和恢复)完整教程
需求:
数据库A存在app1数据库,需要通过xtrabackup将此数据库迁移到数据库B,数据库B已经存在其他数据库数据,要求传输过程不能对B数据库的数据造成损失。
根据需求,我将采用“传输表空间”(Transportable Tablespaces)的方式来完成这个任务,这是实现部分恢复(Partial Restore)最安全、最高效的方法。
本次测试数据库版本为MySQL 5.7
重要:准备工作与前提条件
在开始之前,请务必确认以下几点,否则恢复过程会失败:
-
备份与演练:在对生产环境进行任何操作之前,强烈建议在一个测试环境中完整演练一遍。同时,请确保服务器B已有完整的、可用的备份。
-
XtraBackup 版本:确保在服务器A(或任何可以访问A数据库的机器)上安装了 Percona XtraBackup 2.4 版本。
-
MySQL 用户权限:准备一个在服务器A和B上都拥有足够权限的MySQL用户(例如
RELOAD
,PROCESS
,LOCK TABLES
,REPLICATION CLIENT
等),或者直接使用root
用户。 -
磁盘空间:确保备份目录、服务器B的临时目录和最终数据目录都有足够的磁盘空间。
-
innodb_file_per_table
:这是最关键的前提条件。app1
数据库中所有需要恢复的 InnoDB 表都必须是独立表空间。请在服务器A和B上都执行以下SQL查询进行检查:SHOW VARIABLES LIKE 'innodb_file_per_table';
必须确保其值为
ON
。如果A服务器上此值为OFF
,XtraBackup 无法进行表级别的导出/导入。如果B服务器上此值为OFF
,则无法导入表空间。对于MySQL 5.7,该值通常默认为ON
。
操作流程
整个过程分为四个主要阶段:备份 (A) -> 准备 (A) -> 传输 -> 恢复 (B)
阶段一:在服务器 A 上执行部分备份
此步骤只备份 app1
数据库。
-
登录到服务器A。
-
创建一个用于存放备份的目录,例如:
mkdir -p /data/backups/app1
-
执行备份命令。
--databases
参数是关键,它告诉 XtraBackup 只备份指定的数据库。xtrabackup --backup \ --target-dir=/data/backups/app1 \ --user=your_user \ --password=your_password \ --databases="app1"
--target-dir
: 指定备份文件的存放路径。--user
/--password
: 你的MySQL用户名和密码。--databases="app1"
: 核心参数,指定只备份app1
数据库。如果要备份多个,可以用空格隔开,如"db1 db2"
。
操作完成后,
/data/backups/app1
目录下会包含app1
数据库的数据文件和备份元数据。
阶段二:准备备份以供导出
这个“准备”步骤非常关键。我们需要使用 --export
选项,它会为每个 InnoDB 表生成一个 .cfg
元数据文件,这是在服务器B上导入表空间所必需的。
-
在服务器A上,对刚刚创建的备份执行 "prepare" 操作:
xtrabackup --prepare --export \ --target-dir=/data/backups/app1
--prepare
: 应用事务日志,使数据文件达到一致状态。--export
: 核心参数,为传输表空间做准备,生成.exp
和.cfg
文件。
-
操作完成后,你可以检查备份目录下的
app1
子目录,会看到每个表都有.ibd
,.cfg
文件。
阶段三:将备份文件传输到服务器 B
将准备好的备份目录从服务器A安全地复制到服务器B。
-
使用
scp
或rsync
命令进行传输。rsync
更优,支持断点续传。# 在服务器A上执行 rsync -avzP /data/backups/app1/ your_user@<服务器B的IP>:/data/restore/
- 这会将
app1
目录完整地复制到服务器B的/data/restore/
目录下。
- 这会将
阶段四:在服务器 B 上恢复数据库
这是最精细操作的阶段,我们将一步步地将 app1
数据库导入到服务器B中,而完全不影响B上现有的其他数据库。
-
在服务器B上创建空的
app1
数据库,编码需要自定义,这里进行了简化。
登录服务器B的MySQL:CREATE DATABASE app1;
-
在服务器B上为
app1
创建表结构。
我们需要先创建表的“空壳”(即表结构),然后才能导入数据。最简单的方法是从服务器A导出纯表结构。- 在服务器A上执行:
mysqldump --no-data --routines --triggers --events \ -u your_user -p your_password app1 > /tmp/app1_schema.sql
- 将
app1_schema.sql
文件从服务器A复制到服务器B。 - 在服务器B上导入表结构:
mysql -u your_user -p your_password app1 < /path/to/app1_schema.sql
现在,服务器B上有了一个名为
app1
的数据库,里面包含了所有表,但这些表都是空的。 - 在服务器A上执行:
-
解绑表空间(Discard Tablespace)。
对于app1
数据库中的每一张表,我们需要先解除它与当前空.ibd
文件的关联,为导入做准备。- 登录服务器B的MySQL,并对每一张表执行:
ALTER TABLE app1.your_table_name DISCARD TABLESPACE;
- 如果表很多,可以运行以下SQL生成所有命令,然后复制执行:
SELECT CONCAT('ALTER TABLE ', table_schema, '.', table_name, ' DISCARD TABLESPACE;') FROM information_schema.tables WHERE table_schema = 'app1';
- 登录服务器B的MySQL,并对每一张表执行:
-
复制数据文件 (
.ibd
) 和元数据文件 (.cfg
)。- 首先,找到服务器B的MySQL数据目录(datadir):
通常是SHOW VARIABLES LIKE 'datadir';
/var/lib/mysql/
。 - 将之前从服务器A传过来的备份文件复制到B的数据目录中对应的
app1
文件夹下。# 在服务器B的shell中执行 cp /data/restore/app1/*.ibd /var/lib/mysql/app1/ cp /data/restore/app1/*.cfg /var/lib/mysql/app1/
- 首先,找到服务器B的MySQL数据目录(datadir):
-
修正文件权限。
这是非常容易被忽略但至关重要的一步。新复制的文件属主必须是mysql
用户。chown -R mysql:mysql /var/lib/mysql/app1/
-
导入表空间(Import Tablespace)。
现在,将这些新的数据文件关联到表结构上。- 登录服务器B的MySQL,并对每一张表执行:
ALTER TABLE app1.your_table_name IMPORT TABLESPACE;
- 同样,你可以用SQL批量生成所有命令:
SELECT CONCAT('ALTER TABLE ', table_schema, '.', table_name, ' IMPORT TABLESPACE;') FROM information_schema.tables WHERE table_schema = 'app1';
- 登录服务器B的MySQL,并对每一张表执行:
-
检查和授权。
- 检查数据是否恢复成功。
USE app1; SHOW TABLES; SELECT COUNT(*) FROM your_table_name;
- 数据本身已经恢复,但服务器B上的用户可能还没有访问
app1
数据库的权限。根据需要为相关用户授权。GRANT ALL PRIVILEGES ON app1.* TO 'some_user'@'localhost'; FLUSH PRIVILEGES;
- 检查数据是否恢复成功。
总结
通过以上步骤,已经成功地将服务器A的 app1
数据库,在不影响服务器B任何现有数据的情况下,完整地迁移了过去。整个过程的核心是利用了 Percona XtraBackup 的 --databases
部分备份功能和 --export
传输表空间功能。
如果需要对单表进行备份和恢复 可以采用如下命令,恢复过程大同小异
xtrabackup --backup --datadir=/var/lib/mysql --target-dir=/data/backups/ \
--tables="^test[.].*"