一、Xtrabackup安装
安装依赖包
1 |
$ yum install perl-Time-HiRes perl-DBI libev |
安装RPM包
1 |
$ rpm -ihv percona-xtrabackup-2.4.4-Linux-x86_64.rpm |
或安装二进制版
1 2 |
$ 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个可执行文件,如下:
1 2 3 4 5 |
$ ls percona-xtrabackup-2.4.4-Linux-x86_64/bin/ innobackupex xbcrypt xbstream xtrabackup |
其中最主要的是innobackupex和xtrabackup,前者是一个perl脚本,后者是C/C++编译的二进制,复制到PATH路径下即可。
1 |
$ cp -fr percona-xtrabackup-2.4.4-Linux-x86_64/bin/* /usr/local/bin/ |
PS:注意,对于MySQL 5.7数据库需要percona-xtrabackup-2.4的版本才可以支持。
二、完整备份+二进制日志做数据备份与恢复
实验环境,数据库配置文件基本信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ 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 #………. |
需要造的数据
1 2 3 4 5 |
reset master; create database aa; use aa create table bb(id INT NOT NULL) ENGINE=innodb; insert into bb(id) value(1),(2),(3); |
1. 使用innobackupex完整备份数据(备份一个库)
1 2 |
$ mkdir /backup $ innobackupex --defaults-file=/etc/my.cnf --host 10.10.0.245 --port 3306 --user=root --password=redhat --parallel=2 --databases=aa /backup |
备份选项说明:
--host
备份主机地址。
--port
备份主机端口。
--user
备份主机用户。
--password
备份主机密码。
--socket
备份主机的sock文件位置。
--databases=#
指定备份数据库(如果不指定就是备份全部数据库)。
--databases-exclude=#
排除指定名称的数据库,请注意,此选项的优先级高于--databases
。
--defaults-file=[MY.CNF]
从给定配置文件读取默认选项,必须作为命令行上的第一个选项,必须是真实文件,它不能是一个象征性的链接。
--parallel=#
此选项指定在创建备份时同时复制多个数据文件的线程数,默认值为1(即没有并发传输)。
--no-timestamp
指定此选项,会直接把数据备份在指定备份文件中,不再创建时间戳的文件夹(比如:/backup/2017,在非流传输备份模式下会自动创建目录,但是在流模式下如果目标目录不存在会报错)。
--stream=tar|xbstream
将所有备份文件以指定格式流式传输到标准输出,目前支持的格式是xbstream和tar。
--no-lock
该选项表示关闭FTWRL的表锁,只有在所有表都是Innodb表并且不关心备份的binlog pos点,如果有任何DDL语句正在执行或者非InnoDB正在更新时(包括mysql库下的表),都不应该使用这个选项,后果是导致备份数据不一致,如果考虑备份因为获得锁失败,可以考虑--safe-slave-backup
立刻停止复制线程。
--slave-info
在从服务器备份时,此选项很有用。它打印主服务器的二进制日志位置,它还将该信息作为命令写入xtrabackup_slave_info文件。可以通过此备份来设置一个新从库。
--extra-lsndir
指定xtrabackup_checkpoints文件的存储位置,xtrabackup_checkpoints文件中记录了此次备份是全量还是增量,还记录了LSN。在使用流传输压缩增量备份时,这个参数很重要,可以通过此文件来进行增量备份。
--safe-slave-backup
该选项表示为保证一致性复制状态,这个选项停止SQL线程并且等到show status中的slave_open_temp_tables为0的时候开始备份,如果没有打开临时表,备份会立刻开始,否则SQL线程启动或者关闭知道没有打开的临时表。如果slave_open_temp_tables在--safe-slave-backup-timeount
(默认300秒)秒之后不为0,从库SQL线程会在备份完成的时候重启。
备份成功会出现如下信息:
1 2 3 4 5 6 7 8 |
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)。同时还会备份触发器和数据库配置信息相关的文件,这些文件会被保存至一个以时间命令的目录中,这个目录是innobackupex帮我们生成的。
Note
日志复制线程每一秒钟会检查事务日志,看看是否有新的需要被复制的日志记录,但有一个情况,就是日志复制线程可能无法跟上事务日志的写入速度,那样事务日志记录将被覆盖,从而会读到之前的事务日志,将得到一个错误。
此目录下会产生如下相关文件:
1 2 |
$ 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。
另外,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:
1 2 3 4 |
CREATE USER 'bkuser'@'localhost' IDENTIFIED BY 'redhat'; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'bkpuser'; GRANT RELOAD,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost'; FLUSH PRIVILEGES; |
2. 插入新数据
1 2 3 |
use aa insert into bb(id) value(100); insert into bb(id) value(200); |
3. 删除数据库(模拟数据损坏)
1 |
mysql> drop database aa; |
4. 使用Innobackupex预备(prepare)完全备份
一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“预备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件,使得数据文件处于一致性状态。
1 |
$ innobackupex --use-memory=1G --apply-log /backup/2017-06-22_11-31-24 |
Note
--use-memory
指定预备阶段可使用的内容,内存多则prepare速度快,默认为10MB。
如果执行正确,其最后输出的几行信息通常如下:
1 2 3 4 5 |
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还原完全备份
在进行数据库还原时,最好在一个新的数据库实例中完成,并且需要关闭MySQL实例后进行恢复操作。
1 |
$ mv /mydata /mydata-back |
mydata是我MySQL数据目录,做数据恢复时需要此目录不存在,还原的位子由my.cnf中的datadir决定,如果配置文件不是默认位置,需要使用--defaults-file=
参数指定。
1 |
$ innobackupex --defaults-file=/etc/my.cnf --copy-back /backup/2017-06-22_11-31-24/ |
如果执行正确,其输出信息的最后几行通常如下:
1 2 3 |
170622 11:36:45 [01] Copying ./ibtmp1 to /var/lib/mysql/ibtmp1 170622 11:36:46 [01] ...done 170622 11:36:46 completed OK! |
然后把原来的数据复制回来,注意不能覆盖现有的文件(如果是整个实例备份,那么就不需要复制数据了)。
1 2 3 4 5 6 7 |
$ 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 |
比较好的做法就是在新的实例还原数据库,然后使用逻辑备份工具导出要恢复的数据,再恢复到目标数据库中。
然后赋予权限,重新启动数据库。
1 2 3 4 5 6 7 8 9 10 |
$ chown -R mysql:mysql /mydata 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. 利用二进制日志文件提取完整备份后改动的数据做即时点还原
A. 首先查看xtrabackup_binlog_info文件找到完整备份时记录下正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置
1 2 |
$ cat /backup/2017-06-22_11-31-24/xtrabackup_binlog_info mysql-bin.000001 535 |
B. 使用mysqlbinlog /mydata/mysql-bin.000002(实际中是最后一次操作失误的二进制文件)进行查看,找到最后一次失误操作的时间点
1 2 3 4 5 6 |
$ 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 |
C. 根据最后一次失误的时间点,使用mysqlbinlog工具对二进制日志文件进行SQL命令提取
1 |
$ mysqlbinlog --start-position=535 --stop-position=945 /mydata/mysql-bin.000001 > /root/aaback.sql |
7. 关闭当前会话二进制日志记录功能,因为二进制日志不需要记录完整还原(以下操作只能对当前会话生效)
1 2 |
mysql> set sql_log_bin=0; mysql> show master status; |
8. 还原二进制提取的数据(注意由于sql_log_bin=0只对当前会话生效,所以只能使用source进行还原)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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表而言,执行增量备份时其实进行的是完全备份。关于增量备份的原理看“MySQL备份恢复:Xtrabackup原理阐述”。
使用innobackupex前的准备(实验环境)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ 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 #………. |
同样造一些数据:
1 2 3 4 5 |
reset master; create database aa; use aa create table bb(id INT NOT NULL) ENGINE=innodb; insert into bb(id) value(1),(2),(3); |
1. 使用innobackupex做完整备份(备份全部数据)
1 2 |
$ mkdir /backup $ innobackupex --defaults-file=/etc/my.cnf --user=root --password=redhat --parallel=2 /backup |
检查备份文件夹下的xtrabackup-checkpoints,会有一下信息:
1 2 3 4 5 6 |
$ cat /backup/2017-11-27_19-37-41/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 2094824 last_lsn = 2094824 compact = 0 |
在这种情况下,你可以看到,有是 to_lsn(最后一个检查点 LSN)和 last_lsn(最后复制 LSN)之间的差异,这意味着有在备份过程在服务器上的一些流量。
2. 增加数据
1 2 3 |
use aa insert into bb(id) value(100); insert into bb(id) value(200); |
3. 使用innobackupex做第一次增量备份
1 2 |
$ mkdir /backup/one-incremental $ innobackupex --incremental /backup/one-incremental --incremental-basedir=/backup/2017-11-27_19-37-41/ |
增量备份成功会出现如下:
1 2 3 4 5 |
..... innobackupex: Backup created in directory '/backup/one-incremental/2017-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
应该指向上一次的增量备份所在的目录。或者使用--incremental --incremental-lsn=to_lsn
指向上一次备份时to_lsn值。
如果你查看增量备份目录“/backup/one-incremental/2017-11-27_19-47-11”,会发现现在应该包含增量文件,例如ibdata1.delta和aa/tt.ibd.delta,这些代表自LSN 2094824以来的变化。
然后查看xtrabackup-checkpoints:
1 2 3 4 5 6 |
$ cat /backup/one-incremental/2017-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. 增加数据
1 2 3 |
use aa insert into bb(id) value(1000); insert into bb(id) value(2000); |
5. 使用innodbbackupex做第二次增量备份
1 |
$ innobackupex --incremental /backup/one-incremental --incremental-basedir=/backup/one-incremental/2017-11-27_19-47-11/ |
6. 删除数据(模拟数据损坏)
1 2 |
$ service mysqld stop $ mv /mydata /mydata-back |
7. 使用innodbbackupex预备(prepare)增量备份
预备增量备份需要2个步骤:
A. 需要先预备(prepare)完全备份,但是只重做已提交事务,不回滚未提交事务。然后增量应用到全备,也是只重做提交事务,不回滚未提交事务。
B. 最后一个增备回滚未提交事务(如果已经回滚了未提交事务,那么就无法再应用增量备份)。
注:在Mariadb 10.0上测试发现不加
--redo-only
预备全备,然后使用--redo-only
应用增量备份,MySQL服务能够正常启动并且数据被成功还原。
于是操作就变成了,在完全备份上,使用--redo-only
只重做已提交事务,不回滚未提交事务:
1 2 3 4 5 |
$ innobackupex --apply-log --redo-only /backup/2017-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! |
应用第一次增量备份:
1 |
$ innobackupex --apply-log --redo-only /backup/2017-11-27_19-37-41/ --incremental-dir=/backup/one-incremental/2017-11-27_19-47-11/ |
输出结果,注意LSN的变化
1 2 3 |
xtrabackup: starting shutdown with innodb_fast_shutdown = 1 InnoDB: Starting shutdown... InnoDB: Shutdown completed; log sequence number 2095386 |
需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序,可以使用xtrabackup-checkpoints来确定顺序。
应用第二次增量备份:
1 2 3 |
$ innobackupex --apply-log /backup/2015-11-27_19-37-41/ --incremental-dir=/backup/one-incremental/2017-11-27_19-53-23/ InnoDB: Starting shutdown... InnoDB: Shutdown completed; log sequence number 2096662 |
注:--redo-only
除了最后一个不用加之外,其他的增量应用都要加,最后一个应用的时候可以直接进入回滚未提交事务阶段。如果加了也没事儿,服务启动的时候会进入recovery过程,来回滚。
需要注意的是,应用增量备份的时候只能按照备份的顺序来应用。如果应用顺序错误,那么备份就不可用。如果无法确定顺序,可以使用xtrabackup-checkpoints来确定顺序。
最后回滚未提交事务:
1 |
$ innobackupex --apply-log /backup/2015-11-27_19-37-41/ |
所以全备加增备整个恢复过程如下:
1 2 3 4 5 |
--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. 从完全备份加增量备份中恢复数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ innobackupex --copy-back /backup/2017-11-27_19-37-41/ $ chown -R mysql:mysql /mydata mysql> select * from aa.bb; +------+ | id | +------+ | 1 | | 2 | | 3 | | 100 | | 200 | | 1000 | | 2000 | +------+ 7 rows in set (0.04 sec) |
到此,完整备份和增量备份中的数据都已经恢复了,如果在最后二次增量备份之后还有改动的数据,那么就需要利用二进制日志做即时点还原了。如果需要利用二进制日志的话需要参考最后一个增量备份记录的二进制文件和位置进行还原。
四、Xtrabackup的其他功能
1. Xtrabackup的“流”传输备份功能
XtraBackup支持流式备份,将备份以指定的tar或xbstream格式发送到STDOUT,而不是直接将文件复制到备份目录。要使用此功能,仅需要使用--stream
选项即可。这允许您使用其他程序来过滤备份的输出,为备份的存储提供更大的灵活性。例如,压缩是通过将输出管道输送到压缩实用程序来实现的。流式备份和使用Unix管道的优点之一:备份可以被自动加密。
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为0才启动备份。如果等待时间超过--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