一.XtraBackup简介

    在实际环境中增量备份是使用较多的,percona-xtrabackup就是为实现增量备份而生,因此我们需要使用percona-xtrabackup。


    Xtrabackup是percona公司的开源项目,用以实现类似innodb官方的热备份工具InnoDB Hot Backup的功能,能够非常快速地备份与恢复mysql数据库。

安装XtraBackup后,其实会有几个工具:

    innobackupex:这个是其实是下面三个工具的一个perl脚本封装,可以备份MyISAM, InnoDB, XtraDB表。但在处理Myisam时需要加一个读锁。

    xtrabackup:一个由C编译而来的二进制文件,只能备份InnoDB和XtraDB数据。

    xbcrypt:用来加密或解密备份的数据。

    xbstream:用来解压或压缩xbstream格式的压缩文件。

建议使用perl封装的innobackupex来作数据库备份,因为比较容易使用。所以下面只介绍innobackupex的使用。


XtraBackup优势 :

1、无需停止数据库进行InnoDB热备

2、增量备份MySQL

3、流压缩到传输到其它服务器

4、能比较容易地创建主从同步

5、备份MySQL时不会增大服务器负载

Xtrabackup的特性是针对大数据进行备份恢复使用,数据库大小一般在G以上或10G以上,对于数据量小的Mysql库完全可以使用mysqldump来解决,备份和恢复速度快而且操作简便快捷。


二.软件的获取和文档的获取

http://www.percona.com/downloads

http://www.percona.com/doc/percona-xtrabackup/2.2/


注意:

我的实验使用的软件和系统:
操作系统版本为:
CentOS 6.6 64bit
percona-xtrabackup版本为:
percona-xtrabackup-2.2.3-4982.el6.x86_64.rpm
数据库软件为:
mariadb-10.0.13.tar.gz


三.软件的安装和innobackupex命令的介绍

1.安装percona-xtrabackup

[root@node1 ~]# yum localinstall -y percona-xtrabackup-2.2.3-4982.el6.x86_64.rpm

注:安装时依赖了perl-DBD-MySQL-4.013-3.el6.x86_64.rpm 这个包


2.innobackupex使用方法

完整的选项使用请执行innobackupex –help,这里只介绍使用常用的选项进行完整备份及增量备份和还原。

innobackupex Options 这里只对常用参数进行描述

–defaults-file            #数据库的配置文件路径,感觉本地备份不写也可以,远程没测试过。

–apply-log                #准备在一个备份上启动mysql服务。

–copy-back                #从备份目录拷贝数据,索引,日志到my.cnf文件里规定的初始位置。

–no-timestamp             #创建备份时不自动生成时间目录,可以自定义备份目录名例如: /backups/mysql/base

–databases                #用于指定要备份的数据库, 多个库文件使用方法: “database1 database2″

–incremental              #在全备份的基础上进行增量备份,后跟增量备份存贮目录路径

–incremental-basedir=DIRECTORY         #增量备份所需要的全备份路径目录或上次做增量备份的目录路径

–incremental-dir=DIRECTORY             #增量备份存贮的目录路径

–redo-only                 #用于准备增量备份内容把数据合并到全备份目录,配合–incremental-dir 增量备份目录使用。

–force-non-empty-directories           #如果是特定库备份还原,不需要删掉整个mysql目录,只是特定库的及相关文件就可以,还原时加上此参数就不会报错。



四.完全备份和恢复数据库的实现

1.完全备份的实现:

使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中。

完整备份数据库:

[root@node1 ~]# innobackupex --user=root --password=oracle --defaults-file=/etc/mysql/my.cnf /backup

如果执行正确,其最后输出的几行信息通常如下:

innobackupex: Backup created in directory '/backup/2015-01-22_21-45-17'
innobackupex: MySQL binlog position: filename 'mysql-bin.000010', position 326
150122 21:45:20  innobackupex: Connection to database server closed
150122 21:45:20  innobackupex: completed OK!


查看备份的目录:

[root@node1 ~]# ls /backup/
2015-01-22_21-45-17
[root@node1 ~]# ls /backup/2015-01-22_21-45-17/
backup-my.cnf  hellodb  ibdata1  mysql  performance_schema  test  xtrabackup_binlog_info  xtrabackup_checkpoints  xtrabackup_info  xtrabackup_logfile

在备份的同时,innobackupex还会在备份目录中创建如下文件:

(1)xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

(3)xtrabackup_binlog_pos_innodb —— 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf —— 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。


2.停止数据库服务器:

#service mysqld stop


3.模拟数据库故障,我们删除数据库数据文件:

[root@node1 ~]# rm -rf /mydata/data/*


4.一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:

# innobackupex --apply-log  /path/to/BACKUP-DIR
如果执行正确,其最后输出的几行信息通常如下:
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 1761814
150122 21:49:43  innobackupex: completed OK!

在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。

实际操作:

[root@node1 ~]# innobackupex --apply-log /backup/2015-01-22_21-45-17 --user=root --password=oracle


5.从一个完全备份中恢复数据 

注意:恢复不用启动MySQL

    innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。

# innobackupex --copy-back  /path/to/BACKUP-DIR
如果执行正确,其输出信息的最后几行通常如下:
innobackupex: Starting to copy InnoDB log files
innobackupex: in '/backup/2015-01-22_21-45-17'
innobackupex: back to original InnoDB log directory '/mydata/data'
innobackupex: Copying '/backup/2015-01-22_21-45-17/ib_logfile1' to '/mydata/data/ib_logfile1'
innobackupex: Copying '/backup/2015-01-22_21-45-17/ib_logfile0' to '/mydata/data/ib_logfile0'
innobackupex: Finished copying back files.
150122 21:54:53  innobackupex: completed OK!


实际操作:

[root@node1 ~]# innobackupex --copy-back /backup/2015-01-22_21-45-17


6.请确保如上信息的最行一行出现“innobackupex: completed OK!”。

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:

# chown -R  mysql:mysql  /mydata/data/


实际操作:

[root@node1 ~]# ls /mydata/data/ -l
total 110616
drwxr-xr-x 2 root root     4096 Jan 22 21:54 hellodb
-rw-r--r-- 1 root root 12582912 Jan 22 21:54 ibdata1
-rw-r--r-- 1 root root 50331648 Jan 22 21:54 ib_logfile0
-rw-r--r-- 1 root root 50331648 Jan 22 21:54 ib_logfile1
drwxr-xr-x 2 root root     4096 Jan 22 21:54 mysql
drwxr-xr-x 2 root root     4096 Jan 22 21:54 performance_schema
drwxr-xr-x 2 root root     4096 Jan 22 21:54 test
-rw-r--r-- 1 root root       26 Jan 22 21:54 xtrabackup_binlog_pos_innodb
-rw-r--r-- 1 root root      593 Jan 22 21:54 xtrabackup_info
[root@node1 ~]# chown -R mysql:mysql /mydata/data/


7.启动mysqld服务:

[root@node1 ~]# service mysqld start
Starting MySQL..                                           [  OK  ]
自动生成二进制日志;
[root@node1 ~]# ls /mydata/data/
aria_log.00000001  ib_logfile1        node1.stu31.com.pid
aria_log_control   multi-master.info  performance_schema
hellodb            mysql              test
ibdata1            mysql-bin.000001   xtrabackup_binlog_pos_innodb
ib_logfile0        mysql-bin.index    xtrabackup_info


注意:恢复完成后需要做完全备份,所有的增量依靠此次的完全备份实现;



二.单个数据库备份的实现

1.我们备份hellodb这个数据库

[root@node1 ~]# innobackupex  --user=root  --password=oracle  --defaults-file=/etc/mysql/my.cnf  --databases='hellodb'   /backup
信息略……
innobackupex: Backup created in directory '/backup/2015-01-22_22-05-35'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 312
150122 22:05:38  innobackupex: Connection to database server closed
150122 22:05:38  innobackupex: completed OK!

这样就会在/backup生成一个带时间的目录,如果不需要带时间,可以使用选项–no-timestamp。


2.如果想备份成压缩文件,可以使用如下语句:

[root@node1 ~]# innobackupex --user=root --password=oracle --defaults-file=/etc/mysql/my.cnf --databases='hellodb' --no-timestamp --stream=tar ./ | gzip - > /backup/hellodb.tar.gz
信息略……
innobackupex: Backup created in directory '/root'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 540
150122 22:09:22  innobackupex: Connection to database server closed
innobackupex: You must use -i (--ignore-zeros) option for extraction of the tar stream.
150122 22:09:22  innobackupex: completed OK!


查看备份的压缩文件:

[root@node1 ~]# ls /backup/
2015-01-22_21-45-17  2015-01-22_22-05-35  hellodb.tar.gz


3.模拟数据库hellodb故障,hellodb被删除;

[root@node1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 7
Server version: 10.0.13-MariaDB-log Source distribution
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> drop database hellodb;
Query OK, 9 rows affected (1.83 sec)
MariaDB [(none)]> show schemas;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)
MariaDB [(none)]> \q
Bye

4.还原数据库hellodb的备份;

停止数据库服务器:
[root@node1 ~]# service mysqld stop
Shutting down MySQL...                                     [  OK  ]
进行数据库恢复前的准备工作:
[root@node1 ~]# innobackupex --apply-log /backup/2015-01-22_22-05-35
信息略……
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 1762326
150122 22:19:45  innobackupex: completed OK!


实现数据库hellodb的恢复:

[root@node1 ~]# innobackupex --copy-back --defaults-file=/etc/mysql/my.cnf  /backup/2015-01-22_22-05-35


至此,单个数据库备份恢复实验就完成了。



四.数据库的增量备份和恢复实现


1.增量备份介绍

每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。

要实现第一次增量备份,可以使用下面的命令进行:

# innobackupex --incremental /backup --incremental-basedir=BASEDIR

其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。


注意:增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。


“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:

(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。

(2)基于所有的备份将未提交的事务进行“回滚”。

于是,操作就变成了:

# innobackupex --apply-log --redo-only BASE-DIR

接着执行:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

而后是第二个增量:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,


每一次都要执行如上操作;



2.实现前提:如果我们是进行过恢复数据库后,需要实现增量备份,就需要在恢复数据库后进行一次完全备份,因为增量备份是需要基于数据库的完全备份实现;不能依赖于此前的完全备份

[root@node1 ~]# innobackupex --user=root --password=oracle /backup
[root@node1 ~]# ls /backup/2015-01-23_19-45-33/
backup-my.cnf  performance_schema      xtrabackup_info
hellodb        test                    xtrabackup_logfile
ibdata1        xtrabackup_binlog_info
mysql          xtrabackup_checkpoints
查看一下checkpoint文件:
[root@node1 ~]# cat /backup/2015-01-23_19-45-33/xtrabackup_checkpoints 
backup_type = full-backuped
from_lsn = 0    #起始序列号
to_lsn = 1899788       
last_lsn = 1899788   #终止序列号
compact = 0


我们后续的增量备份操作就是基于上面的完全备份操作了;


3.为了实现增量备份,我们对数据库进行一些更改。

[root@node1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.0.13-MariaDB-log Source distribution
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use hellodb;
Database changed
MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| myisam_table      |
| scores            |
| students          |
| tb1               |
| teachers          |
| toc               |
| v1                |
+-------------------+
10 rows in set (0.00 sec)
#删除表myisam_table
MariaDB [hellodb]> drop table  myisam_table;
Query OK, 0 rows affected (0.00 sec)
#查询表tb1的内容
MariaDB [hellodb]> select * from tb1;
+------+
| id   |
+------+
|    1 |
|    2 |
|   22 |
|    9 |
|   20 |
+------+
5 rows in set (0.03 sec)
#删除表tb1的其中一个内容;
MariaDB [hellodb]> delete from tb1 where id=22;
Query OK, 1 row affected (0.02 sec)
#可以看出内容删除了;
MariaDB [hellodb]> select * from tb1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    9 |
|   20 |
+------+
4 rows in set (0.00 sec)
MariaDB [hellodb]> \q
Bye

修改完成,下面就开始进行增量备份;


4.增量备份的操作:

以上次完全备份的终止lsn号开始向后备份修改的内容;

[root@node1 ~]# innobackupex --incremental /backup/ --incremental-basedir=/backup/2015-01-23_19-45-33/


注意:如果存储引擎是Innodb就会实现增量备份,如果存储引擎是MyISAM就会实现完全备份;因为innobackupex这个指令不支持对MyISAM存储引擎的数据库做增量备份;

查看增量备份文件的lsn信息:

[root@node1 ~]# ls /backup/
2015-01-23_19-45-33  2015-01-23_19-57-12
[root@node1 ~]# cat /backup/2015-01-23_19-57-12/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1899788
to_lsn = 1900220
last_lsn = 1900220
compact = 0

可以看出是从上次完全备份的lsn号后开始备份的;


5.为了后续恢复更实际,我们再次对数据库进行一次更改;

[root@node1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.0.13-MariaDB-log Source distribution
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use hellodb;
Database changed
#在hellodb数据库的tb1表中插入一些新数据
MariaDB [hellodb]> insert into tb1 values (1000),(9999);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
MariaDB [hellodb]> \q
Bye


6.进行第二次增量备份;

此次增量备份是针对第一次增量备份实现备份;

[root@node1 ~]# innobackupex --incremental /backup/ --incremental-basedir=/backup/2015-01-23_19-57-12/
查看备份文件的LSN序列号文件:
[root@node1 ~]# ls /backup/
2015-01-23_19-45-33  2015-01-23_19-57-12  2015-01-23_20-04-56
[root@node1 ~]# cat /backup/2015-01-23_20-04-56/xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 1900220
to_lsn = 1902763
last_lsn = 1902763
compact = 0


7.进行数据库修改操作后模拟数据库损坏操作;

修改数据库操作:

[root@node1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 12
Server version: 10.0.13-MariaDB-log Source distribution
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use hellodb;
Database changed
MariaDB [hellodb]> insert into tb1 values (888888);
Query OK, 1 row affected (0.04 sec)
MariaDB [hellodb]> \q
Bye


我们在生产环境中一定要将数据库生成的二进制日志文件和数据文件分开存放,现在我们模拟数据库损坏是数据损坏而非二进制日志文件损坏;

停止数据库服务器:

[root@node1 ~]# service mysqld stop
Shutting down MySQL..                                      [  OK  ]

备份二进制日志文件需要查看我们增量备份中的xtrabackup_binlog_info 中记录的时间点:

[root@node1 ~]# cat /backup/2015-01-23_20-04-56/xtrabackup_binlog_info 
mysql-bin.000010        1034

备份好二进制日志文件:

[root@node1 ~]# mysqlbinlog --start-position=1034 /mydata/data/mysql-bin.000010 > /tmp/timepoint.sql


模拟数据库损坏,我们将数据库的数据全部删除:

[root@node1 ~]# rm -rf /mydata/data/*

下面就是恢复数据库阶段;



8.恢复数据库的准备阶段;

准备阶段就是按时间顺序将增量备份合并到完全备份中;需要注意的是我们做准备工作时仅能提交不能回滚;

完全备份准备:
[root@node1 ~]# innobackupex --apply-log --redo-only /backup/2015-01-23_19-45-33/
第一次增量备份合并准备:
[root@node1 ~]# innobackupex --apply-log --redo-only /backup/2015-01-23_19-45-33/ --incremental-dir=/backup/2015-01-23_19-57-12/
第二次增量备份合并准备:
[root@node1 ~]# innobackupex --apply-log --redo-only /backup/2015-01-23_19-45-33/ --incremental-dir=/backup/2015-01-23_20-04-56/


9.实现数据库的恢复操作

[root@node1 ~]# innobackupex --copy-back /backup/2015-01-23_19-45-33/
[root@node1 ~]# ls /mydata/data/
hellodb  ibdata1  mysql  performance_schema  test  xtrabackup_info


记得更改数据目录的属主属组:

[root@node1 ~]# chown -R mysql.mysql /mydata/data/


恢复完成后启动数据库服务器:

[root@node1 ~]# service mysqld start
Starting MySQL.                                            [  OK  ]


连入mysql数据库,查看数据:

[root@node1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 4
Server version: 10.0.13-MariaDB-log Source distribution
Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use hellodb;
Database changed
#查看表内容,我们插入的888888那条数据不存在,需要恢复;
MariaDB [hellodb]> select * from tb1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    9 |
|   20 |
| 1000 |
| 9999 |
+------+
6 rows in set (0.00 sec)
#关闭二进制日志记录;
MariaDB [hellodb]> set session sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
#恢复备份的二进制日志;
MariaDB [hellodb]> source /tmp/timepoint.sql;
Query OK, 0 rows affected (0.00 sec)
信息略……
#开启二进制日志记录;
MariaDB [hellodb]> set session sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
#数据恢复了;
MariaDB [hellodb]> select * from tb1;
+--------+
| id     |
+--------+
|      1 |
|      2 |
|      9 |
|     20 |
|   1000 |
|   9999 |
| 888888 |
+--------+
7 rows in set (0.00 sec)
MariaDB [hellodb]> \q
Bye

至此,基于percona-xtrabackup实现增量备份数据库操作就实现了;


注意:我们恢复完成后做的第一件事就是赶紧完全备份一次刚恢复的数据库;