MariaDB/MySQL备份恢复系列:
备份和恢复(一):mysqldump工具用法详述
备份和恢复(二):导入、导出表数据
备份和恢复(三):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
1.安装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/xtrabackup
- xbcloud和xbcloud_osenv是xtrabackup新的高级特性:云备份;
- xbcrypt也是新的特性,加密备份集;
- xbstream是xtrabackup的流数据功能,通过流数据功能,可将备份内容打包并传给管道后的压缩工具进行压缩;
- xtrabackup是主程序;
- innobackupex在以前是一个perl脚本,会调用xtrabackup这个二进制工具,从xtrabackup 2.3开始,该工具使用C语言进行了重写,当前它是xtabackup二进制工具的一个软连接,但是实际的使用方法却不同,并且在以后的版本中会删除该工具。
在本文中,会分别对两个主程序innobackupex和xtrabackup的备份恢复方法进行详细的说明,还会在说明过程中尽可能的解释它们是如何工作的,另外还会介绍它们的一些特殊功能的选项,如流备份选项。
2.备份锁
一篇不错的介绍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种语法:
1
2
3
|
lock tables for backup # 申请备份表锁 lock binlog for backup # 申请二进制日志锁 unlock binlog # 释放二进制日志锁 |
备份表锁在全局范围内只对非innodb表加锁,所以持有该锁后无法修改非innodb表,但却不影响innodb表的DML。当然,因为是全局锁,所以也会阻塞DDL操作。
二进制日志锁在全局范围内锁定二进制日志,所以会阻塞其他会话修改二进制日志。这样可以保证能够获取到二进制日志中一致性的位置坐标。
3.xtrabackup备份原理说明
不管是使用innobackupex还是xtrabackup工具进行备份和恢复,都有3个步骤:备份(backup)、准备(prepare)、恢复(copy back)。
注意,xtrabackup备份过程中,先备份innodb表,再备份非innodb表。
3.1 备份过程(backup阶段)
(1).在启动xtrabackup时记下LSN并将redo log拷贝到备份目标目录下的xtrabackup_logfile文件中。由于拷贝需要一定时间,如果在拷贝时间段内有日志写入,将导致拷贝的日志和MySQL的redo log不一致,所以xtrabackup还有一个后台进程监控着mysql的redo log,每秒监控一次,当MySQL的redo log有变化,该监控进程会立即将变化的内容写入到xtrabackup_logfile文件,这样就能保证拷贝走的redo log中记录了一切变化。但是这也是有风险的,因为redo是轮训式循环写入的,如果某一时刻有非常大量的日志写到redo log中,使得还没开始复制的日志就被新日志覆盖了,这样会日志丢失,并报错。
(2).拷贝完初始版的redo log后,xtrabackup开始拷贝innodb表的数据文件(即表空间文件.ibd文件和ibdata1)。注意,此时不拷贝innodb的frm文件。
(3).当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表的真正热备。
(4).当获取到非innodb表的锁以后,开始拷贝非innodb表的数据和.frm文件。当这些拷贝完成之后,继续拷贝其他存储引擎类型的文件。(实际上,拷贝非innodb表的数据是在获取backup locks(如果支持)后自动进行的,它们属于同一个过程)
(5).当拷贝阶段完成后,就到了备份的收尾阶段。包括获取二进制日志中一致性位置的坐标点、结束redo log的监控和拷贝、释放锁等。
对于不支持backup lock的版本,收尾阶段的过程是这样的:获取二进制日志的一致性坐标点、结束redo log的监控和拷贝、释放锁。
对于支持backup lock的版本,收尾阶段的过程是这样的:先通过lock binlog for bakcup来获取二进制日志锁,然后结束redo log的监控和拷贝,再unlock tables释放表锁,随后获取二进制日志的一致性位置坐标点,最后unlock binlog释放二进制日志锁。
(6).如果一切都OK,xtrabackup将以状态码0退出。
所以,对是否支持backup lock的版本,xtrabackup备份的时的行为是不一样的。
backup阶段的过程具体如下图所示:
FTWRL:flush table with read lock;
3.2 准备过程(prepare阶段)
由于备份的时候拷贝走的数据文件可能是不一致的,比如监控着MySQL的redo log中在拷贝过程完成后又新的事务提交了,而拷贝走的数据是未提交状态的,那么就需要对该事务前滚;如果监控到的日志中有事务未提交,那么该事务就需要回滚。
但是如果只备份了myisam表或其他非事务表数据,因为备份阶段直接锁定了这些表,所以不会有不一致的状态。
xtrabackup有一个"准备"的阶段。这个阶段的实质就是对备份的innodb数据应用redo log,该回滚的回滚,该前滚的前滚,最终保证xtrabackup_logfile中记录的redo log已经全部应用到备份数据页上,并且实现了一致性。当应用结束后,会重写"xtrabackup_logfile"再次保证该redo log和备份的数据是对应的。
准备过程不需要连接数据库,该过程可以在任意装了xtrabackup软件的机器上进行,之所能实现是因为xtrabackup软件的内部嵌入了一个简化的innodb存储引擎,可以通过它完成日志的应用。
3.3 恢复过程(copy back阶段)
xtrabackup的恢复过程实质是将备份的数据文件和结构定义等文件拷贝回MySQL的datadir。同样可以拷贝到任意机器上。
要求恢复之前MySQL必须是停止运行状态,且datadir是空目录,除非恢复的操作是导入表的操作。具体见后文对应的内容。
4.准备实验环境
创建测试数据库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);
5.innobackupex工具
5.1 innobackupex实现全备份和恢复的过程
(1). 全备
除了给定连接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中记录的是当前使用的二进制日志文件。
1 2
[root@xuexi bakdir]# cat 2017-04-02_07-09-47/xtrabackup_binlog_info mysql-bin.000001 120
-
xtrabackup_checkpoints中记录了备份的类型是全备还是增备,还有备份的起始、终止LSN号。
1 2 3 4 5 6 7
[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 = 0
-
xtrabackup_info中记录的是备份过程中的一些信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
[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 = N
-
xtrabackup_logfile是复制和监控后写的redo日志。该日志是备份后下一个操作"准备"的关键。只有通过它才能实现数据一致性。
(2). 全备的准备过程
在全备份完成之后,备份的数据中如果有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,值越大准备的过程越快。当然,将该值加大的前提是服务器内存够用。
(3). 全备份的恢复过程
恢复的阶段就是向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数据库中的数据是否完整。
5.2 innobackupex实现增量备份和恢复的过程
增量备份依赖于全备份。xtrabackup实现增量备份的原理是通过比较全备份的终点LSN和当前的LSN,增备时将从终点LSN开始一直备份到当前的LSN。在备份时也有redo log的监控线程,对于增备过程中导致LSN增长的操作也会写入到日志中。
增备的实现依赖于LSN,所以只对innodb有效,对myisam表使用增备时,背后进行的是全备。
(1). 要进行增备,首先要有全备文件。这里重新进行一次全备。
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
注意:要实现增备,这一次的全备一定不能进行"准备"操作,原因稍后给出。
(2). 进行第一次增备。
假设对示例数据可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进行增备是一样的。
(3). 进行第二次增备。
假设在第一次增备后,向上次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
(4). 增备的准备过程
增备的准备过程和全备的准备过程有点不一样,不到最后恢复的时候不能进行任何"准备"过程。
增备过程中的每一次备份行为都会监控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
如果不小心整合的顺序错误了,那么整合的备份集将是无效的,需要重新整合。
(5). 增备的恢复过程
因为整合结束后就等价于一个全备集,所以可以直接进行恢复。
恢复过程同样需要保证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 | +----------+
5.3 innobackupex实现导出和导入单张表的过程
默认情况下,InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植,即便使用了innodb_file_per_table选项。而使用Xtrabackup工具可以实现此种功能,不过只能"导出"具有.ibd文件的表,也就是说导出表的mysql服务器启用了innodb_file_per_table选项,而且要导出的表还是在启用该选项之后才创建的。
导入表的是,要求导入表的服务器版本是MySQL 5.6+,且启用了innodb_file_per_table选项。
(1). 导出表
导出表是在"准备"的过程中进行的,不是在备份的时候导出。对于一个已经备份好的备份集,使用"--apply-log"和"--export"选项即可导出备份集中的表。
假如以全备份集/bakdir/2017-04-02_17-41-38为例,要导出其中的表。
innobackupex --apply-log --export /bakdir/2017-04-02_17-41-38
在导出过程中,会看到如下信息:
1
2
|
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"文件完全可以不需要,但是如果有该文件的话,会进行架构验证。
(2). 导入表
要在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;
5.4 innobackupex实现部分备份和恢复的过程
xtrabackup支持部分备份,意味着可以指定备份哪个数据库或者哪个表。
部分备份只有一点需要注意:在恢复的时候不要通过"--copy-back"的方式拷贝回datadir,而是应该使用导入表的方式。尽管使用拷贝的方式有时候是可行的,但是很多情况下会出现数据库不一致的状态。
(1). 备份
创建部分备份有三种方式:
- 通过"--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
(2). 部分备份的准备和恢复过程
部分备份的准备和恢复过程分别是导出表和导入表的过程。见上文。
5.5 innobackupex实现定时点恢复
xtrabackup本身无法实现定时点恢复,只能通过恢复备份后通过二进制日志实现。实现方法和一般定时点恢复是一样的。见:二进制日志定点还原数据库。
5.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。
5.7 加速备份
当备份到本地的时候,可以使用"--rsync"选项,该选项用于在flush tables with read lock后调用rsync替代cp进程复制非Innodb数据和.frm文件,加快复制速度。
但要注意,因为支持备份锁的版本在获取到backup locks的时候会自动复制非Innodb数据和.frm文件,所以"--rsync"选项是无效的。
另外,该选项不能和"--stream"选项和"--remote-host"选项同时使用。
6.xtrabackup工具
xtrabackup工具是C语言编写的工具,在innobackupex使用C重写之后,innobackupex是该工具的一个软链接。但是它不能实现innobackupex的所有功能,例如xtrabackup工具没有恢复功能,而innobackupex有"--copy-back"选项来恢复。
xtrabackup工具有两种常用运行模式:"--backup"和"--prepare"。还有两个比较少用的模式:"--stats"和"--print-param"。
由于前文对innobackupex的介绍非常详细,xtrabackup在功能实现上和它是一样的。所以下面将简单介绍。
6.1 xtrabackup实现全备
(1).备份过程
和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
(2).准备过程
xtrabackup --prepare --target-dir=/bakdir/fullback
(3).恢复过程
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/*
6.2 xtrabackup实现增备
(1).首先进行全备
xtrabackup --backup --user=root --password=123456 --datadir=/mydata/data --target-dir=/bakdir/base_full
(2).进行第一次增备
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak1 --incremental-basedir=/bakdir/base_full --datadir=/mydata/data/
同样也可以在增备时使用"--incremental-lsn"来指定从哪个lsn开始增量备份,这和innobackupex是一样的。
(3).进行第二次增备
xtrabackup --backup --user=root --password=123456 --target-dir=/bakdir/incr_bak2 --incremental-basedir=/bakdir/incr_bak1 --datadir=/mydata/data/
(4).准备过程
准备过程和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
(5).恢复阶段
恢复阶段即拷贝阶段,和前面全备的恢复阶段是一样的,要求MySQL停止运行,datadir是空目录,拷贝全备目录到datadir,修改datadir的所有者和属组。
6.3 xtrabackup实现部分备份
xtrabackup部分备份和innobackupex不太一样,innobackupex的部分备份实质上是在已经备份好的备份集上导出导入表,而xtrabackup直接在备份过程中筛选要备份的目标,它不建立在已有的备份集上。
(1).备份过程
- 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_*"
(2).准备过程
xtrabackup的部分备份的准备要比innobackupex方便的多,直接对备份集进行"--prepare"即可。
xtrabackup --prepare --target-dir=/bakdir/part_bak1