1. xtrabackup简介
xtrabackup是percona团队研发的备份工具 , 比MySQL官方的ibbackup的功能还要多。支持myisam温全备、innodb热全备和温增备 , 还可以实现innodb的定时点恢复 , 而且备份和恢复的速度都较快。在目前MySQL的备份实现上 , 考虑价格、速度、安全、一致性等角度 , xtrabackup是非常合适的工具。
MariaDB也可以使用percona xtrabackup进行备份 , 不过MariaDB基于percona xtrabackup开发了它自己的备份工具 : MariaDB Backup。它基于xtrabackup开发 , 所以所用方法基本和xtrabackup相同 , 只是有些自己的特性。详细内容见MariaDB Backup官方手册 : https://mariadb.com/kb/en/library/mariadb-backup/
xtrabackup官方手册 : https://www.percona.com/doc/percona-xtrabackup/LATEST/index.html
xtrabackup包含两个主要的工具 , 即xtrabackup和innobackupex , 二者区别如下 :
xtrabackup只能备份innodb和xtradb两种引擎的表 , 而不能备份myisam引擎的表;innobackupex是一个封装了xtrabackup的Perl脚本 , 支持同时备份innodb和myisam, 但在对myisam备份时需要加一个全局的读锁。还有就是myisam不支持增量备份。
备份生成的相关文件
使用innobackupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中,在备份时,innobackupex还会在备份目录中创建如下文件:
xtrabackup_info:innobackupex工具执行时的相关信息,包括版本,备份选项,备份时长,备份LSN(log sequence number日志序列号),BINLOG的位置xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的xtrabackup_binlog_info:MySQL服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置,可利用实现基于binlog的恢复backup-my.cnf:备份命令用到的配置选项信息xtrabackup_logfile:备份生成的日志文件
2. 安装xtrabackup
下载地址 : https://www.percona.com/downloads/XtraBackup/LATEST/
rpm仓库(实际上是percona的仓库) : http://repo.percona.com/release/
清华大学percona源 : https://mirrors.tuna.tsinghua.edu.cn/percona/
因为只是一个备份工具 , 所以没必要编译安装 , 直接下载它的rpm包即可。但是该rpm包依赖于libev.so.4 , 该依赖包可以在epel源中找到。
这里安装的是目前最新版的xtrabackup-24-2.4.11。
cat <<eof>>/etc/yum.repos.d/percona.repo
[percona]
name = Percona
baseurl = https://mirrors.tuna.tsinghua.edu.cn/percona/release/\$releasever/RPMS/\$basearch
enabled = 1
gpgcheck = 0
[epel]
name=epelrepo
baseurl=https://mirrors.aliyun.com/epel/\$releasever/\$basearch
gpgcheck=0
enable=1
eof
[root@node1 ~]# yum list all| grep xtraback -i
Repository epel is listed more than once in the configuration
holland-xtrabackup.noarch 1.0.14-3.el6 epel
percona-xtrabackup.x86_64 2.3.10-1.el6 percona
percona-xtrabackup-20.x86_64 2.0.8-587.rhel6 percona
percona-xtrabackup-20-debuginfo.x86_64 2.0.8-587.rhel6 percona
percona-xtrabackup-20-test.x86_64 2.0.8-587.rhel6 percona
percona-xtrabackup-21.x86_64 2.1.9-746.rhel6 percona
percona-xtrabackup-21-debuginfo.x86_64 2.1.9-746.rhel6 percona
percona-xtrabackup-22.x86_64 2.2.13-1.el6 percona
percona-xtrabackup-22-debuginfo.x86_64 2.2.13-1.el6 percona
percona-xtrabackup-24.x86_64 2.4.11-1.el6 percona
percona-xtrabackup-24-debuginfo.x86_64 2.4.11-1.el6 percona
percona-xtrabackup-debuginfo.x86_64 2.3.10-1.el6 percona
percona-xtrabackup-test.x86_64 2.3.10-1.el6 percona
percona-xtrabackup-test-21.x86_64 2.1.9-746.rhel6 percona
percona-xtrabackup-test-22.x86_64 2.2.13-1.el6 percona
percona-xtrabackup-test-24.x86_64 2.4.11-1.el6 percona
[root@node1 ~]# yum -y install percona-xtrabackup-24装完xtrabackup后 , 生成以下几个工具。
[root@node1 ~]# rpm -ql percona-xtrabackup-24 | grep bin | xargs ls -hl
lrwxrwxrwx 1 root root 10 May 8 19:19 /usr/bin/innobackupex -> xtrabackup
-rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbcloud
-rwxr-xr-x 1 root root 3.0K Apr 19 01:04 /usr/bin/xbcloud_osenv
-rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbcrypt
-rwxr-xr-x 1 root root 3.5M Apr 19 01:11 /usr/bin/xbstream
-rwxr-xr-x 1 root root 21M Apr 19 01:11 /usr/bin/xtrabackupxbcloud和xbcloud_osenv是xtrabackup新的高级特性 : 云备份;xbcrypt也是新的特性 , 加密备份集;xbstream是xtrabackup的流数据功能 , 通过流数据功能 , 可将备份内容打包并传给管道后的压缩工具进行压缩;xtrabackup是主程序;innobackupex在以前是一个perl脚本 , 会调用xtrabackup这个二进制工具 , 从xtrabackup 2.3开始 , 该工具使用C语言进行了重写 , 当前它是xtabackup二进制工具的一个软连接 , 但是实际的使用方法却不同 , 并且在以后的版本中会删除该工具。
在本文中 , 会分别对两个主程序innobackupex和xtrabackup的备份恢复方法进行详细的说明 , 还会在说明过程中尽可能的解释它们是如何工作的 , 另外还会介绍它们的一些特殊功能的选项 , 如流备份选项。
如果需要安装 mariadb与之对应的备份工具 Mariabackup , 直接安装mariadb源, 然后运行以下命令即可
[root@mariadb ~]# yum install MariaDB-backup3. 备份锁
一篇不错的介绍xtrabackup锁的文章 : https://www.percona.com/blog/2014/03/11/introducing-backup-locks-percona-server-2/。
percona Server 5.6+ 支持一种新锁——backup lock(备份锁) , 这种锁是percona对MySQL的补充 , 专门为备份而设计。这种锁在percona Server 5.6+有 , MariaDB中也有 , 但是Oracle的MySQL中没有 , 至少MySQL 5.7中没有。
这种锁用在备份的时候替代 flush tables with read lock 获取全局锁 , 是一种轻量级的全局锁。它有两种类型的锁 : 备份表锁和二进制日志锁。为此新增了3种语法 :
lock tables for backup # 申请备份表锁
lock binlog for backup # 申请二进制日志锁
unlock binlog # 释放二进制日志锁备份表锁在全局范围内只对非innodb表加锁 , 所以持有该锁后无法修改非innodb表 , 但却不影响innodb表的DML。当然 , 因为是全局锁 , 所以也会阻塞DDL操作。
二进制日志锁在全局范围内锁定二进制日志 , 所以会阻塞其他会话修改二进制日志。这样可以保证能够获取到二进制日志中一致性的位置坐标。
4. xtrabackup备份原理说明
4.1 备份过程(backup)阶段

在启动
xtrabackup时记下LSN并将redo log拷贝到备份目标目录下的xtrabackup_logfile文件中。由于拷贝需要一定时间 , 如果在拷贝时间段内有日志写入 , 将导致拷贝的日志和MySQL的redo log不一致 , 所以xtrabackup还有一个后台进程监控着mysql的redo log, 每秒监控一次 , 当MySQL的redo log有变化 , 该监控进程会立即将变化的内容写入到xtrabackup_logfile文件 , 这样就能保证拷贝走的redo log中记录了一切变化。但是这也是有风险的 , 因为redo是轮训式循环写入的 , 如果某一时刻有非常大量的日志写到redo log中 , 使得还没开始复制的日志就被新日志覆盖了 , 这样会日志丢失 , 并报错。拷贝完初始版的
redo log后 ,xtrabackup开始拷贝innodb表的数据文件(即表空间文件.ibd文件和ibdata1)。注意 , 此时不拷贝innodb的frm文件。当
innodb相关表的数据文件拷贝完成后 ,xtrabackup开始准备拷贝非innodb的文件。但在拷贝它们之前 , 要先对非innodb表进行加锁防止拷贝时有语句修改这些类型的表数据。对于不支持
backup lock的版本 , 只能通过flush tables with read lock来获取全局读锁 , 但这样也同样会锁住innodb表 , 杀伤力太大。所以使用xtrabackup备份Oracle的MySQL, 实质上只能实现innodb表的部分时间热备、部分时间温备。对于支持
backup lock的版本 ,xtrabackup通过lock tables for backup获取轻量级的backup locks来替代flush tables with read lock, 因为它只锁定非innodb表 , 所以由此实现了innodb表的真正热备。当获取到非
innodb表的锁以后 , 开始拷贝非innodb表的数据和.frm文件。当这些拷贝完成之后 , 继续拷贝其他存储引擎类型的文件。(实际上 , 拷贝非innodb表的数据是在获取backup locks(如果支持)后自动进行的 , 它们属于同一个过程)当拷贝阶段完成后 , 就到了备份的收尾阶段。包括获取二进制日志中一致性位置的坐标点、结束
redo log的监控和拷贝、释放锁等。对于不支持
backup lock的版本 , 收尾阶段的过程是这样的 : 获取二进制日志的一致性坐标点、结束redo log的监控和拷贝、释放锁。对于支持
backup lock的版本 , 收尾阶段的过程是这样的 : 先通过lock binlog for bakcup来获取二进制日志锁 , 然后结束redo log的监控和拷贝 , 再unlock tables释放表锁 , 随后获取二进制日志的一致性位置坐标点 , 最后unlock binlog释放二进制日志锁。如果一切都
OK,xtrabackup将以状态码0退出。
所以 , 对是否支持backup lock的版本 , xtrabackup备份的时的行为是不一样的。

backup阶段的过程具体如下图所示 :

FTWRL : flush table with read lock;

4.2 准备过程(prepare阶段)
由于备份的时候拷贝走的数据文件可能是不一致的 , 比如监控着MySQL的redo log中在拷贝过程完成后又新的事务提交了 , 而拷贝走的数据是未提交状态的 , 那么就需要对该事务前滚;如果监控到的日志中有事务未提交 , 那么该事务就需要回滚。
但是如果只备份了myisam表或其他非事务表数据 , 因为备份阶段直接锁定了这些表 , 所以不会有不一致的状态。
xtrabackup有一个"准备"的阶段。这个阶段的实质就是对备份的innodb数据应用redo log , 该回滚的回滚 , 该前滚的前滚 , 最终保证xtrabackup_logfile中记录的redo log已经全部应用到备份数据页上 , 并且实现了一致性。当应用结束后 , 会重写"xtrabackup_logfile"再次保证该redo log和备份的数据是对应的。
准备过程不需要连接数据库 , 该过程可以在任意装了xtrabackup软件的机器上进行 , 之所能实现是因为xtrabackup软件的内部嵌入了一个简化的innodb存储引擎 , 可以通过它完成日志的应用。
4.3 恢复过程(copy back阶段)
xtrabackup的恢复过程实质是将备份的数据文件和结构定义等文件拷贝回MySQL的datadir。同样可以拷贝到任意机器上。
要求恢复之前MySQL必须是停止运行状态 , 且datadir是空目录 , 除非恢复的操作是导入表的操作。具体见后文对应的内容。
5. 准备实验环境
创建测试数据库backuptest , 并创建myisam表和innodb表 , 此处简单的使用数值辅助表并分别插入1亿条数据。
DROP DATABASE IF EXISTS backuptest;
CREATE DATABASE backuptest;
USE backuptest;
# 创建myisam类型的数值辅助表和对应插入数据的存储过程
CREATE TABLE num_isam(n INT NOT NULL PRIMARY KEY)ENGINE=MYISAM;
DELIMITER $$
DROP PROCEDURE IF EXISTS proc_num1$$
CREATE PROCEDURE proc_num1(num INT)
BEGIN
DECLARE rn INT DEFAULT 1;
TRUNCATE TABLE backuptest.num_isam;
INSERT INTO backuptest.num_isam VALUES(1);
dd: WHILE rn*2 < num DO
BEGIN
INSERT INTO backuptest.num_isam SELECT rn+n FROM backuptest.num_isam;
SET rn = rn*2;
END;
END WHILE dd;
INSERT INTO backuptest.num_isam SELECT n+rn FROM num_isam WHERE n+rn <=num;
END;$$
DELIMITER ;
# 创建innodb类型的数值辅助表和对应插入数据的存储过程
CREATE TABLE num_innodb(n INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
DELIMITER $$
DROP PROCEDURE IF EXISTS proc_num2$$
CREATE PROCEDURE proc_num2(num INT)
BEGIN
DECLARE rn INT DEFAULT 1;
TRUNCATE TABLE backuptest.num_innodb;
INSERT INTO backuptest.num_innodb VALUES(1);
dd: WHILE rn*2 < num DO
BEGIN
INSERT INTO backuptest.num_innodb SELECT rn+n FROM backuptest.num_innodb;
SET rn = rn*2;
END;
END WHILE dd;
INSERT INTO backuptest.num_innodb SELECT n+rn FROM backuptest.num_innodb WHERE n+rn <=num;
END;$$
DELIMITER ;
# 分别向两个数值辅助表中插入1亿条数据 ,
CALL proc_num1(100000000);
CALL proc_num2(100000000);6.innobackupex工具
备份 :
innobackupex [option] BACKUP-ROOT-DIR选项说明 :https://www.percona.com/doc/percona-xtrabackup/LATEST/genindex.html
--user:该选项表示备份账号--password:该选项表示备份的密码--host:该选项表示备份数据库的地址--databases:该选项接受的参数为数据库名,如果要指定多个数据库,彼此间需要以空格隔开;如:"xtra_test dba_test",同时,在指定某数据库时,也可以只指定其中的某张表。如:"mydatabase.mytable"。该选项对innodb引擎表无效,还是会备份所有innodb表--defaults-file:该选项指定从哪个文件读取MySQL配置,必须放在命令行第一个选项位置--incremental:该选项表示创建一个增量备份,需要指定--incremental-basedir--incremental-basedir:该选项指定为前一次全备份或增量备份的目录,与--incremental同时使用--incremental-dir:该选项表示还原时增量备份的目录--include=name:指定表名,格式:databasename.tablename
Prepare :
innobackupex --apply-log [option] BACKUP-DIR--apply-log:一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。此选项作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态--use-memory:和--apply-log选项一起使用,当prepare备份时,做crash recovery分配的内存大小,单位字节,也可1MB,1M,1G,1GB等,推荐1G,最后一次还原需要加上--apply-log选项--export:表示开启可导出单独的表之后再导入其他Mysql中--redo-only:此选项在prepare base full backup,往其中合并增量备份时候使用,但不包括对最后一个增量备份的合并,不是最后一次还原,需要加--redo-only选项
还原 :
innobackupex --copy-back [选项] BACKUP-DIR innobackupex --move-back [选项] [--defaults-group=GROUP-NAME] BACKUP-DIR选项说明:
--copy-back: 做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir--move-back:#这个选项与--copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这 个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同事保留数据文件和Backup副本--force-non-empty-directories: 指定该参数时候,使得innobackupex --copy-back或--move back选项转移文件到非空目录,已存在的文件不会被覆盖。如果--copy-back和--move-back文件需要从 备份目录拷贝一个在datadir已经存在的文件,会报错失败
6.1 innobackupex实现全备份和恢复的过程
全备
除了给定连接
MySQL服务器的连接参数 , 只需再给定一个目录即可 , 该目录是备份的目标位置。默认xtrabackup连接数据库的时候从配置文件中去读取和备份相关的配置 , 可以使用选项--defaluts-file指定连接时的参数配置文件 , 但如果指定该选项 , 该选项只能放在第一个选项位置。innobackupex --user=root --password=123456 /bakdir/默认备份的路径是指定路径
/bakdir下的一个以时间为时间戳的目录。[root@xuexi bakdir]# du -sh /bakdir/2017-04-02_07-09-47/* 4.0K /bakdir/2017-04-02_07-09-47/backup-my.cnf 4.0G /bakdir/2017-04-02_07-09-47/backuptest 589M /bakdir/2017-04-02_07-09-47/ibdata1 1.8M /bakdir/2017-04-02_07-09-47/mysql 8.0K /bakdir/2017-04-02_07-09-47/Performance 636K /bakdir/2017-04-02_07-09-47/performance_schema 1008K /bakdir/2017-04-02_07-09-47/world 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_binlog_info 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_checkpoints 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_info 4.0K /bakdir/2017-04-02_07-09-47/xtrabackup_logfile查看该文件目录中文件和大小 , 可以看出
xtrabackup的行为就是复制了目标数据库的相关文件 , 并新建了几个文件。其中 :
backup-my.cnf是拷贝过来的配置文件。里面只包含[mysqld]配置片段和备份有关的选项。xtrabackup_binlog_info中记录的是当前使用的二进制日志文件。[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_binlog_info mysql-bin.000001 120xtrabackup_checkpoints中记录了备份的类型是全备还是增备 , 还有备份的起始、终止LSN号。[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 7533359841 last_lsn = 7533359841 compact = 0 recover_binlog_info = 0xtrabackup_info中记录的是备份过程中的一些信息。[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_info uuid = 66f34974-1730-11e7-9d09-000c299af3f3 name = tool_name = innobackupex tool_command = --user=root --password=... /bakdir/ tool_version = 2.4.6 ibbackup_version = 2.4.6 server_version = 5.6.35-log start_time = 2017-04-02 07:09:47 end_time = 2017-04-02 07:10:31 lock_time = 0 binlog_pos = filename 'mysql-bin.000001', position '120' innodb_from_lsn = 0 innodb_to_lsn = 7533359841 partial = N # N表示未启用该方面的功能 , 如此处表示不是备份部分数据库或表 incremental = N format = file compact = N compressed = N encrypted = Nxtrabackup_logfile是复制和监控后写的redo日志。该日志是备份后下一个操作"准备"的关键。只有通过它才能实现数据一致性。
全备的准备过程
在全备份完成之后 , 备份的数据中如果有
innodb数据 , 则还不能用来恢复。因为从xtrabackup开始备份的时候就监控着MySQL的redo log, 在拷贝的innodb数据文件中很可能还有未提交的事务 , 并且拷贝完innodb数据之后还可能提交了事务或者开启了新的事务等等。总之 , 全备之后的状态不一定是一致的。但是如果只备份了myisam表或其他非事务表数据 , 因为备份阶段直接锁定了这些表 , 所以不会有不一致的状态。xtrabackup有一个"准备"的阶段。这个阶段的实质就是对备份的innodb数据应用redo log, 该回滚的回滚 , 该前滚的前滚 , 最终保证xtrabackup_logfile中记录的redo log已经全部应用到备份数据页上 , 并且实现了一致性。当应用结束后 , 会重写"xtrabackup_logfile"再次保证该redo log和备份的数据是对应的。例如 , 备份的
innodb数据文件中存在未提交的事务 , 但是在监控到的日志中进行了提交 , 那么就需要对该事务前滚;如果监控到的日志中有事务未提交 , 那么该事务就需要回滚。准备阶段使用的模式选项是"
--apply-log"。准备阶段不会连接MySQL, 所以不用指定连接选项如--user等。[root@xuexi bakdir]# innobackupex --apply-log /bakdir/2017-04-02_07-09-47/在准备成功时 , 会在频幕上输出如下提示内容 :
InnoDB: FTS optimize thread exiting. InnoDB: Starting shutdown... InnoDB: Shutdown completed; log sequence number 7533367063 170402 12:11:23 completed OK!在准备阶段 , 有一个内存使用量选项"
--use-memory" , 该选项默认值为100M, 值越大准备的过程越快。当然 , 将该值加大的前提是服务器内存够用。全备份的恢复过程
恢复的阶段就是向
MySQL的datadir拷贝。全备份的恢复要求MySQL必须处于stop状态 , 并且datadir必须为空哪怕是和MySQL无关的文件也不能存在 , 它不会去覆盖datadir中已存在的内容。否则会提示如下错误 :innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7) Original data directory /mydata/data is not empty!停止
mysql并清空datadir。service mysqld stop rm -rf /mydata/data/*恢复时使用的模式是"
--copy-back" , 选项后指定要恢复的源备份目录。恢复时因为不需要连接数据库 , 所以不用指定连接选项 , 如--user等。[root@xuexi bakdir]# innobackupex --copy-back /bakdir/2017-04-02_07-09-47/ 170402 12:36:09 completed OK!
拷贝完成后 , MySQL的datadir的文件的所有者和属组是innobackupex的调用者 , 所以需要改回mysql.mysql。
[root@xuexi bakdir]# ll /mydata/data/
total 712736
drwxr-x--- 2 root root 4096 Apr 2 12:36 backuptest
-rw-r----- 1 root root 616562688 Apr 2 12:35 ibdata1
-rw-r----- 1 root root 50331648 Apr 2 12:35 ib_logfile0
-rw-r----- 1 root root 50331648 Apr 2 12:35 ib_logfile1
-rw-r----- 1 root root 12582912 Apr 2 12:36 ibtmp1
drwxr-x--- 2 root root 4096 Apr 2 12:36 mysql
drwxr-x--- 2 root root 4096 Apr 2 12:35 Performance
drwxr-x--- 2 root root 4096 Apr 2 12:36 performance_schema
drwxr-x--- 2 root root 4096 Apr 2 12:35 world
-rw-r----- 1 root root 23 Apr 2 12:35 xtrabackup_binlog_pos_innodb
-rw-r----- 1 root root 494 Apr 2 12:35 xtrabackup_info
[root@xuexi bakdir]# chown -R mysql.mysql /mydata/data/*完成这些之后 , 就可以启动MySQL服务器了。可以进入mysql测试backuptest数据库中的数据是否完整。
6.2 innobackupex实现增量备份和恢复的过程
增量备份依赖于全备份。xtrabackup实现增量备份的原理是通过比较全备份的终点LSN和当前的LSN , 增备时将从终点LSN开始一直备份到当前的LSN。在备份时也有redo log的监控线程 , 对于增备过程中导致LSN增长的操作也会写入到日志中。
增备的实现依赖于LSN , 所以只对innodb有效 , 对myisam表使用增备时 , 背后进行的是全备。
要进行增备 , 首先要有全备文件。这里重新进行一次全备。
innobackupex --user=root --password=123456 /bakdir/全备完成后 , 在
/bakdir目录下生成的全备目录是2017-04-02_13-26-35。[root@xuexi ~]# ls /bakdir/2017-04-02_13-26-35/ backup-my.cnf ibdata1 Performance secure_dir xtrabackup_binlog_info xtrabackup_info backuptest mysql performance_schema world xtrabackup_checkpoints xtrabackup_logfile查看
xtrabackup_checkpoints可以得知相关的LSN。[root@xuexi ~]# cat /bakdir/2017-04-02_13-26-35/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 7533367093 last_lsn = 7533367093 compact = 0 recover_binlog_info = 0注意 : 要实现增备 , 这一次的全备一定不能进行"准备"操作 , 原因稍后给出。
进行第一次增备。
假设对示例数据可
backuptest中的num_innodb表进行了truncate操作。mysql> truncate backuptest.num_innodb;然后再增备。增备时使用"
--incremental"选项表示增量备份 , 增量备份时需要通过"--incremental-basedir=fullback_PATH"指定基于哪个备份集备份 , 因为是第一次增备 , 所以要基于完全备份增量集。[root@xuexi ~]# innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-basedir=/bakdir/2017-04-02_13-26-35/增备完成后 , 生成的增备集为
/bakdir/2017-04-02_13-39-05/, 查看其中的xtrabackup_checkpoints, 可以看到备份的起始LSN是上次全备完成后的LSN。[root@xuexi ~]# cat /bakdir/2017-04-02_13-39-05/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533367093 to_lsn = 7533372535 last_lsn = 7533372535 compact = 0 recover_binlog_info = 0默认情况下 , 增备的起始
LSN是自动获取的 , 但是在某些情况下无法获取 , 还有些情况下无法获取到将要增备的basedir。xtrabackup提供的选项"--incremental-lsn=N"可以显式指定增备的起始LSN, 显式指定LSN时 , 可以无需提供增备的basedir。例如 , 如果获取到了上次全备的终止
LSN为7533367093, 可以如下方式增备 :innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-lsn=7533367093这样增备后也在
/bakdir中生成一个时间戳目录/bakdir/2017-04-02_13-50-33。查看LSN信息 :[root@xuexi ~]# cat /bakdir/2017-04-02_13-50-33/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533367093 to_lsn = 7533372535 last_lsn = 7533372535 compact = 0 recover_binlog_info = 0由此可知和指定
--incremental-basedir进行增备是一样的。进行第二次增备。
假设在第一次增备后 , 向上次
truncate的表backuptest.num_innodb表中插入的100W条记录。mysql> call backuptest.proc_num2(1000000); mysql> select count(*) from backuptest.num_innodb; +----------+ | count(*) | +----------+ | 1000000 | +----------+然后进行增备。这次增备是基于第一次增备的(当然也可以基于全备进行备份 , 这样实现的是差异备份)。
[root@xuexi ~]# innobackupex --user=root --password=123456 --incremental /bakdir/ --incremental-basedir=/bakdir/2017-04-02_13-39-05/这次增备完成后生成的备份集为
/bakdir/2017-04-02_14-03-51/。查看LSN信息 :[root@xuexi ~]# cat /bakdir/2017-04-02_14-03-51/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533372535 to_lsn = 7585150275 last_lsn = 7585150275 compact = 0 recover_binlog_info = 0增备的准备过程
增备的准备过程和全备的准备过程有点不一样 , 不到最后恢复的时候不能进行任何"准备"过程。
增备过程中的每一次备份行为都会监控
MySQL的redo log, 写入到xtrabackup_logfile的日志中可能会有未提交的事务 , 但是到后面增备的时候进行了提交 , 也就是说提交过程记录到了增备时监控的日志xtrabackup_logfile中。如果在增备前进行了"准备" , 那么该事务就会被回滚 , 后面增备中的提交就丢失了 , 由此会造成数据丢失。要保证将所有的备份集进行整合 , 需要使用在每个备份集的"准备"过程中使用"
--redo-only"选项 , 这样应用日志时会"直线向前"直到最后一个备份集。它的本质是向全备集中不断的追加应用增备中的日志。但是 , 最后一个增备集需要作为备份集整合的终点 , 所以它不能使用"--redo-only"选项。整合完成之后 , 原来的全备就已经完整了 , 这时再对追加完成的全备集进行一次"准备"即可用于后面的恢复。所以 , 如果全备为
A,3次增备分别为B/C/D, 如果只想恢复到C, 那么从A开始整合到C结束即可。因为在每一个增备的"准备"过程中都需要向整合的开始备份集中追加应用日志 , 所以每一次增备的"准备"都需要指定整合的开始备份集目录作为
basedir。例如指定全备份作为整合的初始备份集。从以上实验过程中 , 得到的全备集是
2017-04-02_13-26-35, 第一次和第二次增备集分别是2017-04-02_13-26-35、2017-04-02_14-03-51。下面是它们的"准备"过程。# 对整合的开始备份集——全备集应用日志 , 并指定"--redo-only"表示开始进入日志追加 innobackupex --apply-log --redo-only /bakdir/2017-04-02_13-26-35 # 对第一个增备集进行"准备" , 将其追加到全备集中 innobackupex --apply-log --redo-only /bakdir/2017-04-02_13-26-35 --incremental-dir=/bakdir/2017-04-02_13-39-05 # 对第二个增备集进行"准备" , 将其追加到全备集中 , 但是不再应用"--redo-only" , 表示整合的结束点 innobackupex --apply-log /bakdir/2017-04-02_13-26-35 --incremental-dir=/bakdir/2017-04-02_14-03-51 # 对整合完成的全备集进行一次整体的"准备" innobackupex --apply-log /bakdir/2017-04-02_13-26-35当所有的备份集整合完毕后 , 就像是一个完整的全备集 , 全备中的
LSN会更新到整合的结束点。如下 :[root@xuexi data]# cat /bakdir/2017-04-02_13-26-35/xtrabackup_checkpoints backup_type = full-prepared from_lsn = 0 to_lsn = 7585150275 #整合完成后全备中的LSN last_lsn = 7585150275 compact = 0 recover_binlog_info = 0 [root@xuexi data]# cat /bakdir/2017-04-02_14-03-51/xtrabackup_checkpoints backup_type = incremental from_lsn = 7533372535 to_lsn = 7585150275 #整合的结束备份集中的LSN last_lsn = 7585150275 compact = 0 recover_binlog_info = 0如果不小心整合的顺序错误了 , 那么整合的备份集将是无效的 , 需要重新整合。
增备的恢复过程
因为整合结束后就等价于一个全备集 , 所以可以直接进行恢复。
恢复过程同样需要保证
MySQL的datadir是空的 , 且MySQL服务器是stop的。service mysqld stop rm -rf /mydata/data/* innobackupex --copy-back /bakdir/2017-04-02_13-26-35 chown -R mysql.mysql /mydata/data/*然后重启
MySQL, 进入查看可知num_innodb的数据为100W行记录 , 即恢复成功。mysql> select count(*) from backuptest.num_innodb; +----------+ | count(*) | +----------+ | 1000000 | +----------+
6.3 innobackupex实现导出和导入单张表的过程
默认情况下 , InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植 , 即便使用了innodb_file_per_table选项。而使用Xtrabackup工具可以实现此种功能 , 不过只能"导出"具有.ibd文件的表 , 也就是说导出表的mysql服务器启用了innodb_file_per_table选项 , 而且要导出的表还是在启用该选项之后才创建的。
导入表的是 , 要求导入表的服务器版本是MySQL 5.6+ , 且启用了innodb_file_per_table选项。
导出表
备份表结构用于后续创建表过程
mysql -e 'show create table mydatabase.tabletest' > student.sql导出表是在"准备"的过程中进行的 , 不是在备份的时候导出。对于一个已经备份好的备份集 , 使用"
--apply-log"和"--export"选项即可导出备份集中的表。假如以全备份集
/bakdir/2017-04-02_17-41-38为例 , 要导出其中的表。innobackupex --apply-log --export /bakdir/2017-04-02_17-41-38在导出过程中 , 会看到如下信息 :
xtrabackup: export metadata of table 'backuptest/num_innodb' to file `./backuptest/num_innodb.exp` (1 indexes) xtrabackup: name=PRIMARY, id``.low=144, page=3它说明了创建了一个
.exp文件。查看备份集目录下的
backuptest目录 , 会发现多出了2个文件 :.cfg和.exp, 再加上.ibd文件 , 这3个文件是后续导入表时所需的文件。-rw-r--r-- 1 root root 349 Apr 2 18:15 num_innodb.cfg -rw-r----- 1 root root 16K Apr 2 18:15 num_innodb.exp -rw-r----- 1 root root 8.4K Apr 2 17:41 num_innodb.frm -rw-r----- 1 root root 31M Apr 2 17:41 num_innodb.ibd其中
.cfg文件是一种特殊的innodb数据字典文件 , 它和exp文件的作用是差不多的 , 只不过后者还支持在xtradb中导入 , 严格地讲 , 要将导出的表导入到MySQL5.6或者percona server 5.6中 , ".cfg"文件完全可以不需要 , 但是如果有该文件的话 , 会进行架构验证。导入表
将生生成的文件拷贝到对应的
mysql目录中cp /bakdir/2017-04-02_17-41-38/mydatabase/tabletest.{cfg,exp,ibd} /var/lib/mysql/hellodb/ chown -R mysql.mysql /var/lib/mysql/hellodb/要在
mysql服务器上导入来自于其它服务器的某innodb表 , 需要先在当前服务器上创建一个跟原表表结构一致的表 , 而后才能实现将表导入 :mysql> CREATE TABLE tabletest (...) ENGINE=InnoDB;然后将此表的表空间 :
mysql> ALTER TABLE mydatabase.tabletest DISCARD TABLESPACE;接下来 , 将来自于"导出"表的的
.ibd和.exp文件复制到当前服务器的数据目录 , 如果导入目标服务器是MySQL 5.6+, 也可以复制.cfg文件。然后使用如下命令将其“导入” :mysql> ALTER TABLE mydatabase.tabletest IMPORT TABLESPACE;
6.4 innobackupex实现部分备份和恢复的过程
xtrabackup支持部分备份 , 意味着可以指定备份哪个数据库或者哪个表。
部分备份只有一点需要注意 : 在恢复的时候不要通过"--copy-back"的方式拷贝回datadir , 而是应该使用导入表的方式。尽管使用拷贝的方式有时候是可行的 , 但是很多情况下会出现数据库不一致的状态。
备份
创建部分备份有三种方式 :
通过"
--include"选项可以指定正则来匹配要备份的表 , 这种方式要使用完整对象引用格式 , 即db_name.tab_name的方式。将要备份的表分行枚举到一个文件中 , 通过"
--tables-file"指定该文件。或者使用"
--databases"指定要备份的数据库或表 , 指定备份的表时要使用完整对象引用格式 , 多个元素使用空格分开。
使用前两种部分备份方式 , 只能备份
innodb表 , 不会备份任何myisam, 即使指定了也不会备份。而且要备份的表必须有独立的表空间文件 , 也就是说必须开启了innodb_file_per_table, 更精确的说 , 要备份的表是在开启了innodb_file_per_table选项之后才创建的。第三种备份方式可以备份myisam表。例如
--include='^back.*[.]num_*', 将备份back字母开头的数据库中num开头的表 , 其中"[.]"的中括号不能少 , 因为正则中"."有特殊意义 , 所以使用中括号来枚举以实现对象的完整引用。innobackupex --user=root --password=123456 --include='^back*[.]num_*' /bakdir/使用"
--include"和"--tables-file"备份后 , 会生成一个时间戳目录 , 目录中只有和要备份的表有关的文件。[root@xuexi data]# ls /bakdir/2017-04-02_17-35-46/ backup-my.cnf ibdata1 xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile如果使用的是
--databases选项 , 则会生成一个时间戳目录 , 里面有备份的数据库代表的目录 , 如果只备份了某个表 , 则该数据库目录中只有该表相关的文件。innobackupex --user=root --password=123456 --databases='mysql.user backuptest' /bakdir/上面只备份
mysql.user表和backuptest数据库 , 在生成的时间戳目录中将有两个mysql目录和backuptest目录。[root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/ backup-my.cnf backuptest ibdata1 mysql xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile [root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/backuptest/ db.opt num_innodb.frm num_innodb.ibd num_isam.frm num_isam.MYD num_isam.MYI [root@xuexi data]# ls /bakdir/2017-04-02_17-41-38/mysql/ user.frm user.MYD user.MYI部分备份的准备和恢复过程
部分备份的准备和恢复过程分别是导出表和导入表的过程。见上文。
6.5 innobackupex实现定时点恢复
xtrabackup本身无法实现定时点恢复 , 只能通过恢复备份后通过二进制日志实现。实现方法和一般定时点恢复是一样的。见 : 二进制日志定点还原数据库。具体可以查看3-6-1日志管理一章中的最后一节即可。
6.6 流备份和远程备份
xtrabackup支持备份流 , 当前可用的流类型只有tar和xtrabackup自带的xbstream , 通过流可以将它们传递给其他程序进行相关的操作 , 如压缩。但是不建议在备份的同时进行压缩 , 因为压缩会占用极大的cpu资源 , 使得备份时间延长很多 , 温备的过程也就延长了。
另外 , MySQL的数据文件压缩比非常大 , 所以建议备份后在空闲的时候进行压缩。
xtrabackup还支持远程备份 , 只需使用"--remote-host"指定远程的主机名即可 , 指定方式和ssh指定的方式一样。如--remote-host=root@192.168.100.18。
使用流备份的方法如下 :
# 使用tar流
innobackupex --user=root --password=123456 --stream=tar /bakdir/ >/tmp/a.tar
# 使用tar流的同时交给gzip压缩
innobackupex --user=root --password=123456 --stream=tar /bakdir/ | gzip >/tmp/a.tar.gz
# 使用tar流备份到远程主机中并归档
innobackupex --user=root --password=123456 --stream=tar /bakdir/ | ssh root@192.168.100.10 "cat - > /tmp/`date +%F_%H-%M-%S`.tar"
# 使用tar流备份到原远程主机中并解包
innobackupex --user=root --password=123456 --stream=tar /bakdir/ | ssh root@192.168.100.10 "cat - | tar -x -C /tmp/"
# 使用xtrabackup自带的xbstream流
innobackupex --user=root --password=123456 --stream=xbstream /bakdir/ >/tmp/b.xbs
# 解压xbstream流
innobackupex --user=root --password=123456 --stream=xbstream /bakdir/ | ssh root@192.168.100.10 "cat - | xbstream -x -C /tmp/"
# 使用xbstream流的同时进行压缩 , 使用"--compress"选项
innobackupex --user=root --password=123456 --stream=xbstream --compress /bakdir/ > /bakdir/backup.xbs注意 , 如果在解压备份的.tar.gz时出错 , 可能在解压的时候需要使用-i选项。如tar -xif /tmp/b.tar/gz。
6.7 加速备份
当备份到本地的时候 , 可以使用"--rsync"选项 , 该选项用于在flush tables with read lock后调用rsync替代cp进程复制非Innodb数据和.frm文件 , 加快复制速度。
但要注意 , 因为支持备份锁的版本在获取到backup locks的时候会自动复制非Innodb数据和.frm文件 , 所以"--rsync"选项是无效的。
另外 , 该选项不能和"--stream"选项和"--remote-host"选项同时使用。
7.xtrabackup工具
xtrabackup工具是C语言编写的工具 , 在innobackupex使用C重写之后 , innobackupex是该工具的一个软链接。但是它不能实现innobackupex的所有功能 , 例如xtrabackup工具没有恢复功能 , 而innobackupex有"--copy-back"选项来恢复。
xtrabackup工具有两种常用运行模式 : "--backup"和"--prepare"。还有两个比较少用的模式 : "--stats"和"--print-param"。
由于前文对innobackupex的介绍非常详细 , xtrabackup在功能实现上和它是一样的。所以下面将简单介绍。
7.1 xtrabackup实现全备
备份过程
和
innobackupex备份过程不同的是 ,xtrabackup的备份路径是由"--target-dir"选项严格指定的 , 如果指定的目录不存在 , 它备份的时候不会在target-dir目录中再创建时间戳子目录。[root@xuexi data]# xtrabackup --backup --user=root --password=123456 --datadir=/mydata/data --target-dir=/bakdir/fullback [root@xuexi data]# ls /bakdir/fullback backup-my.cnf ibdata1 Performance secure_dir xtrabackup_binlog_info xtrabackup_info backuptest mysql performance_schema world xtrabackup_checkpoints xtrabackup_logfile准备过程
xtrabackup --prepare --target-dir=/bakdir/fullback恢复过程
xtrabackup自身不能恢复 , 只能通过拷贝备份集的方式来恢复。例如使用rsync或者cp等。另外 , 恢复时也一样要求
MySQL是stop状态 ,datadir是空目录。并且拷贝完成后要修改datadir中文件的所有者和属组为mysql用户和组。service mysqld stop rm -rf /mydata/data/* rsync -azP /bakdir/fullback/* /mydata/data chown -R mysql.mysql /mydata/data/*另外可以通过
--copy-back参数实现恢复功能xtrabackup --copy-back --target-dir=/tmp/mariadb/backup/
7.2 xtrabackup实现增备
首先进行全备
xtrabackup --backup --user=root --password=123456 --datadir=/mydata/data --target-dir=/bakdir/base_full进行第一次增备
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak1 --incremental-basedir=/bakdir/base_full --datadir=/mydata/data/同样也可以在增备时使用"
--incremental-lsn"来指定从哪个lsn开始增量备份 , 这和innobackupex是一样的。进行第二次增备
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak2 --incremental-basedir=/bakdir/incr_bak1 --datadir=/mydata/data/准备过程
准备过程和
innobackupex是一样的 , 使用"--apply-log-only"来直线向前地应用redo log, 同样 , 在最后一个增备集的准备过程中不能使用"--apply-log-only"选项。xtrabackup --prepare --apply-log-only --target-dir=/bakdir/base_full xtrabackup --prepare --apply-log-only --target-dir=/bakdir/base_full --incremental-dir=/bakdir/incr_bak1 xtrabackup --prepare --target-dir=/bakdir/base_full --incremental-dir=/bakdir/incr_bak2恢复阶段
恢复阶段即拷贝阶段 , 和前面全备的恢复阶段是一样的 , 要求
MySQL停止运行 ,datadir是空目录 , 拷贝全备目录到datadir, 修改datadir的所有者和属组。
7.3 xtrabackup实现部分备份
xtrabackup部分备份和innobackupex不太一样 , innobackupex的部分备份实质上是在已经备份好的备份集上导出导入表 , 而xtrabackup直接在备份过程中筛选要备份的目标 , 它不建立在已有的备份集上。
备份过程
xtrabackup使用"--tables"选项对应innobackupex的"--include"选项 , 它们是一样的 , 都是正则匹配完整对象引用名称。使用"
--tables-file"选项指定枚举要备份表的列表 , 每行一个表 , 表名需要使用完整对象引用名称。和innobackupex一样的。使用"
--databases"和"--databases-file"指定要单独备份的数据库或表 , 后者可以枚举出要备份的列表。这两个选项不能使用通配符和正则匹配。
例如 :
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/part_bak1 --datadir=/mydata/data/ --tables="^back*[.]num_*"准备过程
xtrabackup的部分备份的准备要比innobackupex方便的多 , 直接对备份集进行"--prepare"即可。xtrabackup --prepare --target-dir=/bakdir/part_bak1
8. 备份脚本
全量备份脚本
[root@centos7 ~]# cat fullback_mysql.sh #!/bin/bash user=root passwd=centos DATE=`date +"%Y/%W/%w/%F-%T"` # 定义备份目录日期,创建的目录有年、月、周分别的目录及全量日期的目录 fullback=/backup/full/$DATE # 定义全量备份目录 [ ! -d $fullback ] && mkdir $fullback -p # 判断目录不存在为真,为真就创建目录 xtrabackup --user=$user --password=$passwd --backup --target-dir=$fullback &> /tmp/mysql # 进行全量备份,并将备份信息指定到文件中 egrep ".* Backup created in directory.*" /tmp/mysql >> /backup/full/complete.info # 过滤出当前创建的目录路径,方便在增量时可以确定上一级全备份的目录。 scp -rp $fullback 192.168.7.101:/fullback # 将备份的全量数据传到另外一个主机上。 find $fullback/ -ctime +30 -type d -exec rm {} \; # 删除超过30天的备份数据信息。增量备份脚本
[root@centos7 ~]# cat incr.sh #!/bin/bash user=root passwd=centos DATE=`date +"%Y/%W/%w/%F-%T"` inc1back=/backup/inc1/$DATE BASE_DIR=$(tail -1 /backup/full/complete.info | cut -d\' -f2) # 基于全量备份的基础上,导入的complete.info有全量备份的目录路径信息,将前面的全量备份目录提取出来。 [ ! -d $inc1back ] && mkdir $inc1back -p # 判断目录不存在为真,就创建新增目录 xtrabackup --user=$user --password=$passwd --backup --target-dir=$inc1back --incremental-basedir=$BASE_DIR # 指定上一个全量备份目录的路径。 xtrabackup --user=$user --password=$passwd --prepare --apply-log-only --target-dir=$BASE_DIR # 整合全量备份目录 xtrabackup --user=$user --password=$passwd --prepare --target-dir=$BASE_DIR --incremental-dir=$inc1back # 基于全量备份目录进行整合增量备份目录 scp -rp $inc1back 192.168.7.101:/inc1back # 备份到远程主机的目录下 find $inc1back/ -ctime +30 -type d -exec rm {} \; # 删除30天以前的数据
9. mariabackup
Mariabackup 是从 Percona XtraBackup 2.3.8 版分叉出来的,支持 XtraBackup 的所有功能,如热备份,并且增加了对 MariaDB 10.1 及以上版本特有的新功能的支持,例如静态数据加密和 InnoDB 页面压缩
安装 Mariabackup
在 Linux 系统中,可以通过包管理器安装 Mariabackup。例如,在 Debian/Ubuntu 系统中,可以使用以下命令安装:
sudo apt install mariadb-backup在 RHEL/CentOS 系统中,可以使用以下命令安装:
sudo yum install mariadb-backupmariabackup的用法与xtrabackup一致,使用方法也基本相同
完整备份和恢复
备份过程
要进行完整备份,需要运行带有
--backup选项的Mariabackup,并使用--target-dir选项指定备份目录的位置。例如:mariabackup --backup --target-dir=/tmp/mariadb/backup/ --user=backupuser --password=backup123如果需要创建压缩备份,可以使用
--stream选项:mariabackup --user=backupuser --password=backup123 --backup --stream=xbstream | gzip > backup_22_03_2020.gz准备过程
由于备份过程中的数据文件在不同时间被复制,需要使用
--prepare选项来准备备份,使其一致:mariabackup --prepare --target-dir=/tmp/mariadb/backup/恢复过程
在恢复之前,需要确保
MariaDB进程已停止且数据目录为空。然后使用--copy-back或--move-back选项之一来恢复备份:mariabackup --copy-back --target-dir=/tmp/mariadb/backup/恢复后,可能需要更改数据目录的权限,以匹配
MariaDB服务器的用户和组,通常为mysql:chown -R mysql:mysql /var/lib/mysql/然后启动
MariaDB服务器。增量备份和恢复
备份过程
在创建增量备份之前,必须已经创建了数据库的完整备份。增量备份命令如下:
mariabackup --backup --target-dir=/tmp/mariadb/backup/increment/ --incremental-basedir=/tmp/mariadb/backup/ --user=backupuser --password=backup123准备过程
对于每个增量备份,需要先进行
--prepare,然后将其合并到已恢复的全量备份数据中:mariabackup --prepare --apply-log-only --target-dir=/tmp/mariadb/backup/ --incremental-dir=/tmp/mariadb/backup/increment/恢复过程
一旦完整备份与所有增量更改同步,就可以像恢复完整备份一样恢复它。数据恢复后,不要忘记更改数据目录的权限。
参考链接
MariaDB/MySQL备份和恢复(三) : xtrabackup用法和原理详述 - 骏马金龙 - 博客园