Percona XtraBackup
一、简介
1.1、Xtrabackup工具介绍
Xtrabackup是一个对InnoDB做物理数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个很好的替代品。
Xtrabackup有两个主要的工具:xtrabackup、innobackupex
- xtrabackup只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表。
- innobackupex是用来备份非InnoDB表的,同时会调用xtrabackup命令来备份InnoDB表,还会和mysql server发送命令进行交会,如加读锁、获取位点等。简单来说,innobackupex在xtrabackup之上做了一层封装。
- xbcrypt 加密解密备份工具
- xbstream 流传打包传输工具,类似tar
一般情况下,我们是希望能备份MyISAM表的,虽然我们可能自己不用MyISAM表,但是mysql库下的系统表示MyISAM的,因此备份基本都通过innobackupex命令进行;另外一个原因是我们可能需要保存位点信息。
1.2、XtraBackup备份原理
XtraBackup基于InnoDB的crash-recovery功能,它会复制InnoDB的data file,由于不锁表,复制出来的数据是不一致的,在恢复的时候使用crash-recovery,使得数据恢复一致。
InnoDB维护了一个redo log,又称为transaction log(事务日志),它包含了InnoDB数据的所有改动情况。当InnoDB启动的时候,它会先去检查data file和transaction log,并且会做两步操作:
XtraBackup在备份的时候,一页一页的复制InnoDB的数据,而且不锁定表,与此同时,XtraBackup还有另外一个线程监视着transaction log,一旦log发生变化,就把变化过的log pages复制走。为什么要着急复制走呢?因为transaction log文件大小有限,写满之后,就会从头再开始写,所以新数据可能会覆盖到旧的数据。
在prepare过程中,XtraBackup使用复制到的transaction log对备份出来的InnoDB data file进行crash recovery。
1.3、XtraBackup备份特点
- 备份过程快速、可靠
- 备份过程不会打断正在执行的事务
- 能够基于压缩等功能节约磁盘空间和流量
- 自动实现备份检验
- 还原速度快
1.4、XtraBackup安装
安装见官网:https://www.percona.com/doc/percona-xtrabackup/2.4/installation.html
二、XtraBackup使用
2.1、innobackupex工具使用
前期准备,mysql搭建:
docker run -d --name mysql --rm -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
mkdir -pv /data/docker/mysql
cd /data/docker/mysql
docker cp mysql:/etc/mysql .
docker stop msyql
docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /data/docker/mysql/config:/etc/mysql -v /data/docker/mysql/data:/var/lib/mysql mysql:5.7
创建备份用户
create user cyf@'%' identified by '123456';
grant reload,process,lock tables,replication client on *.* to cyf@'%';
2.1.1、常用参数说明
参数 | 含义 |
---|---|
–defaults-file | 指定mysql的配置文件(必须放在参数第一位) |
–host | 指定mysql主机地址 |
–user | 指定备份用户 |
–password | 指定备份用户的密码 |
–port | 指定mysql的端口号 |
–databases | 指定备份的数据库或表(多个库之间用空格隔开,默认所有库)备份表就写成db1.table1 |
–socket | 指定mysqld.sock文件位置 |
–no-timestamp | 不使用时间戳,直接在指定的目录下生成备份文件 |
–parallel | 指定并行备份线程数 |
–use-memory | 在恢复过程中的准备阶段可以使用的内存大小 |
–datadir | 指定mysql数据目录位置(默认/var/lib/mysql) |
–incremental | 该选项表示创建增量备份,而不是全量备份。 |
–incremental-basedir | 指定增量备份时,基于的全量备份目录或增量备份目录 |
–incremental-dir | 指定还原时增量备份的目录 |
–copy-back | 将准备好的备份文件从备份目录复制到原始位置,其原始位置目录必须为空,否则报错(除非指定–force-non-empty-directories选项) |
–apply-log | 应用xtrabackup_logfile文件,重做已提交的事务,回滚未提交的事务 |
–redo-only | 只重做已提交的事务,不回滚未提交的事务 |
–compact | 压缩备份 |
–incremental-lsn | 自定义增量备份的LSN |
2.1.2、全量、增量备份
生成数据库和数据:
shell> docker exec -it mysql mysql -uroot -p123456
mysql> create database test default character set utf8 collate utf8_general_ci;
Query OK, 1 row affected (0.04 sec)
mysql> use test;
Database changed
mysql> create table if not exists info(id int(11) not null auto_increment, name varchar(30) not null, age int(11) not null, primary key (id));
Query OK, 0 rows affected (0.34 sec)
mysql> insert into info(id, name, age) values(1, "cyf", 24);
Query OK, 1 row affected (0.08 sec)
mysql> select * from info;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | cyf | 24 |
+----+------+-----+
1 row in set (0.00 sec)
全量备份
创建备份目录:
mkdri -pv /data/docker/mysql/backup
开始全量备份:
innobackupex --no-timestamp --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data /data/docker/mysql/backup/full
查看备份目录:
root@deepin:~# ls /data/docker/mysql/backup/full/
backup-my.cnf ib_buffer_pool ibdata1 mysql performance_schema sys test xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile
备份文件说明:
- backup-my.cnf:备份命令用到的配置选项信息
# This MySQL options file was generated by innobackupex.
# The MySQL server
[mysqld]
innodb_checksum_algorithm=innodb
innodb_log_checksum_algorithm=strict_crc32
innodb_data_file_path=ibdata1:12M:autoextend
innodb_log_files_in_group=2
innodb_log_file_size=50331648
innodb_fast_checksum=false
innodb_page_size=16384
innodb_log_block_size=512
innodb_undo_directory=./
innodb_undo_tablespaces=0
server_id=0
redo_log_version=1
- ib_buffer_pool:
0,284
18,3
3,3
0,51
0,5
10,314
0,547
10,313
...
- ibdata1: 备份的表空间文件
- xtrabackup_binlog_info:记录是备份完成时间点的binlog文件名,binlog位点,Executed_Gtid_Set
mysql-bin.000003 944 623f7620-ee62-11ea-9022-0242ac110002:1-8
- xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息
backup_type = full-backuped # 代表全量备份
from_lsn = 0 # 由于是全量备份,所以数据是从LSN=0开始的
to_lsn = 12471407
last_lsn = 12471416
compact = 0
recover_binlog_info = 0
- xtrabackup_info:记录的是备份时候的一些参数,脚本版本,数据库版本,备份时间,binlog,是否压缩,备份增量还是全量等信息
uuid = 9d52879f-ee62-11ea-b36a-0242ac110002
name =
tool_name = innobackupex
tool_command = --no-timestamp --host=192.168.10.38 --user=root --password=... --port=3306 --datadir=/data/docker/mysql/data /data/docker/mysql/backup/full
tool_version = 2.4.4
ibbackup_version = 2.4.4
server_version = 5.7.27-log
start_time = 2020-09-04 11:56:17
end_time = 2020-09-04 11:56:30
lock_time = 0
binlog_pos = filename 'mysql-bin.000003', position '944', GTID of the last change '623f7620-ee62-11ea-9022-0242ac110002:1-8'
innodb_from_lsn = 0
innodb_to_lsn = 12471407
partial = N
incremental = N
format = file
compact = N
compressed = N
encrypted = N
- xtrabackup_logfile:备份的重做日志文件
全备恢复
通过删除数据目录下的所有文件模拟数据丢失(不删除的话,恢复时也需要目录为空):
rm -rf /data/docker/mysql/data/*
prepare完整的数据备份文件:
一般情况下,这个/data/docker/mysql/backup/full备份不能用于恢复,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务,此时数据文件仍处于不一致的状态。
因此--apply-log
的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态
innobackupex --apply-log /data/docker/mysql/backup/full
查看全量备份的xtrabackup_checkpoints
,状态如下
backup_type = full-prepared
from_lsn = 0
to_lsn = 12471407
last_lsn = 12471416
compact = 0
recover_binlog_info = 0
开始恢复数据(注意:原数据目录必须为空
):
innobackupex --datadir=/data/docker/mysql/data --copy-back /data/docker/mysql/backup/full
重启mysql服务,docker restart mysql
,查看数据是否恢复,数据存在,恢复完毕。
root@deepin:~# docker exec -it mysql mysql -uroot -p123456
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from info;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | cyf | 24 |
+----+------+-----+
1 row in set (0.00 sec)
增量备份
增量备份前需要做全量备份
,删除上面操作的数据库和数据,重复上面的全量备份操作。再重新执行完上面的基础上,再插入一条mysql数据,然后做第一次增量备份
mysql> insert into info(id, name, age) values(2, "kobe", 24);
Query OK, 1 row affected (0.07 sec)
mysql> select * from info;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | cyf | 24 |
| 2 | kobe | 24 |
+----+------+-----+
2 rows in set (0.00 sec)
--incremental-basedir
:指的是全量备份
所在的目录,另外,在执行过增量备份之后再一次进行增量备份
时,其--incremental-basedir
应该指向上一次的增量备份
所在的目录。
需要注意的是,增量备份仅能应用于InnoDB
或XtraDB
表,对于MyISAM表而言,执行增量备份时其实进行的是全量备份。
执行第一次增量备份
innobackupex --no-timestamp --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --incremental /data/docker/mysql/backup/incr1 --incremental-basedir=/data/docker/mysql/backup/full
查看第一次增量备份目录:
root@deepin:~# ls /data/docker/mysql/backup/incr1/
backup-my.cnf ib_buffer_pool ibdata1.delta ibdata1.meta mysql performance_schema sys test xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile
查看第一次增量备份的xtrabackup_checkpoints
文件,状态如下:
backup_type = incremental
from_lsn = 12471407 # 来自全量备份的to_lsn
to_lsn = 12472241
last_lsn = 12472250
compact = 0
recover_binlog_info = 0
再插入一条数据,进行第二次增量备份
mysql> insert into info(id, name, age) values(3, "tom", 6);
Query OK, 1 row affected (0.07 sec)
mysql> select * from info;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | cyf | 24 |
| 2 | kobe | 24 |
| 3 | tom | 6 |
+----+------+-----+
3 rows in set (0.00 sec)
注意第二次的--incremental-basedir
指向的是第一次增量备份
的目录,是基于上一次增量备份,再进行增量备份
innobackupex --no-timestamp --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --incremental /data/docker/mysql/backup/incr2 --incremental-basedir=/data/docker/mysql/backup/incr1
查看第二次增量备份目录:
root@deepin:~# ls /data/docker/mysql/backup/incr2
backup-my.cnf ib_buffer_pool ibdata1.delta ibdata1.meta ib_logfile0 ib_logfile1 mysql performance_schema sys test xtrabackup_binlog_info xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile
查看第二次增量备份的xtrabackup_checkpoints
文件,状态如下:
backup_type = incremental
from_lsn = 12472241 # 来自第一次增量备份的to_lsn
to_lsn = 12472606
last_lsn = 12472615
compact = 0
recover_binlog_info = 0
增备恢复
--redo-only
:在prepare阶段,完整备份合并,除最后一个增量之外的所有增量,都应使用该选项。迫使innobackupex跳过“回滚”阶段,只做一次“重做”。如果已经在全量备份上重放了提交的事务并回滚了未提交的事务,则无法在此备份上添加增量。同样,如果在增量备份上执行,则无法添加其余的增量备份
prepare完整的数据恢复文件
# prepare全备
innobackupex --apply-log --redo-only /data/docker/mysql/backup/full
# 查看全备目录
root@deepin:~# ls /data/docker/mysql/backup/full/
backup-my.cnf ib_buffer_pool ibdata1 ib_logfile0 ib_logfile1 ibtmp1 mysql performance_schema sys test xtrabackup_binlog_info xtrabackup_binlog_pos_innodb xtrabackup_checkpoints xtrabackup_info xtrabackup_logfile
# 再查看全量备份的xtrabackup_checkpoints文件
backup_type = log-applied
from_lsn = 0
to_lsn = 12471407
last_lsn = 12471416
compact = 0
recover_binlog_info = 0
# prepare增备1
innobackupex --apply-log --redo-only /data/docker/mysql/backup/full --incremental-dir=/data/docker/mysql/backup/incr1
# 再查看全量备份的xtrabackup_checkpoints文件,to_lsn已经变化
backup_type = log-applied
from_lsn = 0
to_lsn = 12472241
last_lsn = 12472250
compact = 0
recover_binlog_info = 0
# prepare增备2(由于我只做两次增量,第二次不需要--redo-only)
innobackupex --apply-log /data/docker/mysql/backup/full --incremental-dir=/data/docker/mysql/backup/incr2
# 再查看全量备份的xtrabackup_checkpoints文件,to_lsn已经变化,backup_type也prepared
backup_type = full-prepared
from_lsn = 0
to_lsn = 12472606
last_lsn = 12472615
compact = 0
recover_binlog_info = 0
# 把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据
innobackupex --apply-log /data/docker/mysql/backup/full
# 恢复数据
# 数据目录还是不能为空,rm -rf /data/docker/mysql/data/*
innobackupex --datadir=/data/docker/mysql/data --copy-back /data/docker/mysql/backup/full
重启mysql docker restart mysql
,查看数据是否恢复成功,可以看到第一次增量前的数据已经恢复
root@deepin:~# docker exec -it mysql mysql -uroot -p123456
mysql> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from info;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | cyf | 24 |
| 2 | kobe | 24 |
| 3 | tom | 6 |
+----+------+-----+
3 rows in set (0.00 sec)
2.2、xtraBackup工具使用
2.2.1、常用参数说明
参数 | 含义 |
---|---|
–host | 指定mysql主机地址 |
–user | 指定备份用户 |
–password | 指定备份用户的密码 |
–port | 指定mysql的端口号 |
–databases | 指定备份的数据库或表(多个库之间用空格隔开,默认所有库)备份表就写成db1.table1 |
–socket | 指定mysqld.sock文件位置 |
–backup | 表示备份 |
–prepare | 相当于innobackupex的参数–apply-log |
–target-dir | 指定全量或增量备份文件存放的目录 |
–datadir | 指定mysql数据目录位置(默认/var/lib/mysql) |
–incremental-basedir | 同innobackupex |
–incremental-dir | 同innobackupex |
–apply-log-only | 相当于innobackupex的参数–redo-only |
2.2.2、全量、增量备份
全量备份
# 全量备份
xtrabackup --backup --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/full
# prepare全量备份
xtrabackup --prepare --target-dir=/data/docker/mysql/backup/full
# 全量恢复
xtrabackup --copy-back --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/full
增量备份
# 全量备份
xtrabackup --backup --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/full
# 增备1
xtrabackup --backup --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/incr1 --incremental-basedir=/data/docker/mysql/backup/full
# 增备2
xtrabackup --backup --host=192.168.10.38 --user=cyf --password=123456 --port=3306 --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/incr2 --incremental-basedir=/data/docker/mysql/backup/incr1
# prepare增量备份(最后一次增量不需要--apply-log-only)
xtrabackup --prepare --apply-log-only --target-dir=/data/docker/mysql/backup/full
xtrabackup --prepare --apply-log-only --target-dir=/data/docker/mysql/backup/full --incremental-dir=/data/docker/mysql/backup/incr1
xtrabackup --prepare --target-dir=/data/docker/mysql/backup/full --incremental-dir=/data/docker/mysql/backup/incr2
# 全量恢复
xtrabackup --copy-back --datadir=/data/docker/mysql/data --target-dir=/data/docker/mysql/backup/full