MySQL备份工具Xtrabackup使用说明

一、Xtrabackup安装

安装依赖包

 yum install perl-Time-HiRes perl-DBI libev

安装RPM包

rpm -ihv percona-xtrabackup-2.4.4-Linux-x86_64.rpm

或安装二进制版

tar xvf percona-xtrabackup-2.4.4-Linux-x86_64.tar.gz
cp percona-xtrabackup-2.4.4-Linux-x86_64/bin/* /usr/local/bin/

软件包安装完后一共有4个可执行文件,如下:

ls percona-xtrabackup-2.4.4-Linux-x86_64/bin/
innobackupex 
xbcrypt
xbstream
xtrabackup

其中最主要的是innobackupex和xtrabackup,前者是一个perl脚本,后者是C/C++编译的二进制,复制到PATH路径下即可。

cp -fr percona-xtrabackup-2.4.4-Linux-x86_64/bin/* /usr/local/bin/

PS:注意,对于MySQL 5.7数据库需要percona-xtrabackup-2.4的版本才可以支持。

二、使用innobackupex做数据备份

完整备份加二进制日志做数据备份与恢复实例

实验环境

配置文件基本信息

cat /etc/my.cnf
[client]
user = root
password=redhat
port=3306
socket=/tmp/mysql.sock
 
[mysqld]
port=3306
datadir=/mydata
socket=/tmp/mysql.sock
Innodb_file_per_table = ON
#……….
service mysqld restart

需要的数据

mysql -uroot -predhat
mysql> reset master;
mysql> CREATE DATABASE aa;
mysql> USE aa
mysql> CREATE TABLE bb(id INT NOT NULL) ENGINE=innodb;
mysql> INSERT INTO bb(id) VALUE(1),(2),(3);

1)使用innobackupex完整备份数据(备份一个库)
备份选项说明:

--host :备份主机地址。

--port :备份主机端口。

--user :备份主机用户。

--password :备份主机密码。

--socket :备份主机的sock文件位置。

--databases=# :指定备份数据库(如果不指定就是备份全部数据库)。

--databases-exclude=# :排除指定名称的数据库,请注意,此选项的优先级高于–databases。

--defaults-file=[MY.CNF] :从给定配置文件读取默认选项,必须作为命令行上的第一个选项,必须是真实文件,它不能是一个象征性的链接。

--parallel=# :此选项指定在创建备份时同时复制多个数据文件的线程数,默认值为1(即没有并发传输)。

--no-timestamp :指定此选项,会直接把数据备份在指定备份文件中,不再创建时间戳的文件夹(比如:/backup/2017,会自动创建目录)。

--stream=name :将所有备份文件以指定格式流式传输到标准输出,目前支持的格式是xbstream和tar。

--no-lock :该选项表示关闭FTWRL的表锁,只有在所有表都是Innodb表并且不关心备份的binlog pos点,如果有任何DDL语句正在执行或者非InnoDB正在更新时(包括mysql库下的表),都不应该使用这个选项,后果是导致备份数据不一致,如果考虑备份因为获得锁失败,可以考虑–safe-slave-backup立刻停止复制线程。

--slave-info :备份从服务器时,此选项很有用。它打印主服务器的二进制日志位置,它还将该信息作为命令写入xtrabackup_slave_info文件。可以通过此备份来设置一个新从库。

--safe-slave-backup :该选项表示为保证一致性复制状态,这个选项停止SQL线程并且等到show status中的slave_open_temp_tables为0的时候开始备份,如果没有打开临时表,备份会立刻开始,否则SQL线程启动或者关闭知道没有打开的临时表。如果slave_open_temp_tables在–safe-slave-backup-timeount(默认300秒)秒之后不为0,从库SQL线程会在备份完成的时候重启。

备份成功会出现如下信息:

170622 11:31:26 Backup created in directory '/backup/2017-06-22_11-31-24'
MySQL binlog position: filename 'mysql-bin.000008', position '943304070'
170622 11:31:26 [00] Writing backup-my.cnf
170622 11:31:26 [00]        ...done
170622 11:31:26 [00] Writing xtrabackup_info
170622 11:31:26 [00]        ...done
xtrabackup: Transaction log of lsn (2769567364) to (2770244949) was copied.
170622 11:31:26 completed OK!

从信息中会发现备份被创建在’/backup/2017-06-22_11-31-24′

内部机制:在备份的时候innobackupex会调用xtrabackup来备份innodb表,并复制所有的表定义,其他引擎的表(MyISAM,MERGE,CSV,ARCHIVE)。同时还会备份触发器和数据库配置信息相关的文件,这些文件会被保存至一个以时间命令的目录中,这些文件会被保存至备份目录下一个以时间命令的目录中有如下文件:

[root@localhost ~]# ls /backup/2017-06-22_11-31-24/
aa  backup-my.cnf  ib_buffer_pool  ibdata1  xtrabackup_binlog_info  xtrabackup_checkpoints  xtrabackup_info  xtrabackup_logfile

aa:备份的数据库。

backup-my.cnf:备份命令用到的配置选项信息。

xtrabackup_checkpoints:记录了此次的备份类型(如完全或增量),备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息。每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN,LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的;xtrabackup也正是根据LSN进行增量备份。

xtrabackup_info:记录了此次备份相关信息,如备份命令,工具名称,服务器版本,备份开始时间,备份结束时间,备份锁时间,全备还是增备,LSN,备份格式,是否压缩,是否加密等信息。

xtrabackup_binlog_info:记录MySQL服务器备份时的binlog position。

xtrabackup_slave_info:如果在从库备份时指定了 --slave-info选项,则会创建此文件,并且会记录主库的binlog position。

另外,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

mysql> CREATE USER 'bkuser'@'localhost' IDENTIFIED BY 'redhat';
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bkpuser';
mysql> GRANT RELOAD,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';
mysql> FLUSH PRIVILEGES;

2)插入新数据

mysql> USE aa
mysql> INSERT INTO bb(id) VALUE(100);
mysql> INSERT INTO bb(id) VALUE(200);

3)删除数据库(模拟数据损坏)

mysql> DROP DATABASE aa;

4)使用Innobackupex预备(prepare)完全备份

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

$ innobackupex --apply-log /backup/2017-06-22_11-31-24

--use-memory=2G :指定预备阶段可使用的内容,内存多则速度快,默认为10MB。

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

xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 2770245198
170622 11:35:06 completed OK!

内部机制:读取备份文件夹中的配置文件,然后innobackupex重做已提交事务,回滚未提交事务,之后数据就被写到了备份的数据文件(innodb文件)中,并重建日志文件。这一步隐式调用了2次 xtrabackup --prepare ,跟多关于xtrabackup可以看之后的章节。

5)使用innobackupex还原完全备份

service mysqld stop
mv /mydata /mydata-back

mydata是我MySQL数据目录,做数据恢复时需要此目录不存在,还原的位子由my.cnf中的datadir决定,如果配置文件不是默认位置,需要使用 --defaults-file= 参数指定。

innobackupex --defaults-file=/etc/my.cnf --copy-back /backup/2017-06-22_11-31-24/
170622 11:36:45 [01] Copying ./ibtmp1 to /var/lib/mysql/ibtmp1
170622 11:36:46 [01]        ...done
170622 11:36:46 completed OK!

然后把原来的数据复制回来,注意不能覆盖现有的文件(如果是整个实例备份,那么就不需要复制数据了)。

cp -fr /mydata-back/* /mydata/
cp: overwrite `/mydata/ib_buffer_pool'? n
cp: overwrite `/mydata/ibdata1'? n
cp: overwrite `/mydata/ib_logfile0'? n
cp: overwrite `/mydata/ib_logfile1'? n
cp: overwrite `/mydata/xtrabackup_binlog_pos_innodb'? n
cp: overwrite `/mydata/xtrabackup_info'? n

然后赋予权限,重新启动。

[root@localhost ~]# chown -R mysql:mysql /mydata
[root@localhost ~]# service mysqld start
mysql> select * from aa.bb;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
+----+
3 rows in set (0.00 sec)

恢复完成后,mydata目录会自动存在,另外需要再把/mydata-back下的文件复制回来。

注:datadir必须是为空的, innobackupex --copy-back 不会覆盖已存在的文件,还要注意,还原时需要先关闭服务,如果服务是启动的,那么就不能还原到datadir。如果不指定 --database 就是所有数据库恢复。

6)利用二进制日志文件提取完整备份后改动的数据做即时点还原

1. 首先查看xtrabackup_binlog_info文件找到完整备份时记录下正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

cat /backup/2017-06-22_11-31-24/xtrabackup_binlog_info
mysql-bin.000001    535

2. 使用mysqlbinlog /mydata/mysql-bin.000002(实际中是最后一次操作失误的二进制文件)进行查看,找到最后一次失误操作的时间点,我这里是:

mysqlbinlog /mydata/mysql-bin.000001
# at 945
#151127 19:02:26 server id 1  end_log_pos 1031 CRC32 0x4643ebce        Query       thread_id=18   exec_time=0    error_code=0
SET TIMESTAMP=1448622146/*!*/;
drop database aa
# at 1031

3. 根据最后一次失误的时间点,使用Mysqlbinlog工具对二进制日志文件进行SQL命令提取

mysqlbinlog --start-position=535 --stop-position=945 /mydata/mysql-bin.000001 > /root/aaback.sql

7)关闭当前会话二进制日志记录功能,因为二进制日志不需要记录完整还原(以下操作只能对当前会话生效)

mysql> set sql_log_bin=0;
mysql> show master status;

8)还原二进制提取的数据(注意由于sql_log_bin=0只对当前会话生效,所以只能使用source进行还原)

Mysql> SOURCE /root/aaback.sql;
Mysql> SHOW master STATUS;
Mysql> SET sql_log_bin=1;
mysql> SELECT * FROM aa.bb;
+-----+
| id  |
+-----+
|   1 |
|   2 |
|   3 |
| 100 |
| 200 |
+-----+
5 ROWS IN SET (0.00 sec)

注:这里的mysql-bin.00001是完整备份后数据改动记录的第一个二进制日志文件,这个恢复时间就是完全备份中记录下来的文件,可以查看xtrabackup_binlog_info中有,这里的数据量小所以就一个二进制文件,恢复二进制日志时需要从xtrabackup_binlog_info文件中的记录开始到最后一次刷新所有的日志文件。另外对于二进制日志也需要有好的备份措施,毕竟数据是核心。

完整备份加增量备份做数据备份与恢复实例

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

增量备份呢是为了减少空间使用和备份的时间。增量备份的实现,依赖于innodb页上面的LSN(log sequence number),每次对数据库的修改都会导致LSN自增。每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现,复制指定LSN之后的所有数据页。

使用innobackupex前的准备(实验环境)

cat /etc/my.cnf
[client]
user = root
password=redhat
port=3306
socket=/tmp/mysql.sock
 
[mysqld]
port=3306
datadir=/mydata
socket=/tmp/mysql.sock
Innodb_file_per_table = ON
#……….
service mysqld restart
$ mysql -uroot -predhat
mysql> reset master;
mysql> create database aa;
mysql> use aa
mysql> create table bb(id INT NOT NULL) ENGINE=innodb;
mysql> insert into bb(id) value(1),(2),(3);

1)使用innobackupex做完整备份(备份全部数据)

mkdir /backup
$ innobackupex --user=root --password=redhat /backup

检查备份文件夹下的xtrabackup-checkpoints,会有一下信息:

cat /backup/2015-11-27_19-37-41/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 2094824
last_lsn = 2094824
compact = 0

2)增加数据

mysql> USE aa
mysql> INSERT INTO bb(id) VALUE(100);
mysql> INSERT INTO bb(id) VALUE(200);

3)使用innobackupex做第一次增量备份

mkdir /backup/one-incremental
$ innobackupex --incremental /backup/one-incremental --incremental-basedir=/backup/2015-11-27_19-37-41/

增量备份成功会出现如下:

innobackupex: Backup created in directory '/backup/one-incremental/2015-11-27_19-47-11'
innobackupex: MySQL binlog position: filename 'mysql-bin.000001', position 945
151127 19:47:19  innobackupex: Connection to database server closed
151127 19:47:19  innobackupex: completed OK!

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

然后查看xtrabackup-checkpoints:

cat /backup/one-incremental/2015-11-27_19-47-11/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 2094824
to_lsn = 2095386
last_lsn = 2095386
compact = 0

可以发现和全备不同的是,backup_type为incremental,from_lsn不为0。

4)增加数据

mysql> USE aa
mysql> INSERT INTO bb(id) VALUE(1000);
mysql> INSERT INTO bb(id) VALUE(2000);

5)使用innodbbackupex做第二次增量备份

$ innobackupex --incremental /backup/one-incremental --incremental-basedir=/backup/one-incremental/2015-11-27_19-47-11/

6)删除数据(模拟数据损坏)

$ service mysqld stop
$ mv /mydata /mydata-back

7)使用innodbbackupex预备(prepare)增量备份

预备增量备份需要2个步骤:

1. 需要先预备(prepare)完全备份,但是只重做已提交事务,不回滚未提交事务。然后增量应用到全备,也是只重做提交事务,不回滚未提交事务。

2. 最后一个增备回滚未提交事务(如果已经回滚了未提交事务,那么就无法再应用增量备份)。

注:在Mariadb 10.0上测试发现不加 --redo-only预备全备,然后使用 --redo-only应用增量备份,MySQL服务能够正常启动并且数据被成功还原。

于是操作就变成了,在完全备份上,使用 --redo-only只重做已提交事务,不回滚未提交事务:

$ innobackupex --apply-log --redo-only /backup/2015-11-27_19-37-41/
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 2094824
151127 20:05:45  innobackupex: completed OK!

应用第一次增量备份:

$ innobackupex --apply-log --redo-only /backup/2015-11-27_19-37-41/ --incremental-dir=/backup/one-incremental/2015-11-27_19-47-11/

输出结果,注意LSN的变化

xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 2095386

需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序,可以使用xtrabackup-checkpoints来确定顺序。

应用第二次增量备份:

$ innobackupex --apply-log /backup/2015-11-27_19-37-41/ --incremental-dir=/backup/one-incremental/2015-11-27_19-53-23/
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 2096662

注: --redo-only除了最后一个不用加之外,其他的增量应用都要加,最后一个应用的时候可以直接进入回滚未提交事务阶段。如果加了也没事儿,服务启动的时候会进入recovery过程,来回滚。

需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序,可以使用xtrabackup-checkpoints来确定顺序。

最后回滚未提交事务:

$ innobackupex --apply-log /backup/2015-11-27_19-37-41/

所以全备加增备整个恢复过程如下:

--apply-log --redo-only fullback
--apply-log --redo-only increment-first-1
--apply-log --redo-only increment-first-2
--apply-log increment-last
--apply-log fullback

8)从完全备份加增量备份中恢复数据

$ innobackupex --copy-back /backup/2015-11-27_19-37-41/
$ chown -R mysql:mysql /mydata
$ service mysqld start
$ mysql -uroot -predhat
mysql> select * from aa.bb;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|  100 |
|  200 |
| 1000 |
| 2000 |
+------+
7 rows in set (0.04 sec)

到此,完整备份和增量备份中的数据都已经恢复了,如果在最后二次增量备份之后还有改动的数据,那么就需要利用二进制日志做即时点还原了。如果需要利用二进制日志的话需要参考最后一个增量备份记录的二进制文件和位置进行还原。

三、Xtrabackup的其他功能

1)Xtrabackup的“流”及“备份压缩”功能

Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档或xbstream格式输出,流允许,其他程序过滤备份输出,提供更大的灵活存储backup,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用–stream选项即可如:

# 使用tar备份;
$ innobackupex --stream=tar /backup > /backup/db.tar
 
# 使用tar流并备份到其他服务器;
$ innobackupex --stream=tar /backup | ssh user@destination \ "cat - > /data/backups/backup.tar"
 
# 提取tar流,需要加i参数;
$ tar -xizf /backup/db.tar
 
# 压缩备份;
$ innobackupex --stream=tar /backup | gzip - > /backup/db.tar.gz

2)Xtrabackup对数据库进行部分备份

Xtrabackup也可以实现部分备份,即只备份某个或某些指定的数据库或某数据库中的某个或某些表。但要使用此功能,必须启用innodb_file_per_table选项,即每张表保存为一个独立的文件。同时,其也不支持–stream选项,即不支持将数据通过管道传输给其它程序进行处理。

此外,还原部分备份跟还原全部数据的备份也有所不同,即你不能通过简单地将prepared的部分备份使用–copy-back选项直接复制回数据目录,而是要通过导入表的方向来实现还原。当然,有些情况下,部分备份也可以直接通过–copy-back进行还原,但这种方式还原而来的数据多数会产生数据不一致的问题,因此,无论如何不推荐使用这种方式。

3)在复制环境下备份

有2个选项用于从复制环境下备份

--slave-info

备份从服务器时,此选项很有用。它打印主服务器的二进制日志位置,它还将该信息作为命令写入xtrabackup_slave_info文件。可以通过此备份来设置一个新从库。

--safe-slave-backup

为了保证复制状态的一致性,这个选项会关闭slave sql线程,等待直到SHOW STATUS中的Slave_open_temp_tabls为了才启动备份。如果等待时间超过–safe-slave-backup-timeout的值就会报错,默认300秒。备份成功后slave sql thread会自动启动。

4)备份加密

为了使备份加密需要指定的选项如下(选项中-加密密钥和加密密钥文件是相互排斥的,即只有一个需要提供):

--decrypt=ENCRYPTION-ALGORITHM

此选项指示xtrabackup使用ENCRYPTION_ALGORITHM中指定的算法加密InnoDB数据文件的备份副本。它直接传递到xtrabackup子进程。目前支持AES128,AES192和AES256算法。

--encrypt-key=encryption_key

适当长度的加密密钥的使用,不建议使用此选项,在不受控制的机器作为命令行访问,因此,关键可以被看作是过程信息的一部分。

--encrypt-key-file=ENCRYPTION_KEY_FILE

文件在适当长度的原始密钥可以读取,该文件必须是一个简单的二进制(或文本)文件,该文件包含了要使用的密钥。

<参考>

http://www.cnblogs.com/Amaranthus/archive/2014/08/19/3922570.html#_Toc396231239

https://www.percona.com/doc/percona-xtrabackup/LATEST/index.html

还没有评论,快来抢沙发!

发表评论

  • 😉
  • 😐
  • 😡
  • 😈
  • 🙂
  • 😯
  • 🙁
  • 🙄
  • 😛
  • 😳
  • 😮
  • emoji-mrgree
  • 😆
  • 💡
  • 😀
  • 👿
  • 😥
  • 😎
  • ➡
  • 😕
  • ❓
  • ❗
  • 68 queries in 0.434 seconds