xtrabackup 全备/增备和还原测试

关于xtrabackup


据官方介绍,xtrabackup是世界上唯一一款开源的能够对Innodb和Xtradb存储引擎进行物理热备的工具。XtraBackup包含两部分:xtrabackup的c程序和innobackupex的Perl脚本;前者主要用于处理InnoDB表的备份;后者是前者的封装,主要包括一些与MySQL服务器的通信和MyISAM表的备份。
而且xtrabackup热备份兼容所有版本的Percona Server和MySQL,它基于流式数据,压缩等进行备份,节省空间。

特点:

  1. 备份过程快速可靠.
  2. 备份过程不打断正在执行的事务.
  3. 节约磁盘空间和流量.
  4. 自动备份检验.
  5. 还原速度快.

xtrabackup 相关的参数可以查看官方Index:

1
https://www.percona.com/doc/percona-xtrabackup/2.4/genindex.html

xtrabackup 用户手册:

1
https://www.percona.com/doc/percona-xtrabackup/2.4/manual.html

根据需求下载xtrabackup

1
https://www.percona.com/downloads/XtraBackup/LATEST/

安装xtrabackup

我线上的环境用的是5.7.18的mysql,我选择2.4.libgcrypt145版本
下载xtrabackup二进制包

1
2
# cd /usr/local/src
# wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/tarball/percona-xtrabackup-2.4.12-Linux-x86_64.libgcrypt145.tar.gz

解压文件

1
# tar xf percona-xtrabackup-2.4.12-Linux-x86_64.libgcrypt145.tar.gz

方便管理,重命名一下

1
2
3
# mv percona-xtrabackup-2.4.12-Linux-x86_64 xtrabackup24
# ls /usr/local/src/xtrabackup24/bin/
innobackupex xbcloud xbcloud_osenv xbcrypt xbstream xtrabackup

创建相关的软链,不用设置环境变量

1
# ln -sv /usr/local/src/xtrabackup24/bin/* /usr/bin/

查看innobackupex版本信息,确认安装

1
# innobackupex -v

全量备份和还原测试

查看一下数据库的原始数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
logindb  -->
root@slave-3 [(none)]>show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| flask |
| mysql |
| performance_schema |
| sys |
| txdq_center |
+--------------------+
6 rows in set (0.00 sec)

root@slave-3 [(none)]>use flask
Database changed
root@slave-3 [flask]>show tables;
+-----------------+
| Tables_in_flask |
+-----------------+
| mytb |
| tb2 |
+-----------------+
2 rows in set (0.00 sec)

root@slave-3 [flask]>select * from mytb;
+----+----------+------+
| id | username | core |
+----+----------+------+
| 1 | john | 98 |
| 2 | keth | 88 |
| 3 | mary | 95 |
| 4 | ben | 93 |
| 5 | kitty | 68 |
+----+----------+------+
5 rows in set (0.00 sec)

这里我针对flask库和它下面的mytb表进行测试

创建备份存放目录

1
# mkdir -p /tmp/xtrabackup/{full,incre}

做一次全量备份

1
2
3
4
# innobackupex  --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --user=root --password=`cat /data/.dbp`  /tmp/xtrabackup/full

xtrabackup: Transaction log of lsn (2832968) to (2832977) was copied.
190104 14:44:59 completed OK!

查看第一次的全备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ls /tmp/xtrabackup/full/2019-01-04_14-44-55/ -l
total 282680
-rw-r----- 1 root root 488 2019-01-04 14:44:59 backup-my.cnf
drwxr-x--- 2 root root 82 2019-01-04 14:44:58 flask
-rw-r----- 1 root root 443 2019-01-04 14:44:59 ib_buffer_pool
-rw-r----- 1 root root 134217728 2019-01-04 14:47:34 ibdata1
-rw-r----- 1 root root 33554432 2019-01-04 14:47:34 ib_logfile0
-rw-r----- 1 root root 33554432 2019-01-04 14:47:32 ib_logfile1
-rw-r----- 1 root root 33554432 2019-01-04 14:47:32 ib_logfile2
-rw-r----- 1 root root 33554432 2019-01-04 14:47:32 ib_logfile3
-rw-r----- 1 root root 12582912 2019-01-04 14:47:33 ibtmp1
drwxr-x--- 2 root root 4096 2019-01-04 14:44:58 mysql
drwxr-x--- 2 root root 8192 2019-01-04 14:44:58 performance_schema
drwxr-x--- 2 root root 8192 2019-01-04 14:44:58 sys
drwxr-x--- 2 root root 244 2019-01-04 14:44:58 txdq_center
-rw-r----- 1 root root 21 2019-01-04 14:44:58 xtrabackup_binlog_info
-rw-r--r-- 1 root root 21 2019-01-04 14:47:30 xtrabackup_binlog_pos_innodb
-rw-r----- 1 root root 113 2019-01-04 14:47:32 xtrabackup_checkpoints
-rw-r----- 1 root root 534 2019-01-04 14:44:59 xtrabackup_info
-rw-r----- 1 root root 8388608 2019-01-04 14:47:32 xtrabackup_logfile
-rw-r--r-- 1 root root 1 2019-01-04 14:47:30 xtrabackup_master_key_id

观察一下备份目录里面的文件

1
2
3
4
先看一下所有的目录mysql,sys,flask,performance_schema 这些里面都是数据库文件了
ibdata1: 独立表空间
ib_logfile0-3: redolog 文件,保证数据一致性的
ib_buffer_pool: buffer pool 中的热数据,当设置 `innodb_buffer_pool_dump_at_shutdown=1` ,在关闭 MySQL 时,会把内存中的热数据保存在磁盘里 `ib_buffer_pool` 文件中

-> backup-my.cnf, 备份命令使用的参数选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cat  backup-my.cnf 
# This MySQL options file was generated by innobackupex.
# The MySQL server
[mysqld]
innodb_checksum_algorithm=crc32
innodb_log_checksum_algorithm=strict_crc32
innodb_data_file_path=ibdata1:128M:autoextend
innodb_log_files_in_group=4
innodb_log_file_size=33554432
innodb_fast_checksum=false
innodb_page_size=16384
innodb_log_block_size=512
innodb_undo_directory=./
innodb_undo_tablespaces=0
server_id=3
redo_log_version=1
server_uuid=33768ea9-0f2f-11e9-9277-1e57f2acce04
master_key_id=0

-> xtrabackup_binlog_info,mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件position

1
2
# cat xtrabackup_binlog_info
mysql-bin.000024 724

xtrabackup_binlog_pos_innodb 这个文件记录的信息跟xtrabackup_binlog_info一样。但是在增量备份的时候这个文件并不存在,这里注意。

-> xtrabackup_checkpoints
重点关注一下backup_type,这里是full-backuped

1
2
3
4
5
6
7
# cat xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 2832968
last_lsn = 2832977
compact = 0
recover_binlog_info = 0

from_lsn: 这里是第一次全备份,所以从0开始
to_lsn: 这里是备份完成这一刻所有有效数据的偏移量
last_lsn: 最后一个写入重做日志(redo log)的偏移量
简而言之,LSN(日志序列号)是重做日志的偏移,to_lsn应与from_lsn配对,主要用于增量备份等。

-> xtrabackup_info是一些数据记录,还原的时候会用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# cat xtrabackup_info
uuid = 412d5d7c-0fec-11e9-9277-1e57f2acce04
name =
tool_name = innobackupex
tool_command = --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --user=root --password=... /tmp/xtrabackup/full
tool_version = 2.4.12
ibbackup_version = 2.4.12
server_version = 5.7.18-log
start_time = 2019-01-04 14:44:55
end_time = 2019-01-04 14:44:59
lock_time = 0
binlog_pos = filename 'mysql-bin.000024', position '724'
innodb_from_lsn = 0
innodb_to_lsn = 2832968
partial = N
incremental = N
format = file
compact = N
compressed = N
encrypted = N

-> xtrabackup_logfile 文件是xtrabackup的数据文件,用来恢复前回滚redo log的。

模拟删除数据库

1
2
root@slave-3 [flask]>drop database flask;
Query OK, 2 rows affected (0.11 sec)

关闭mysql数据库:

1
# systemctl stop mysqld

模拟恢复数据库:

先apply-log,用于恢复前回滚事务

1
2
3
4
# innobackupex --apply-log /tmp/xtrabackup/full/2019-01-04_14-44-55/

InnoDB: Shutdown completed; log sequence number 2833448
190104 14:47:34 completed OK!

注意一下状态变化,这里如果没有把握一次性还原成功的话,必须先备份你的备份数据,否则apply-log之后,备份就改变了。

1
2
3
4
5
6
7
# cat xtrabackup_checkpoints
backup_type = full-backuped

# cat xtrabackup_checkpoints
backup_type = full-prepared

可以看到backup_type 由原来的 `full-backuped` 变成 `full-prepared`

清空原来mysql的数据目录

1
# rm -rf data/*

还原数据库

1
# innobackupex --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --copy-back --rsync /tmp/xtrabackup/full/2019-01-04_14-44-55/

修改数据目录权限

1
# chown mysql. -R data

启动mysql检查数据

1
# systemctl start mysqld

记得先关闭mysql服务并且删除(移走)原来的数据目录,否则还原报。
记得修改数据目录的权限,否则mysql启动失败。

登录检查数据

1
2
3
4
5
6
7
8
9
10
11
12
13
root@slave-3 [(none)]>use flask
Database changed
root@slave-3 [flask]>select * from mytb;
+----+----------+------+
| id | username | core |
+----+----------+------+
| 1 | john | 98 |
| 2 | keth | 88 |
| 3 | mary | 95 |
| 4 | ben | 93 |
| 5 | kitty | 68 |
+----+----------+------+
5 rows in set (0.03 sec)

全量备份和还原成功,数据已经回来。

增量备份

恢复数据之后先进行一次全备

1
2
3
# innobackupex  --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --user=root --password=`cat /data/.dbp`  /tmp/xtrabackup/full
xtrabackup: Transaction log of lsn (2833467) to (2833476) was copied.
190104 15:13:32 completed OK!

这里注意两个时间点2019-01-04_14-44-55是第一次全备的,2019-01-04_15-13-29这个是恢复数据之后重新做的一个全备,后面的增量备份全部基于这个全备时间点

1
2
# ls /tmp/xtrabackup/full
2019-01-04_14-44-55 2019-01-04_15-13-29

为了体现效果,这里新建一个新表testtb,并且插入一些测试数据

第一次数据修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@slave-3 [flask]>create table testtb (id int, name varchar(20) NOT NULL);
Query OK, 0 rows affected (0.04 sec)

root@slave-3 [flask]>INSERT INTO `testtb` VALUES (1,'a'),(2,'b'),(3,'c');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0

root@slave-3 [flask]>select * from testtb;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
| 3 | c |
+------+------+
3 rows in set (0.00 sec)

基于上一次的全量备份进行

第一次增量备份

1
2
3
# innobackupex  --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --user=root --password=`cat /data/.dbp` --incremental  /tmp/xtrabackup/incre --incremental-basedir=/tmp/xtrabackup/full/2019-01-04_15-13-29/
xtrabackup: Transaction log of lsn (2839777) to (2839786) was copied.
190104 15:32:18 completed OK!

–incremental 指定备份为增量备份
–incremental-basedir 指定增量备份的basedir,就是上边的全备时间点文件


1
2
# ls incre
2019-01-04_15-33-58

第二次修改数据

1
2
3
4
5
6
7
8
9
10
11
root@slave-3 [flask]>delete from  testtb where id =2;
Query OK, 1 row affected (0.03 sec)

root@slave-3 [flask]>select * from testtb;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 3 | c |
+------+------+
2 rows in set (0.00 sec)

第二次增量备份

1
2
3
# innobackupex  --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --user=root --password=`cat /data/.dbp` --incremental  /tmp/xtrabackup/incre --incremental-basedir=/tmp/xtrabackup/incre/2019-01-04_15-33-58 --parallel=2  
xtrabackup: Transaction log of lsn (2840255) to (2840264) was copied.
190104 15:38:31 completed OK!

模拟误操作删除数据

1
2
root@slave-3 [flask]>drop table testtb;
Query OK, 0 rows affected (0.01 sec)

增量备份还原

准备还原数据

增量备份之前记得redo-only,用于回滚未同步事务以及未提交事务

1
2
3
# innobackupex --apply-log --redo-only /tmp/xtrabackup/full/2019-01-04_15-13-29/
# cat /tmp/xtrabackup/full/2019-01-04_15-13-29/xtrabackup_checkpoints
backup_type = log-applied //状态变了,redo-only

第一次增备合并
1
2
3
4
5
# innobackupex --apply-log --redo-only /tmp/xtrabackup/full/2019-01-04_15-13-29 --incremental-dir=incre/2019-01-04_15-33-58
190104 15:43:32 completed OK!

# cat /tmp/xtrabackup/full/2019-01-04_15-13-29/xtrabackup_checkpoints
backup_type = log-applied
第二次增备合并
1
2
3
4
5
6
# innobackupex --apply-log  /tmp/xtrabackup/full/2019-01-04_15-13-29/ --incremental-dir=incre/2019-01-04_15-38-25
InnoDB: Shutdown completed; log sequence number 2840616
190104 15:44:28 completed OK!

# cat /tmp/xtrabackup/full/2019-01-04_15-13-29/xtrabackup_checkpoints
backup_type = full-prepared

注意,最后一个增量备份合并的时候不需要--redo-only,而且backup_type已经变成full-prepared

完整备份apply
1
2
3
# innobackupex --apply-log /tmp/xtrabackup/full/2019-01-04_15-13-29/
InnoDB: Shutdown completed; log sequence number 2840654
190104 15:45:21 completed OK!

这样就准备好还原的数据了

应用还原数据

关闭mysql
1
# systemctl stop mysqld
清空原来mysql的数据目录
1
# rm -rf data/*
还原数据库
1
2
# innobackupex --defaults-file=/data/mysqlDB/slave/4401/conf/slave.cnf --copy-back --rsync /tmp/xtrabackup/full/2019-01-04_15-13-29/
190104 15:49:33 completed OK!
修改数据目录权限
1
# chown mysql. -R data
启动mysql
1
# systemctl start mysqld
登录检查数据
1
2
3
4
5
6
7
8
9
10
root@slave-3 [(none)]>use flask
Database changed
root@slave-3 [flask]>select * from testtb;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 3 | c |
+------+------+
2 rows in set (0.22 sec)

可以看到数据已经恢复了。