xtrabackup进行MySQL数据库备份/还原

时间:2023-02-10 03:20:20

http://hongge.blog.51cto.com/

使用xtrabackup进行MySQL数据库备份

前面介绍mysqldump备份方式是采用逻辑备份,其最大的缺陷就是备份和恢复速度都慢,对于一个小于50G的数据库而言,这个速度还是能接受的,但如果数据库非常大,那再使用mysqldump备份就不太适合了。

这时就需要一种好用又高效的工具,xtrabackup就是其中一款,号称免费版的InnoDB HotBackup。

Xtrabackup实现是物理备份,而且是物理热备

目前主流的有两个工具可以实现物理热备:ibbackup和xtrabackup;ibbackup是商业软件,需要授权,非常昂贵。而xtrabackup功能比ibbackup还要强大,但却是开源的。因此我们这里就来介绍xtrabackup的使用。

Xtrabackup提供了两种命令行工具:

xtrabackup:专用于备份InnoDB和XtraDB引擎的数据;

innobackupex:这是一个perl脚本,在执行过程中会调用xtrabackup命令,这样用该命令即可以实现备份InnoDB,也可以备份MyISAM引擎的对象。

Xtrabackup是由percona提供的mysql数据库备份工具,特点:

(1)备份过程快速、可靠;

(2)备份过程不会打断正在执行的事务;

(3)能够基于压缩等功能节约磁盘空间和流量;

(4)自动实现备份检验;

(5)还原速度快。

官方链接地址:http://www.percona.com/software/percona-xtrabackup;可以下载源码编译安装,也可以下载适合的RPM包或使用yum进行安装或者下载二进制源码包。

安装xtrabackup

1)下载xtrabackup

wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/tarball/percona-xtrabackup-2.4.4-Linux-x86_64.tar.gz

2)解压

# tar zxf percona-xtrabackup-2.4.4-Linux-x86_64.tar.gz

3)进入解压目录

# cd percona-xtrabackup-2.4.4-Linux-x86_64/

4)复制bin下的所有程序到/usr/bin

[root@localhost percona-xtrabackup-2.4.4-Linux-x86_64]# cp bin/* /usr/bin/

Xtrabackup中主要包含两个工具:

xtrabackup:是用于热备份innodb, xtradb表中数据的工具,支持在线热备份,可以在不加锁的情况下备份Innodb数据表,不过此工具不能操作Myisam引擎表;

innobackupex:是将xtrabackup进行封装的perl脚本,能同时处理Innodb和Myisam,但在处理Myisam时需要加一个读锁。

由于操作Myisam时需要加读锁,这会堵塞线上服务的写操作,而Innodb没有这样的限制,所以数据库中Innodb表类型所占的比例越大,则越有利。

4)安装相关插件

#yum install perl-DBI perl-DBD-MySQL perl-Time-HiRes perl-IO-Socket-SSL perl-TermReadKey.x86_64 perl-Digest-MD5 �Cy

5)下载percona-toolkit并安装

#wget https://www.percona.com/downloads/percona-toolkit/2.2.19/RPM/percona-toolkit-2.2.19-1.noarch.rpm

# rpm -vih percona-toolkit-2.2.19-1.noarch.rpm

下面就可以启动备份了

方案一:xtrabackup完全备份+binlog增量备份

1、备份

创建备份目录

# mkdir -p /opt/mysqlbackup/{full,inc}

full:全备存放的目录;inc:增量备份存放的目录

1)完全备份

基本语法:# innobackupex --user=DBUSER --password=DBUSERPASS  /path/to/BACKUP-DIR/

执行下面的命令进行完全备份:

# innobackupex --user=root --password=123456 /opt/mysqlbackup/full

注: --defaults-file=/etc/my.cnf 指定mysql的配置文件my.cfg,如果指定则必须是第一个参数。

/path/to/BACKUP-DIR/指定备份所存放的目标目录,备份过程会创建一个以当时备份时间命名的目录存放备份文件。

出现如下提示。表示成功

xtrabackup进行MySQL数据库备份/还原

备份后的文件:

在备份的同时,备份数据会在备份目录下创建一个以当前日期时间为名字的目录存放备份文件:

xtrabackup进行MySQL数据库备份/还原

各文件说明:

(1)xtrabackup_checkpoints ―― 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

(2)xtrabackup_binlog_info ―― mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。

(3)xtrabackup_binlog_pos_innodb ―― 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

(4)xtrabackup_binary ―― 备份中用到的xtrabackup的可执行文件;

(5)backup-my.cnf ―― 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据

注意:相关选项说明:

其中,--user指定连接数据库的用户名,--password指定连接数据库的密码,--defaults-file指定数据库的配置文件,innobackupex要从其中获取datadir等信息;--database指定要备份的数据库,这里指定的数据库只对MyISAM表有效,对于InnoDB 数据来说都是全备(所有数据库中的InnoDB数据都进行了备份,不是只备份指定的数据库,恢复时也一样);/opt/mysqlbackup/full是备份文件的存放位置。

注意:备份数据库的用户需要具有相应权限,如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

mysql> create user 'bkpuser'@'localhost' identified by '123456';

mysql> revoke all privileges,grant option from 'bkpuser'@'localhost';

mysql> grant reload,lock tables,replication client, process on *.* to 'bkpuser'@'localhost';

mysql> flush privileges;

至此全备完全成功,然后向mysql某个库插入几条数据,然后进行增量备份

对完全备份的后数据库更改进行二进制日志增量备份:

查看完全备份时binlog日志位置(position):

xtrabackup进行MySQL数据库备份/还原

模拟数据库修改:

xtrabackup进行MySQL数据库备份/还原

2)增量备份二进制文件:

#mysqlbinlog --start-position=2378 /usr/local/mysql/data/mysql-bin.000023 > /opt/mysqlbackup/inc/`date +%F`.sql

2、还原数据库:

模拟数据库损坏:

我这里直接使用删除数据目录文件来模拟损坏。

# rm -fr /usr/local/mysql/data/*

还原完全备份:

(1)准备(prepare)一个完全备份

一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。

在准备(prepare)过程结束后,InnoDB表数据已经前滚到整个备份结束的点,而不是回滚到xtrabackup刚开始时的点。

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:

--apply-log指明是将日志应用到数据文件上,完成之后将备份文件中的数据恢复到数据库中:

# innobackupex --apply-log /opt/mysqlbackup/full/2016-09-12_11-29-55/

注:/opt/mysqlbackup/full/2016-09-12_11-29-55/备份文件所在目录名称

如果执行正确,其最后输出的几行信息通常如下:

xtrabackup进行MySQL数据库备份/还原

在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。

innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。

(2)还原数据库语法:

# innobackupex --copy-back /opt/mysqlbackup/full/2016-09-12_11-29-55/

这里的--copy-back指明是进行数据恢复。数据恢复完成之后,需要修改相关文件的权限mysql数据库才能正常启动。

如果执行正确,其输出信息的最后几行通常如下:

xtrabackup进行MySQL数据库备份/还原

请确保如上信息的最行一行出现“completed OK!”。

修改还原后的数据目录权限:

xtrabackup进行MySQL数据库备份/还原

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:

# chown -R mysql:mysql /usr/local/mysql/data/

重启动MySQL:

# systemctl restart mysqld

验证还原后的数据:

mysql> select * from tb1;

+----+------+

| id | name |

+----+------+

| 1 | tom1 |

| 2 | tom2 |

+----+------+

(3)还原增量备份:

为了防止还原时产生大量的二进制日志,在还原时可临时关闭二进制日志后再还原:

mysql> set sql_log_bin=0;

mysql> source /opt/mysqlbackup/inc/2016-09-12.sql

重新启动二进制日志并验证还原数据:

mysql> set sql_log_bin=1;

验证数据是否恢复回来

xtrabackup进行MySQL数据库备份/还原

方案二、xtrabackup完全备份+xtrabacup增量备份

前面我们进行增量备份时,使用的还是老方法:备份二进制日志。其实xtrabackup还支持进行增量备份。

先介绍下xtrabackup的备份原理

在InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件(transaction log,事务日志)。事务日志会存储每一个InnoDB表数据的记录修改。当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。

xtrabackup在启动时会记住log sequence number(LSN),并且复制所有的数据文件。复制过程需要一些时间,所以这期间如果数据文件有改动,那么将会使数据库处于一个不同的时间点。这时,xtrabackup会运行一个后台进程,用于监视事务日志,并从事务日志复制最新的修改。xtrabackup必须持续的做这个操作,是因为事务日志是会轮转重复的写入,并且事务日志可以被重用。所以xtrabackup自启动开始,就不停的将事务日志中每个数据文件的修改都记录下来。这就是xtrabackup的备份过程

所以每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础。

xtraBackup基于InnoDB的crash-recovery功能。它会复制innodb的data file,由于不锁表,复制出来的数据是不一致的,在恢复的时候使用crash-recovery,使得数据恢复一致。

当InnoDB启动的时候,它会先去检查data file和transaction log,并且会做二步操作:

1.It applies committed transaction logentries to the data files

2.it performs an undo operation on anytransactions that modified data but did not commit.

所以在prepare过程中,XtraBackup使用复制到的transactions log对备份出来的innodb data file进行crash recovery。

测试环境准备

创建一个测试数据库,并创建一张表输入几行数据

mysql> create database test;

mysql> use test;

mysql> create table xx(id int,name varchar(20));

mysql> insert into xx values(1,'tom1');

mysql> insert into xx values(2,'tom2');

1、 xtrabacup进行备份

执行完全备份:

备份命令:

# xtrabackup --defaults-file=/etc/my.cnf --user=root --password="123456" --port=3306 --backup --target-dir=/opt/mysqlbackup/full/full_incre_$(date +%Y%m%d_%H%M%S)

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

其中,--defaults-file指定数据库的配置文件,如果使用该参数必须做为第一个参数;--user指定连接数据库的用户名;--password指定连接数据库的密码;--port指定连接数据库的端口号;--backup 实施备份到target-dir; --target-dir=name 备份文件的存放目录路径。innobackupex要从其中获取datadir等信息;--database指定要备份的数据库,这里指定的数据库只对MyISAM表和InnoDB表的表结构有效,对于InnoDB 数据来说都是全备(所有数据库中的InnoDB数据都进行了备份,不是只备份指定的数据库,恢复时也一样);/opt/mysqlbackup/full/是备份文件的存放位置。

查看完全备份文件

[root@localhost ~]# ls /opt/mysqlbackup/full/ -l

drwxr-x---. 8 root root 4096 Sep 12 22:11 full_incre_20160912_221111

xtrabackup进行增量备份

先录入些数据,实现第一次增量数据:

mysql> use test;

mysql> insert into xx values(3,'tom3');

再进行增量备份1

备份命令:

# xtrabackup --defaults-file=/etc/my.cnf --user=root --password="123456" --port=3306 --backup --target-dir=/opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/full/full_incre_20160912_221111/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

其中,--incremental-basedir指定上次完整备份或者增量备份文件的位置(即如果是第一次增量备份则指向完全备份所在目录,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录)。

查看增量备份文件:

[root@localhost ~]# ls -l /opt/mysqlbackup/inc/

drwxr-x---. 8 root root 4096 Sep 12 22:15 incre_20160912_221510

注:

这里的增量备份其实只针对的是InnoDB,对于MyISAM来说,还是完整备份。

向表中再插入几行数据,继续第二次增量备份

mysql> use test;

mysql> insert into xx values(4,'tom4');

mysql> commit;

进行第二次增量备份

备份命令:

# xtrabackup --defaults-file=/etc/my.cnf --user=root --password="123456" --port=3306 --backup --target-dir=/opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/inc/incre_20160912_221510/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

注:第二次增量备份--incremental-basedir指向上一次增量备份文件的位置。

查看增量备份文件

[root@localhost ~]# ls -l /opt/mysqlbackup/inc/

drwxr-x---. 8 root root 4096 Sep 12 22:15 incre_20160912_221510

drwxr-x---. 8 root root 4096 Sep 12 22:19 incre_20160912_221916

2、 xtrabacup进行增量恢复

为了验证比对,先删除两个增量备份前表里面的数据

mysql> use test;

mysql> delete from xx where id=3;

完整备份恢复:

在进行恢复前,如果完整备份在远程主机上,首先将完整备份复制到本地主机上,如果是tar包,则需要先解包,解包命令为:tar �Cizxf xxx.tar,这里必须使用-i参数(忽略存档中的 0 字节块(通常意味着文件结束))。

开始全备份恢复

命令如下:

# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=root --password="123456" --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20160912_221111/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

恢复到第一次增量的时刻

增量备份恢复的步骤和完整备份恢复的步骤基本一致,只是应用日志的过程稍有不同。增量备份恢复时,是先将所有的增量备份挨个应用到完整备份的数据文件中,然后再将完整备份中的数据恢复到数据库中。

恢复命令:

# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=root --password="123456" --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20160912_221111/ --incremental-dir=/opt/mysqlbackup/inc/incre_20160912_221510/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

恢复到第二次增量备份前面:

恢复命令:

# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=root --password="123456" --apply-log-only --target-dir=/opt/mysqlbackup/full/full_incre_20160912_221111/ --incremental-dir=/opt/mysqlbackup/inc/incre_20160912_221916/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

恢复整个库

恢复命令:

# xtrabackup --defaults-file=/etc/my.cnf --prepare --user=root --password="123456" --target-dir=/opt/mysqlbackup/full/full_incre_20160912_221111/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

然后停止mysql数据库:

[root@localhost ~]# systemctl stop mysqld

开始rsync数据文件:

# cd /opt/mysqlbackup/full/full_incre_20160912_221111/

#rsync -rvt --exclude 'xtrabackup_checkpoints' --exclude 'xtrabackup_logfile' ./ /usr/local/mysql/data/

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。

授予mysql访问权限:

# chown -R mysql:mysql /usr/local/mysql/data/

启动mysql服务:

# systemctl start mysqld

验证

登录mysql,看到以前在备份之后删除的数据已经通过2次增量备份恢复过来了,如下所示:

[root@localhost ~]# mysql -uroot -p123456 -e "select * from test.xx"

+------+------+

| id | name |

+------+------+

| 1 | tom1 |

| 2 | tom2 |

| 3 | tom3 |

| 4 | tom4 |

+------+------+

方案三:innobackupex全库备份+innobackupex增量备份

测试环境准备

创建一个测试数据库,并创建一张表输入几行数据

mysql> create database test2;

mysql> use test2;

mysql> create table yy(id int,name varchar(20));

mysql> insert into yy values(1,'kim1');

mysql> insert into yy values(2,'kim2');

1、innobackupex先做完全备份

命令如下:

# innobackupex --defaults-file=/etc/my.cnf --user=root --password="123456" /opt/mysqlbackup/full/full_incre_$(date +%Y%m%d_%H%M%S) --no-timestamp

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

查看完全备份文件

# ll /opt/mysqlbackup/full/

drwxr-x---. 10 root root 4096 Sep 12 23:52 full_incre_20160912_235237

innobackupex做增量备份

做第一次增量备份

先录入增量数据

mysql> use test2;

mysql> insert into yy values(3,'kim3');

再进行增量备份,命令如下:

# innobackupex --incremental /opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/full/full_incre_20160912_235237/ --user=root --password="123456" --no-timestamp

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

查看增量备份文件

# ll /opt/mysqlbackup/inc/

drwxr-x---. 10 root root 4096 Sep 12 23:56 incre_20160912_235636

基于全备和第一个增量备份来做第二次增量备份

先录入增量数据录入

mysql> use test2;

mysql> insert into yy values(4,'kim4');

开始进行第二次增量备份,备份命令:

# innobackupex --incremental /opt/mysqlbackup/inc/incre_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/opt/mysqlbackup/inc/incre_20160912_235636/ --user=root --password="123456" --no-timestamp

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

查看增量备份文件

# ll /opt/mysqlbackup/inc/

drwxr-x---. 10 root root 4096 Sep 12 23:56 incre_20160912_235636

drwxr-x---. 10 root root 4096 Sep 12 23:59 incre_20160912_235942

2、innobackupex做增量恢复

先删除两次增量数据,用来查看验证恢复结果

mysql> use test2;

mysql> delete from yy where id=3;

开始做恢复,恢复全备份

命令如下:

# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20160912_235237/

部分显示信息如下图所示:

xtrabackup进行MySQL数据库备份/还原

--redo-only 用于准备增量备份内容把数据合并到全备份目录,配合incremental-dir 增量备份目录使用

基于全备份进行第一次增量备份的恢复

命令如下:

# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20160912_235237/ --incremental-dir=/opt/mysqlbackup/inc/incre_20160912_235636/

基于全备份和第一次增量备份,恢复第二次增量备份

命令如下:

# innobackupex --apply-log --redo-only /opt/mysqlbackup/full/full_incre_20160912_235237/ --incremental-dir=/opt/mysqlbackup/inc/incre_20160912_235942/

恢复整个数据库

停止数据库

# systemctl stop mysqld

清空数据目录下所有文件

# mkdir -p /tmp/mysqldatabak

# mv /usr/local/mysql/data/* /tmp/mysqldatabak/

将恢复好的数据按照配置文件的需求拷贝到相应目录

# innobackupex --defaults-file=/etc/my.cnf --user=root --password="123456" --copy-back /opt/mysqlbackup/full/full_incre_20160912_235237/

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。

赋予mysql账号权限

# chown -R mysql:mysql /usr/local/mysql/data/

启动mysql服务

# systemctl start mysqld

登录mysql界面,查看数据是否已经恢复,如下所示:

mysql> use test2;

mysql> select * from yy;

+------+------+

| id | name |

+------+------+

| 1 | kim1 |

| 2 | kim2 |

| 3 | kim3 |

| 4 | kim4 |

+------+------+

附:Xtrabackup的“流”及“备份压缩”功能

Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用--stream选项即可。如:

# innobackupex --user=root --password="123456" --stream=tar /opt/mysqlbackup/full/ | gzip >/opt/mysqlbackup/full/full_`date +%F_%H%M%S`.tar.gz

http://hongge.blog.51cto.com/