XtraBackup是Percona公司开发的一款很好用的数据备份工具,支持对InnoDB引擎数据的热备份,对MyISAM引擎的数据做备份时需要锁表,详细信息参见官网或其他资源。【XtracBackup官网】

1. 实验环境

1.1 系统环境:

操作系统:CentOS 6.5 64位
主机地址:10.0.0.26
主机名:mysql01
mysql版本:mysql-5.6.36
XtraBackup版本:2.4.12 

2. 软件安装

2.1 安装mysql服务

MySQL服务详细安装过程请参考上一篇文章【慢查询可视化介绍】
这里需要注意的是,必须要开启log-bin功能,而且日志文件最好不要和数据文件放在同一个目录,以免对实验造成影响。下面是mysql的基本配置,如果缺少其中某一项则可能会出现报错。

[mysqld]
basedir=/opt/mysql-5.6.36/
datadir=/opt/mysql/data
log-bin=/opt/mysql/log/mysql-bin
slow_query_log_file = /opt/mysql/log/slow.log

[client]
socket=/opt/mysql/tmp/mysql.sock

2.2 安装XtraBackup工具

1、安装XtraBackup的依赖:

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL

2、下载安装XtraBackup:

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.12-1.el6.x86_64.rpm --no-check-certificate
yum -y localinstall percona-xtrabackup-24-2.4.12-1.el6.x86_64.rpm

3、检查是否安装成功:

[root@mysql01 data]# xtrabackup -v
xtrabackup: recognized server arguments: --datadir=/opt/mysql/data --log_bin=/opt/mysql/log/mysql-bin 
xtrabackup version 2.4.12 based on MySQL server 5.7.19 Linux (x86_64) (revision id: 170eb8c)

3. 生产案例描述

3.1 备份策略

某公司使用mysql数据库作为生产环境,对数据库的备份策略为全量+增量,具体如下:
1、每周六00:00通过XtraBackup进行一次数据全量备份

0 0 * *  6   full.sh

2、周日-周五每天01:00通过XtraBackup进行数据增备

0 1 * * 0-5  inc.sh

3、开启binlog日志功能

3.2 故障描述

在星期二的下午2点,某开发人员不小心误删了一张表,大概10GB左右,需要对该表进行恢复操作。在删表到开始恢复的这段时间内,可能还在继续对其他表进行写入操作。

3.3 恢复思路

1、断开数据库的连接,以防止二次破坏
2、准备上周六全备,并--apply-log  redo-only
3、合并增量,周日、周一、--apply-log --redoonly 周二--apply-log
4、在测试库恢复以上数据,数据的目前状态应该周二凌晨1:00
5、需要恢复的数据状态是下午2点钟左右,从1点开始的binlog恢复到删除之前那个events的position。
6、导出删除的表,恢复到生产库,验证数据可用性、完整性。
7、启动应用连接数据库。

4. 实践过程

4.1 环境模拟

1、创建备份相关目录:

    mkdir /backup/xbackup/full    #<==全备目录
    mkdir /backup/xbackup/inc1   #<==增备目录1
    mkdir /backup/xbackup/inc2   #<==增备目录2
    mkdir /backup/xbackup/inc3   #<==增备目录3

2、创建数据库和表:
创建数据库test,在test下创建表test和SC。其中test是需要删除的表,而SC是一直有数据写入的表

create database test character set utf8 collate utf8_general_ci;
use test;
create table test(id int,name char(20),age int);
drop table SC;
create table SC(
SCid int(12) NOT NULL auto_increment COMMENT '主键',
Cno int(10) NOT NULL COMMENT '课程号',
Sno int(10) NOT NULL COMMENT '学号',
Grade tinyint(2) NOT NULL COMMENT '学生成绩',
PRIMARY KEY (SCid)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

4.2 模拟数据写入过程

时间规划为2018-07-20(周五)----2018-07-24(周二)![]
1、模拟全备前数据写入:

date -s 2018-07-20
insert into test values(1,'小红',11);
insert into test values(2,'小黄',12);
INSERT INTO SC(Sno,Cno,Grade) values(0001,1001,1);

XtraBackup备份恢复模拟实践_第1张图片
2、周六数据全备及之后数据写入:

date -s 2018-07-21
innobackupex --user=root --password=123456 --no-timestamp /backup/xbackup/full/
date -s 08:00:00
insert into test values(3,'小蓝',13);
INSERT INTO SC(Sno,Cno,Grade) values(0002,1002,2);
commit;

XtraBackup备份恢复模拟实践_第2张图片
3、周日1点进行增备(20180722)和增量数据模拟:

date -s 2018-07-22
date -s 01:00:00
innobackupex --user=root --password=123456 --incremental --no-timestamp --incremental-basedir=/backup/xbackup/full/ /backup/xbackup/inc1
date -s 14:00:00
insert into test values(4,'小白',14);
INSERT INTO SC(Sno,Cno,Grade) values(0003,1003,3);
commit;

XtraBackup备份恢复模拟实践_第3张图片
4、周一1点进行增备(20180723)和增量数据模拟:

date -s 2018-07-23
date -s 01:00:00
innobackupex --user=root --password=123456 --incremental --no-timestamp --incremental-basedir=/backup/xbackup/inc1/ /backup/xbackup/inc2
date -s 17:00:00
insert into test values(5,'小黑',15);
INSERT INTO SC(Sno,Cno,Grade) values(0004,1004,4);
commit;

XtraBackup备份恢复模拟实践_第4张图片
5、周二1点进行增备(20180724)和增量数据模拟:

date -s 2018-07-24
date -s 01:00:00
innobackupex --user=root --password=123456 --incremental --no-timestamp --incremental-basedir=/backup/xbackup/inc2/ /backup/xbackup/inc3
date -s 04:00:00
insert into test values(6,'小黄',16);
INSERT INTO SC(Sno,Cno,Grade) values(0005,1005,5);
commit;

XtraBackup备份恢复模拟实践_第5张图片

4.3 模拟删除test表

在下午两点的时候删除表test,在此之后还继续对其他表进行操作。

date -s 14:00:00
drop table test;
INSERT INTO SC(Sno,Cno,Grade) values(0006,1006,6);

XtraBackup备份恢复模拟实践_第6张图片

5. 数据恢复

5.1 数据恢复准备

想要恢复数据,需要XtraBackup备份到星期二01:00点的数据,以及binlog在星期二01:00点之后到14:00这一段时间之类的数据。根据这两部分的数据,即可恢复表删除之前时间点的数据。
1、获取XtraBackup到星期二01:00的完整数据:

innobackupex --apply-log --redo-only /backup/xbackup/full/
innobackupex --apply-log --redo-only --incremental-dir=/backup/xbackup/inc1 /backup/xbackup/full/
innobackupex --apply-log --redo-only --incremental-dir=/backup/xbackup/inc2 /backup/xbackup/full/
innobackupex --apply-log --incremental-dir=/backup/xbackup/inc3 /backup/xbackup/full/
innobackupex --apply-log /backup/xbackup/full/
详细备份参数请参考官方文档或其他资料。

2、确认binlog的起点:
在XtraBackup的备份文件xtrabackup_binlog_info中会记录binlog的文件及起始位置。
XtraBackup备份恢复模拟实践_第7张图片

3、确认DROP语句之前的binlog位置:

mysqlbinlog --start-position=3295 /opt/mysql/log/mysql-bin.000006 >> /tmp/tmp.sql
cat /tmp/tmp.sql 

XtraBackup备份恢复模拟实践_第8张图片
4、恢复成sql文件:
通过上面两步,可以发现binlog的起始位置,以及DROP之前一个的结束位置。通过这两个position可以生成从01:00开始到14:00这一段时间内的数据库增量文件。

mysqlbinlog --start-position=3295 --stop-position=3782 /opt/mysql/log/mysql-bin.000006 > /tmp/recover.sql

5.2 数据恢复方案一

通过另外一台测试库恢复。将XtraBackup和binlog的恢复文件发送到另外一台测试数据库(10.0.0.27,mysql02),通过这台测试数据库将数据恢复到14:00的状态,再通过mysqldump备份出test表,最终传输到mysql01将数据恢复。
1、传输备份文件到mysql02:

scp -rp /backup/xbackup/full/ [email protected]:/tmp/
scp -rp /tmp/recover.sql [email protected]:/tmp/

2、测试库恢复XtraBackup数据:
再数据恢复之前,需要将测试库的data目录清空

innobackupex --copy-back /tmp/full/
chown -R mysql.mysql /opt/mysql/data/
/etc/init.d/mysqld start

XtraBackup备份恢复模拟实践_第9张图片
3、测试库恢复binlog数据:

source /tmp/recover.sql

XtraBackup备份恢复模拟实践_第10张图片
到此,已恢复到了删表前一个时间点的数据,这时我们将test表导出并恢复到正式库即可。

mysqldump -uroot -p123456 test test > /tmp/test_test.sql
mysql -uroot -p123456 < /tmp/test_test.sql
删除表恢复到删除时间点过程结束!

5.3 数据恢复方案二

从XtraBackup抽取表文件恢复。相对于方案一来说,不需要恢复全部数据库,也不需要再其他库上进行恢复,但是此种方式需要清楚建表的结构。
1、导出表:
导出表是在备份的prepare阶段进行的,因此,一旦完全备份完成,就可以在prepare过程中通过--export选项将某表导出了。
导出前:
XtraBackup备份恢复模拟实践_第11张图片
导出表命令:

innobackupex --apply-log --export /backup/xbackup/full/
此命令会为每个innodb表的表空间创建一个以.exp结尾的文件,这些以.exp结尾的文件则可以用于导入至其它服务器。

导出后:可以看出多了表结构等两个文件
XtraBackup备份恢复模拟实践_第12张图片
2、创建相同结构的表并删除此表的表空间:

create table test(id int,name char(20),age int);
alter table test.test discard tablespace;      #<==必须通过命令删除,不能手动删除文件

3、复制test.ibd和test.exp文件到数据目录:

[root@mysql01 test]# pwd
/backup/xbackup/full/test
[root@mysql01 test]# cp test.ibd /opt/mysql/data/test/
[root@mysql01 test]# cp test.exp /opt/mysql/data/test/
[root@mysql01 test]# chown -R mysql.mysql /opt/mysql/data/test/*

4、使用命令导入表

alter table test import tablespace;

XtraBackup备份恢复模拟实践_第13张图片
5、通过binlog恢复tests表01:00-14:00的增量数据
单表恢复只涉及到了test表,因此不需要其他表的数据,需要从recover.sql中过滤出test表

grep test /tmp/recover.sql > /tmp/test.sql
source /tmp/test.sql

XtraBackup备份恢复模拟实践_第14张图片

5.4 两种方案的比较

方案1

不需要知道原来的表结构,主库也只需要source sql文件,但是需要恢复全部数据库,并且需要在两台主机上传输数据,在数据量大的时候比较慢。

方案2

需要知晓表结构,相对来说更简单快捷。

至此,XtraBackup备份及恢复实践完毕!!!