今天给大家带来的是Xtrabackup给mysql(mariaDB)备份
一、Xtrabackup
1、Xtrabackup介绍
Percona XtraBackup是开源免费的MySQL数据库热备份软件,它能对InnoDB和XtraDB存储引擎的数据库非阻塞地备份,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具
2、Xtrabackup的特点
(1)在线热备整个库的InnoDB、XtraDB表
(2)备份过程不会打断正在执行的事务;
(3)在xtrabackup的上一次整库备份基础上做增量备份(innodb only)
(4)自动实现备份检验;
(5)以流的形式产生备份,可以直接保存到远程主机上
3、Xtrabackup有两个主要的工具
(1)xtrabackup
xtrabackup的增量备份只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表
(2)innobackupex
innobackupex是参考了InnoDB Hotbackup的innoback脚本修改而来的.innobackupex是一个perl脚本封装,封装了xtrabackup。主要是为了方便的同时备份InnoDB和MyISAM引擎的表,但在处理myisam时需要加一个读锁。并且加入了一些使用的选项。如slave-info可以记录备份恢复后,作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重做slave。
4、增量备份的过程
(1)首先完成一个完全备份,并记录下此时检查点的LSN(Log Sequence Number)。
(2)在进程增量备份时,比较表空间中每个页的LSN是否大于上次备份时的LSN,如果是,则备份该页,同时记录当前检查点的LSN。
首先,在logfile中找到并记录最后一个checkpoint(“last checkpoint LSN”),然后开始从LSN的位置开始拷贝InnoDB的logfile到xtrabackup_logfile;接着,开始拷贝全部的数据文件.ibd;在拷贝全部数据文件结束之后,才停止拷贝logfile。
因为logfile里面记录全部的数据修改情况,所以,即使在备份过程中数据文件被修改过了,恢复时仍然能够通过解析xtrabackup_logfile保持数据的一致。
5、Xtrabackup备份原理
(1)XtraBackup基于InnoDB的crash-recovery功能。它会复制innodb的data file,由于不锁表,复制出来的数据是不一致的,在恢复的时候使用crash-recovery,使得数据恢复一致。
(2)InnoDB维护了一个redo log,又称为transaction log,事务日志,它包含了innodb数据的所有改动情况。当InnoDB启动的时候,它会先去检查data file和transaction log,并且会做二步操作:
①、XtraBackup在备份的时候, 一页一页地复制innodb的数据,而且不锁定表,与此同时,XtraBackup还有另外一个线程监视着transactions log,一旦log发生变化,就把变化过的log pages复制走。为什么要急着复制走呢? 因为transactions log文件大小有限,写满之后,就会从头再开始写,所以新数据可能会覆盖到旧的数据。
②、在prepare过程中,XtraBackup使用复制到的transactions log对备份出来的innodb data file进行crash recovery。
6、实现细节
XtraBackup以read-write模式打开innodb的数据文件,然后对其进行复制。其实它不会修改此文件。也就是说,运行XtraBackup的用户,必须对innodb的数据文件具有读写权限。之所以采用read-write模式是因为XtraBackup采用了其内置的innodb库来打开文件,而innodb库打开文件的时候就是rw的。
7、Xtrabackup的安装
(1)所需软件,直接到percona官网下载即可
1
2
|
percona-toolkit-2.2.4-1.noarch.rpm
percona-xtrabackup-2.1.8-733.rhel6.x86_64.rpm
|
因为percona-toolkit是perl组件,所以会依赖很多perl库,所以选择yum方式安装
二、Xtrabackup完全备份的实现
1、前提准备
(1)创建数据备份目录
1
|
mkdir /backups/
|
(2)修改二进制日志文件存储路径
1
2
|
vim /etc/my.cnf
log-bin=
/mydata/binlogs/master-bin
|
(3)授权一个最小权限的用户进行复制
1
2
|
MariaDB [(none)]> grant reload,lock tables,replication client on *.* to
'backup'
@
'localhost'
identified by
'backup'
;
MariaDB [(none)]> flush privileges;
|
2、完整备份的实现
(1)导入一个数据库,就不自己建库了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
MariaDB [hellodb]>
set
sql_log_bin=0;
#导入数据库过程无需记录二进制日志,把以先暂时关闭
MariaDB [hellodb]>
source
hellodb.sql;
MariaDB [hellodb]> show databases;
+--------------------+
| Database |
+--------------------+
| hellodb |
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
MariaDB [hellodb]>
set
sql_log_bin=1;
#开启二进制日志
|
(2)做完整备份
1
2
3
4
5
6
7
|
innobackupex --user=backup --password=backup --host=localhost /backups/ #做完备
……
……
innobackupex: Backup created
in
directory
'/backups/2014-04-21_11-28-06'
#备份存储路径
innobackupex: MySQL binlog position: filename
'master-bin.000013'
, position 105544
#二进制日志及位置信息
140421 11:28:15 innobackupex: Connection to database server closed
140421 11:28:15 innobackupex: completed OK!
#只有到了这里才说明备份成功
|
看一下备份目录中生成的一些文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@shuishui ~]
# cd /backups/2014-04-21_11-28-06/
[root@shuishui 2014-04-21_11-28-06]
# ll
total 12388
-rw-r--r--. 1 root root 357 Apr 21 11:28 backup-my.cnf
drwxr-xr-x. 2 root root 4096 Apr 21 11:28 hellodb
-rw-r-----. 1 root root 12582912 Apr 21 11:28 ibdata1
drwxr-xr-x. 2 root root 4096 Apr 21 11:28 makingware
drwx------. 2 root root 4096 Apr 21 11:28 mysql
drwxr-xr-x. 2 root root 4096 Apr 21 11:28 performance_schema
drwxr-xr-x. 2 root root 4096 Apr 21 11:28
test
drwxr-xr-x. 2 root root 61440 Apr 21 11:28 ultrax
-rw-r--r--. 1 root root 13 Apr 21 11:28 xtrabackup_binary
-rw-r--r--. 1 root root 27 Apr 21 11:28 xtrabackup_binlog_info
-rw-r-----. 1 root root 89 Apr 21 11:28 xtrabackup_checkpoints
-rw-r-----. 1 root root 2560 Apr 21 11:28 xtrabackup_logfile
[root@shuishui 2014-04-21_11-28-06]
#
|
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命令的目录中。
在备份的同时,innobackupex还会在备份目录中创建如下文件:
(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目录来存储备份数据。
三、使用完全备份恢复数据
1、模拟数据误删除
1
|
rm -rf /mydata/data/*
|
2、准备一个完全备份
一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。
innobackupex命令的--apply-log选项可用于实现上述功能
在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。
1
2
3
4
5
6
7
8
|
innobackupex --apply-log /backups/2014-04-21_11-28-06/
……
……
xtrabackup: starting
shutdown
with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting
shutdown
...
InnoDB: Shutdown completed; log sequence number 1619478
140421 12:33:26 innobackupex: completed OK!
#准备OK
|
注意:不要在备份完成后整理,要在恢复时再去整理
3、从完全备份中恢复数据
在此时恢复数据时,不要启动mysql
innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。
1
2
3
4
|
innobackupex --copy-back /backups/2014-04-21_11-28-06/
……
……
140421 12:40:41 innobackupex: completed OK!
#到了这里就说明恢复成功了
|
查看下数据目录
1
2
3
4
5
6
7
8
9
10
11
|
ll /mydata/data/
total 110676
drwxr-xr-x. 2 root root 4096 Apr 21 12:40 hellodb
-rw-r--r--. 1 root root 12582912 Apr 21 12:40 ibdata1
-rw-r--r--. 1 root root 50331648 Apr 21 12:40 ib_logfile0
-rw-r--r--. 1 root root 50331648 Apr 21 12:40 ib_logfile1
drwxr-xr-x. 2 root root 4096 Apr 21 12:40 makingware
drwxr-xr-x. 2 root root 4096 Apr 21 12:40 mysql
drwxr-xr-x. 2 root root 4096 Apr 21 12:40 performance_schema
drwxr-xr-x. 2 root root 4096 Apr 21 12:40
test
drwxr-xr-x. 2 root root 61440 Apr 21 12:40 ultrax
|
数据是都回来了,可是数据的属主和属组都是root,所以应该将其全部修改为mysql
1
2
3
4
5
6
7
8
9
10
11
12
|
chown -R mysql.mysql /mydata/data/
ll /mydata/data/
total 110676
drwxr-xr-x. 2 mysql mysql 4096 Apr 21 12:40 hellodb
-rw-r--r--. 1 mysql mysql 12582912 Apr 21 12:40 ibdata1
-rw-r--r--. 1 mysql mysql 50331648 Apr 21 12:40 ib_logfile0
-rw-r--r--. 1 mysql mysql 50331648 Apr 21 12:40 ib_logfile1
drwxr-xr-x. 2 mysql mysql 4096 Apr 21 12:40 makingware
drwxr-xr-x. 2 mysql mysql 4096 Apr 21 12:40 mysql
drwxr-xr-x. 2 mysql mysql 4096 Apr 21 12:40 performance_schema
drwxr-xr-x. 2 mysql mysql 4096 Apr 21 12:40
test
drwxr-xr-x. 2 mysql mysql 61440 Apr 21 12:40 ultrax
|
启动mysql服务,连入mysql验证是否正常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
service mysqld start
Starting MySQL [ OK ]
mysql
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| hellodb |
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
|
一个不差,数据完美恢复成功
四、使用innobackupex进行增量备份
每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。
需要注意的是,增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。
1、新建一个数据库,达到数据库发生变化的目的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
MariaDB [(none)]> create database hlbrc;
Query OK, 1 row affected (0.01 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| hellodb |
| hlbrc |
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
|
2、进行第一次增量备份
1
2
3
4
5
6
7
|
innobackupex --incremental /backups/ --incremental-basedir=/backups/2014-04-21_11-28-06/
……
……
innobackupex: Backup created
in
directory
'/backups/2014-04-21_13-11-33'
#增量备份也产生了一个以时间命名的目录
innobackupex: MySQL binlog position: filename
'master-bin.000013'
, position 105667
#记录的二进制日志及位置
140421 13:11:43 innobackupex: Connection to database server closed
140421 13:11:43 innobackupex: completed OK!
#出现OK说明操作成功
|
其中,/backups/2014-04-21_11-28-06/指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backups目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。
如果每一次都相对于上次的完全备份做增量备份,那就是差异备份!
既然完全备份出来的目录是以日期+时间为命名的,而增量备份也是日期+时间命名的,那应该怎么区分这个备份出来的数据目录是完全备份还是增量备份呢
其实也很多简单,只需进入备份出来的目录看一下它的xtrabackup_checkpoints就知道了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
cd /backups/
[root@shuishui backups]
# ls
2014-04-21_11-28-06 2014-04-21_13-11-33
cd 2014-04-21_11-28-06/
ls
backup-my.cnf ib_logfile0 mysql ultrax xtrabackup_checkpoints
hellodb ib_logfile1 performance_schema xtrabackup_binary xtrabackup_logfile
ibdata1 makingware
test
xtrabackup_binlog_info
cat xtrabackup_checkpoints #cat一个这个
backup_type = full-prepared
#这就是完全备份
from_lsn = 0
to_lsn = 1619228
last_lsn = 1619228
compact = 0
|
那再看一下刚才备份出来的那个增量备份的目录中的xtrabackup_checkpoints
1
2
3
4
5
6
|
cat xtrabackup_checkpoints
backup_type = incremental
#这就是增量备份
from_lsn = 1619228
to_lsn = 1619488
last_lsn = 1619488
compact = 0
|
3、第二次增量备份
首先再创建一个数据库,再让数据库变化下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
MariaDB [(none)]> create database bynr;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| bynr |
#第二次增量备份时备份了bynr这个库
| hellodb |
| hlbrc |
#第一次增量备份时备份了hlbrc这个库
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
|
基于上一次增量备份再做增量备份(增量不就是这样吗?不是差异啊!)
1
2
3
4
5
6
7
|
innobackupex --incremental /backups/ --incremental-basedir=/backups/2014-04-21_13-11-33/ #指的目录是上一次增量备份的目录哦
……
……
innobackupex: Backup created
in
directory
'/backups/2014-04-21_13-36-36'
innobackupex: MySQL binlog position: filename
'master-bin.000013'
, position 105788
140421 13:36:45 innobackupex: Connection to database server closed
140421 13:36:45 innobackupex: completed OK!
#看到OK才放心
|
第二次增量备份后又修改了数据库,但此时修改完后还没来得及做增量备份。像这样的情况,如果数据丢失了,在没做增量备份的情况下,就只能依靠二进制日志文件来恢复了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
MariaDB [(none)]> create database hhht;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| bynr |
#第二次增量备份时,备份到了bynr这个库
| hellodb |
| hhht |
#第二次增量备份后,创建了hhht这个库,还没做增量备份
| hlbrc |
#第一次增量备份时,备份到了hlbrc这个库
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
|
五、增量备份的还原
像准备完全备份一样, 增量备份的还原也需要有一个准备的过程
“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:
(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。
(2)基于所有的备份将未提交的事务进行“回滚”。
于是,操作就变成了:
|
接着执行:
|
而后是第二个增量:
|
其中BASE-DIR指的是完全备份所在的目录,
而INCREMENTAL-DIR-1指的是第一次增量备份的目录,
INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作;
1、删除数据目录下的所有文件
|
2、数据还原准备过程
现在备份目录中的情况是这样的,第一个文件夹是完全备份,剩下的那两个是增量备份
|
(1)准备第一次完全备份
|
(2)准备第一次增量备份
|
(3)准备第二次增量备份
|
3、还原数据
(1)经过上面的三步准备,现在终于可以还原数据了,下面就是见证奇迹的时刻
|
(2)查看下恢复回来的数据
经过一次完全和两次增量备份还原,数据已经恢复到了第二次增量备份时的状态
|
(3)使用二进制日志文件做即时点恢复
因为我们在做第二次增量备份后,又修改了数据(创建了数据库hhht),所以数据只能恢复到第二次增量备份时的状态,想要恢复以后的数据就只能依靠二进制日志做即时点恢复了
①、 查看xtrabackup_binlog_info中记录的 mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
|
②、 由于二进制日志是没法直接查看的,所以要先把它导出来,然后再看看里面是否有我们后来创建的hhht数据库
|
③、查看使用二进制日志导出的a.sql
|
确实有刚才创建的hhht数据库,那就是它了。现在把这个二进制日志文件导出来并附加到数据库中
④、启动mysql服务,并附加刚才用二进制日志文件导出的那个数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
service mysqld start #启动mysql服务
mysql
MariaDB [(none)]>
set
sql_log_bin=0;
#暂时关闭二进制日志
MariaDB [(none)]>
source
/mydata/binlogs/a
.sql
#导入数据库
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| bynr |
#bynr库回来了
| hellodb |
| hhht |
#hhht库回来了
| hlbrc |
#hlbrc库也回来了
| information_schema |
| makingware |
| mysql |
| performance_schema |
|
test
|
| ultrax |
+--------------------+
10 rows
in
set
(0.00 sec)
MariaDB [(none)]>
set
sql_log_bin=1;
#再开启二进制日志
|