Percona-Xtrabackup之innobackupex的使用

innobackupex为Percona Xtrabackup工具之一,文章从innobackupex工具的工作原理与使用对其进行了介绍。
Percona Xtrabackup的安装详见:
http://wing324.github.io/2015/10/04/Percona-Xtrabackup%E5%AE%89%E8%A3%85/

innobackupex

工作原理

备份
  1. 默认情况下,innobackupex会以xtrbackup –suspend-at-end启动复制InnoDB文件,当xtrbackup完成后,innobackupex检测到xtrabackup创建的xtrabackup_suspended_2文件,然后执行FTWRL复制非InnoDB文件。
  2. 当所有的文件都备份成功,重新开始ibbackup,等待完成复制备份过程中执行完成的事务,然后释放表锁,从库开启(在使用参数–safe-slave-backup的前提下),关闭连接MySQL,删除xtrabackup_suspended_2文件,退出xtrabackup。
    备份目录下的文件
    backup-my.cnf文件
    备份时需要的一些my.cnf文件中的选项。
[root@oracle01 2015-09-08_14-29-08]# cat backup-my.cnf
# This MySQL options file was generated by innobackupex.
# The MySQL server
[mysqld]
innodb_checksum_algorithm=innodb
innodb_data_file_path=ibdata1:64M:autoextend
innodb_log_files_in_group=2
innodb_log_file_size=67108864
innodb_page_size=16384
innodb_undo_directory=.
innodb_undo_tablespaces=0

xtrabackup_binlog_info文件
记录最后的binlog目录和位置

[root@oracle01 2015-09-08_14-29-08]# cat xtrabackup_binlog_info
mysql-bin.000005 47391729

xtrabackup_checkpoints文件
记录备份类型,开始和结束的LSN,是否为压缩备份

[root@oracle01 2015-09-08_14-29-08]# cat xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 545232808
last_lsn = 545232808
compact = 0

xtrabackup_info文件
备份的相关信息

[root@oracle01 2015-09-08_14-29-08]# cat xtrabackup_info
uuid = f19640f9-55f2-11e5-9676-fa163ee44368
name =
tool_name = innobackupex
tool_command = --user=percona --host=127.0.0.1 --password=... --port=3306 --defaults-group=mysqld3306 /data/backup/
tool_version = 1.5.1-xtrabackup
ibbackup_version = xtrabackup version 2.2.12 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 8726828)
server_version = 5.6.26-log
start_time = 2015-09-08 14:29:08
end_time = 2015-09-08 14:29:22
lock_time = 1
binlog_pos = filename 'mysql-bin.000005', position 47391729
innodb_from_lsn = 0
innodb_to_lsn = 545232808
partial = N
incremental = N
format = file
compact = N
compressed = N
encrypted = N

xtrabackup_binlog_pos_innodb文件
当前正在备份的相关事务对应的binlog位置

xtrabackup_slave_info文件
使用-slave-info参数时记录SHOW SLAVE STATUS\G的主库binlog位置

恢复
  1. 首先innobackup会读取my.cnf文件,检查 datadir, innodb_data_home_dir, innodb_data_file_path, innodb_log_group_home_dir 对应的目录是否存在
  2. 然后,最先复制非InnoDB数据和索引文件,然后复制InnoDB表和索引文件,最后复制日志文件。复制会保留文件属性,所以在启动恢复服务器之前要修改复制文件的用户和用户组为mysql

innobackupex连接MySQL需要使用的参数

–user:连接MySQL用户
–port: 连接MySQL端口
–host:连接MySQL的IP地址
–socket:连接MySQL的socket文件
–password:连接MySQL用户的密码
–defaults-file:指定MySQL配置文件
–defaults-group:指定MySQL配置文件读取的位置,如–defaults-group=‘mysqld’或者–defaults-group=‘mysqld3306’

innobackupex用户权限

  1. RELOAD & LOCK TABLES:为了在复制文件之前FLUSH TABLE WITH READ LOCK & FLUSH ENGINE LOGS使用,但备份锁需要时,则还需要执行LOCK TABLE FOR BACKUP & LOCK BINLOG FOR BACKUP
  2. REPLICATION CLIENT:获取二进制日志位置信息
  3. CREATE TABLESPACE:为了导入表
  4. PROECSS:为了查看服务器上哪些线程正在运行
  5. SUPER:复制环境下start/stop从库线程
  6. CREATE:创建PERCONA_SCHEMA.xtrabackup_history数据库和表
  7. INSERT:向PERCONA_SCHEMA.xtrabackup_history表中插入历史记录
  8. SELECT:在PERCONA_SCHEMA.xtrabackup_history表中查看innodb_to_lsn值

备份用户所需要的最小的权限为:RELOAD、LOCK TABLES、REPLICATION CLIENT
恢复用户所需要的最小的权限为:CREATE TABLESPACE

innobackupex完全备份使用演示

创建完全备份
# innobackupex备份工具
innobackupex --user=percona --host=127.0.0.1 --Port=3306 --password=percona --defaults-group='mysqld3306' /data/backup
# 备份成功会有如下输出信息
150906 13:16:53 innobackupex: Connection to database server closed
150906 13:16:53 innobackupex: completed OK!
# 进入备份目录
cd /data/backup/2015-09-06_13-16-49
# 查看备份目录下的文件
ls -l
# 备份目录下的文件如下
-rw-r--r-- backup-my.cnf
-rw-r------ ibdata1
drwx------ mysql
drwxr-xr-x performance_schema
drwx------ test
drwx------ wing
-rw-r--r-- xtrabackup_binlog_info
-rw-r----- xtrabackup_checkpoints
-rw-r--r-- xtrabackup_info
-rw-r----- xtrabackup_logfile
完全备份准备阶段

完全备份结束后,数据并不能立即被使用,因为此时的备份只是简单的复制文件,而存在未提交事务,需要进行prepare阶段方可使用数据。

# 准备阶段
innobackupex --apply-log /data/backup/2015-09-06_13-16-49/
# 准备成功会有如下输出信息
InnoDB: Shutdown completed; log sequence number 1639446
150906 13:18:16 innobackupex: completed OK!

注意该部分准备阶段不适合增量备份。
原理
该过程从备份目录下的backup-my.cnf开始读取配置,然后innobackupex重播已提交事务或者回滚未提交事务,一旦这样做,表空间的所有信息和日志文件都将被重建。
其他参数
–use-memory 指定该过程使用的内存,默认为100MB。

恢复完全备份
# innobackupex备份工具
innobackupex --defaults-group='mysqld3307' --copy-back /data/backup/2015-09-06_13-16-49/
# 恢复成功会有如下输出信息
innobackupex: Finished copying back files.
150906 15:27:22 innobackupex: completed OK!

特别说明

  1. 恢复前,需要停掉恢复使用的MySQL数据库实例
  2. datadir、innodb_data_home_dir(即共享表空间目录)、innodb_log_group_home_dir(即InnoDB日志文件)目录均需要清空,因为表空间的所有信息和日志文件都需要被重建。
  3. 恢复完成后,实例启动前,需要将之前清空的目录内部文件的权限修改为mysql用户。
  4. 恢复备份的实例不需要恢复账号即可完成。
chown -R mysql:mysql 目录名

恢复中的常见错误
错误1:innobackupex: Error: Cannot overwrite file: /data/mysqldata3307/innodb_ts/ibdata1 at /usr/bin/innobackupex line 2177
解决方法:删除文件ibdata1
错误2:innobackupex: Error: Cannot overwrite file: /data/mysqldata3307/innodb_log/ib_logfile0 at /usr/bin/innobackupex line 2177.
解决方法:删除文件ib_logfile0
错误3:innobackupex: Error: Original data directory ‘/data/mysqldata3307/mydata’ is not empty! at /usr/bin/innobackupex line 2162.
解决方法:删除/data/mysqldata3307/mydata下的所有文件

innobackupex增量备份使用演示

增量备份只适用于XtraDB和InnoDB存储引擎,对于其他的存储引擎会复制整个数据库。

创建增量备份
# 指定上一次备份后的增量备份
innobackupex --user=percona --host=192.168.200.143 --port=3306 --password=percona --defaults-group='mysqld3306' --incremental /data/backup --incremental-basedir=/data/backup/2015-09-06_13-16-49/
# 备份成功会有如下输出信息
150906 16:34:11 innobackupex: Connection to database server closed
150906 16:34:11 innobackupex: completed OK!
# 指定lsn后的增量备份
innobackupex --user=percona --host=192.168.200.143 --port=3306 --password=percona --incremental /data/backup --defaults-group='mysqld3306' --incremental-lsn=1639125
# 备份成功后会有如下输出信息
150906 16:45:43 innobackupex: Connection to database server closed
150906 16:45:43 innobackupex: completed OK!

特别说明
–incremental 指定增量备份的存储位置,以及指定为增量备份
–incremental-basedir 指定最近上一次备份的目录

原理
基于LSN,增量备份是在上一次备份后的LSN后备份其后的修改数据,可通过 xtrabackup_checkpoints文件查看LSN的变化。

增量备份准备阶段

特别说明

  1. 只有已提交的事务被使用,未提交的事务将会被回滚。
# 完全备份准备阶段
innobackupex --apply-log --redo-only /data/backup/2015-09-06_13-16-49/
注意此处存在--redo-only参数,如果在基础完全备份上对未提交事务进行回滚,此时将不能使用增量备份,故使用--redo-only只重播已提交事务解决该问题。
# 第一次增量备份准备阶段
innobackupex --apply-log --redo-only /data/backup/2015-09-06_13-16-49/ --incremental-dir=/data/backup/2015-09-06_16-34-08/
--incremental-dir 表示增量备份的目录
# 第二次增量备份准备阶段
innobackupex --apply-log /data/backup/2015-09-06_13-16-49/ --incremental-dir=/data/backup/2015-09-06_16-45-40/
注意此处没有--redo-only参数,该参数用于所有的增量备份准备阶段,除了最后一个增量备份
此时可在基础的完全备份目录下查看xtrabackup_checkpoints文件中LSN位置已经备份之最后一个增量备份处。
增量备份恢复阶段

与完全备份恢复相同,故省略。

部分备份使用演示

创建部分备份

仅备份部分表(要求表为独立表空间)或者部分数据库。
注意:部分备份的恢复不建议使用–copy-back,因为–copy-back是复制所有之前备份的文件。

# 备份wing.percona_test表,使用--include参数
innobackupex --user=percona --host=127.0.0.1 --port=3306 --password=percona --defaults-group='mysqld3306' --include='^wing[.]percona_test' /data/backup/
# 备份成功输出如下信息
150907 11:08:44 innobackupex: Connection to database server closed
150907 11:08:44 innobackupex: completed OK!
# 该备份还是会为每个数据库创建目录,但是没有备份表的数据库目录会没有文件,mysql和information_schema亦没有文件。
# 备份wing.t表,使用--tables_file参数
innobackupex --user=percona --host=127.0.0.1 --port=3306 --password=percona --defaults-group='mysqld3306' --tables-file=/data/mysqldata3306/tmpdir/innobackupex_table.txt /data/backup/
# 备份成功输出如下信息
150907 11:20:21 innobackupex: Connection to database server closed
150907 11:20:21 innobackupex: completed OK!
# 该备份不会为每个数据库创建目录,仅指定备份的表的数据库才会创建目录
部分备份恢复准备阶段

该阶段将会为每个innodb表创建自己的.exp表空间文件。

# --include参数备份文件恢复准备
innobackupex --apply-log --export 2015-09-07_11-08-40/
--export 用户导入单独表到服务器使用
# 恢复准备成功输出如下信息
InnoDB: Shutdown completed; log sequence number 1659926
150907 11:29:18 innobackupex: completed OK!
# 此时可看到该数据库目录下,该表的文件格式如下几种
[root@oracle01 wing]# ll
total 128
-rw-r--r-- 1 root root 420 Sep 7 11:53 t.cfg
-rw-r--r-- 1 root root 16384 Sep 7 11:53 t.exp
-rw-r----- 1 root root 8586 Sep 7 11:20 t.frm
-rw-r----- 1 root root 98304 Sep 7 11:20 t.ibd

特别说明
对于上述四种文件:.ctg、.exp、.frm、.ibd,有三种文件(.cfg、.exp、.ibd)需导入到服务器中
.cfg文件:该文件将表的数据字典存放为特殊的格式,严格来说,该文件不需要被导入到服务器中,但是如果没有该文件,会在导入表空间时存在如下警告信息;

Warning (Code 1810): InnoDB: IO Read error: (2, No such file or directory) Error opening './wing/t.cfg', will attempt to import without schema verification

.exp文件:
.frm文件:innodb表的数据字典文件;
.ibd文件:innodb表的数据+索引文件。

# 以导入t表为例
# 首先需要在导入的服务器中添加相同的表结构
root@localhost : wing 01:44:32> create table t (id int,name varchar(16));
Query OK, 0 rows affected (0.01 sec)
# 然后discard该表的表空间
root@localhost : wing 01:45:03> alter table t discard tablespace;
Query OK, 0 rows affected (0.00 sec)
# 将备份文件中的.exp、.ibd文件复制到该数据库目录下,.cfg文件可选复制
cp t.ibd t.exp /data/mysqldata3307/mydata/wing/
# 修改复制文件的权限
[root@oracle01 wing]# chown -R mysql:mysql t.*
# 然后import该表空间
root@localhost : wing 01:48:09> alter table t import tablespace;
Query OK, 0 rows affected, 1 warning (0.02 sec)

压缩备份使用演示

压缩备份会跳过innodb表的二级索引页,所以在恢复准备阶段需要更长的时间用于重建二级索引。(只适用于独立表空间的表)

创建压缩备份
innobackupex --user=percona --host=127.0.0.1 --port=3306 --password=percona --defaults-group='mysqld3306' --compact /data/backup/

是否为压缩备份,可从xtrabackup_checkpoints文件中查看,compact 选项为 1时,则为压缩备份。

恢复压缩备份准备阶段

该过程需要重建二级索引,所以需要使用–rebuild-indexes参数。

innobackupex --apply-log --rebuild-indexes /data/backup/2015-09-07_14-17-50/
恢复压缩备份

与完全恢复备份相同,请参考之。

innobackupex --user=percona --host=127.0.0.1 --port=3307 --password=percona --defaults-group='mysqld3307' --copy-back /data/backup/2015-09-07_14-17-50

加密备份

个人不是特别感兴趣,若以后感兴趣再学习之。
https://www.percona.com/doc/percona-xtrabackup/2.2/innobackupex/encrypted_backups_innobackupex.html

复制环境下的备份

–slave-info 该选项用于备份从库,输出二进制位置以及主库服务器名称,也会将CHANGE MASTER语句写入到xtrabackup_slave_info文件中。
–safe-slave-backup 该选项用于确保一致性的复制状态,该选项将停止从库的SQL线程,等到Slave_open_temp_tables的状态值为0时,开始备份,备份完成后会重启SQL线程。如果在–safe-slave-backup-timeout(默认为30s)之后,Slave_open_temp_tables的状态值未变为0,则备份将失败。
percona建议使用pt-table-checksum工具检查主从备份是否正确,暂时本人还未使用,待使用后告知。

基于时间点恢复备份

# 完全备份
innobackupex --user=percona --host=127.0.0.1 --port=3306 --password=percona --defaults-group='mysqld3306' --parallel=5 --rsync /data/backup/
# 准备恢复阶段
innobackupex --apply-log 2015-09-08_10-50-05/
# 对数据库做一些更改,然后查看当前数据库二进制日志及位置
root@localhost : wing 10:52:44> show tables;
+----------------+
| Tables_in_wing |
+----------------+
| percona_test |
| t |
+----------------+
2 rows in set (0.00 sec)
root@localhost : wing 10:52:46> drop table t;
Query OK, 0 rows affected (0.18 sec)
root@localhost : wing 10:52:56> drop table percona_test;
Query OK, 0 rows affected (0.01 sec)
root@localhost : wing 11:28:27> create table wing(id int);
Query OK, 0 rows affected (0.09 sec)
root@localhost : wing 11:29:11> insert into wing values(1),(2),(3),(4),(5),(6),(7),(8),(9);
Query OK, 9 rows affected (0.01 sec)
Records: 9 Duplicates: 0 Warnings: 0
root@localhost : wing 11:29:18> select * from wing;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+------+
9 rows in set (0.00 sec)
root@localhost : wing 11:29:34> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 65456 |
| mysql-bin.000002 | 1175657 |
| mysql-bin.000003 | 2099 |
| mysql-bin.000004 | 600 |
| mysql-bin.000005 | 449 |
+------------------+-----------+
5 rows in set (0.00 sec)
root@localhost : wing 11:29:40> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 449 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# 查找备份中的二进制日志及位置
[root@oracle01 2015-09-08_10-50-05]# less xtrabackup_binlog_info
mysql-bin.000004 338
# 恢复完全备份
innobackupex --copy-back --defaults-group='mysqld3307' /data/backup/2015-09-08_10-50-05/
# 基于完全备份后的位置(338)重定向到另一个文件中(官网需要这一步,然而好像并没有什么用的样子)
mysqlbinlog /data/mysqldata3306/binlog/mysql-bin.000004 /data/mysqldata3306/binlog/mysql-bin.000005 --start-position=338 > /data/mysqldata3307/tmpdir/mybinlog.sql
# 此时我想将备份恢复到时间为2015-09-08 11:00:00
mysqlbinlog /data/mysqldata3306/binlog/mysql-bin.000004 /data/mysqldata3306/binlog/mysql-bin.000005 --start-position=338 --stop-datetime='15-09-08 11:00:00' | mysql -uroot --socket=/data/mysqldata3307/sock/mysql.sock
# 检查发现percona_test,t表均不存在,是我想要的结果
root@localhost : (none) 11:37:48> use wing
Database changed
root@localhost : wing 11:37:50> show tables;
Empty set (0.00 sec)

加速innobackupex备份的几个选项

  1. –parallel
    为备份添加多个并行线程,它是文件级别上的,只适用于独立表空间或者共享表空间有多个文件。
innobackupex --user=percona --host=127.0.0.1 --port=3306 --password=percona --defaults-group='mysqld3306' --parallel=5 /data/backup/
  1. –compress-threads
    对使用–stream=xbstream –compress的压缩备份时,–compress-threads代表压缩备份的并行线程数。

  2. –rsync
    该选项是加速备份并且缩小flush tables with read lock,使用该选项可以对非innodb文件使用rsync代替cp复制。
    该参数不能与–remote-host、–stream一起使用。

提高FLUSH TABLES WITH READ LOCK处理

备份时为了保证一致性,会在备份开始时使用FLUSH TABLES WITH READ LOCK,但此时如果存在很长的写操作,将会导致产生冲突,默认为所有操作执行完毕后,才开始执行FLUSH TABLES WITH READ LOCK.

–lock-wait-timeout 当产生冲突时,innobackupex等待的时候,如果在–lock-wait-timeout时间内没有执行FLUSH TABLES WITH READ LOCK,那么将退出备份。

–lock-wait-query-type=all|update all表示执行等待所有长运行语句结束后执行FLUSH TABLES WITH READ LOCK,update表示等待UPDATE/ALTER/REPLACE/INSERT长运行语句结束后执行FLUSH TABLES WITH READ LOCK。

–lock-wait-threshold 执行长运行查询的时间,超过该值的语句均为长运行语句,该参数需要PROCESS&SUPPER权限。

–kill-long-queries-timeout 杀死FTWRL(FLUSH TABLES WITH READ LOCK)开始后超过该时间的操作。

–kill-long-query-type=all|select all代表杀死FTWRL(FLUSH TABLES WITH READ LOCK)开始后超过–kill-long-queries-timeout 时间的所有操作,select表示杀死FTWRL(FLUSH TABLES WITH READ LOCK)开始后超过–kill-long-queries-timeout 时间的select操作。

在服务器上保存备份历史

https://www.percona.com/doc/percona-xtrabackup/2.2/innobackupex/storing_history.html
暂时搁置该部分的学习。

innobackex参数

https://www.percona.com/doc/percona-xtrabackup/2.2/innobackupex/innobackupex_option_reference.html

推荐阅读

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