Loading

MySQL物理备份 xtrabackup

MySQL 备份之 xtrabackup | innobackupex

Xtrabackup 介绍

Xtrabackup 是一个对 InnoDB 做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具 InnoDB Hotbackup 的一个很好的
替代品。 
  Xtrabackup有两个主要的工具:xtrabackup、innobackupex 
1、xtrabackup只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表 
2、innobackupex 是参考了 InnoDB Hotbackup 的 innoback 脚本修改而来的.innobackupex 是一个 perl 脚本封装,封装了 xtrabackup。主要
是为了方便的同时备份InnoDB和MyISAM引擎的表,但在处理myisam时需要加一个读锁。并且加入了一些使用的选项。如slave-info可以记录备份
恢复后,作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重做slave。 
3、官方文档:http://www.percona.com/doc/percona-xtrabackup/2.1/ 
A、Xtrabackup是什么?
在线(热)备份整个库的InnoDB、 XtraDB表 
  在xtrabackup的上一次整库备份基础上做增量备份(innodb only) 
  以流的形式产生备份,可以直接保存到远程机器上(本机硬盘空间不足时很有用) 
  MySQL数据库本身提供的工具并不支持真正的增量备份,二进制日志恢复是point-in-time(时间点)的恢复而不是增量备份。Xtrabackup工具支持
对InnoDB存储引擎的增量备份,工作原理如下: 
  (1)首先完成一个完全备份,并记录下此时检查点的LSN(Log Sequence Number)。 
  (2)在进程增量备份时,比较表空间中每个页的LSN是否大于上次备份时的LSN,如果是,则备份该页,同时记录当前检查点的LSN。 
  首先,在 logfile 中找到并记录最后一个 checkpoint(“last checkpoint LSN”),然后开始从 LSN 的位置开始拷贝 InnoDB 的 logfile 到
xtrabackup_logfile;接着,开始拷贝全部的数据文件.ibd;在拷贝全部数据文件结束之后,才停止拷贝logfile。 
  因为logfile里面记录全部的数据修改情况,所以,即时在备份过程中数据文件被修改过了,恢复时仍然能够通过解析xtrabackup_logfile保持数据
的一致。 
B、Xtrabackup 可以做什么?
XtraBackup基于InnoDB的crash-recovery功能。它会复制innodb的data file,由于不锁表,复制出来的数据是不一致的,在恢复的时候使用
crash-recovery,使得数据恢复一致。 
  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。 
官方原理 
在 InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件。事务日志会存储每一个InnoDB表数据的记录修改。当InnoDB启动 时,
InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用(前滚)已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。
 
Xtrabackup 在启动时会记住 log sequence number(LSN),并且复制所有的数据文件。复制过程需要一些时间,所以这期间如果数据文件有改动,
那么将会使数据库处于一个不同的时间点。这 时,xtrabackup会运行一个后台进程,用于监视事务日志,并从事务日志复制最新的修改。Xtrabackup
必须持续的做这个操作,是因为事务日 志是会轮转重复的写入,并且事务日志可以被重用。所以 xtrabackup 自启动开始,就不停的将事务日志中每个
数据文件的修改都记录下来。 
上面就是 xtrabackup 的备份过程。接下来是准备(prepare)过程。在这个过程中,xtrabackup 使用之前复制的事务日志,对各个数据文件执行灾难
恢复(就像mysql刚启动时要做的一样)。当这个过程结束后,数据库就可以做恢复还原了。 
以 上的过程在 xtrabackup 的编译二进制程序中实现。程序 innobackupex 可以允许我们备份 MyISAM 表和 frm 文件从而增加了便捷和功 能。
Innobackupex会启动xtrabackup,直到xtrabackup复制数据文件后,然后执行FLUSH TABLES WITH READ LOCK来阻止新的写入进来并把MyISAM
表数据刷到硬盘上,之后复制MyISAM数据文件,最后释放锁。 
备 份MyISAM和InnoDB表最终会处于一致,在准备(prepare)过程结束后,InnoDB表数据已经前滚到整个备份结束的点,而不是回滚到 xtrabackup
刚开始时的点。这个时间点与执行FLUSH TABLES WITH READ LOCK的时间点相同,所以myisam表数据与InnoDB表数据是同步的。类似oracle的,
InnoDB的prepare过程可以称为 recover(恢复), myisam的数据复制过程可以称为restore(还原)。 
Xtrabackup 和 innobackupex 这两个工具都提供了许多前文没有提到的功能特点。手册上有对各个功能都有详细的介绍。简单介绍下,这些工具提供
了如流 (streaming)备份,增量(incremental)备份等,通过复制数据文件,复制日志文件和提交日志到数据文件(前滚)实现了各种复合备份方 式。
C、Xtrabackup 备份原理
XtraBackup以read-write模式打开innodb的数据文件,然后对其进行复制。其实它不会修改此文件。也就是说,运行XtraBackup的用户,必须
对 innodb 的数据文件具有读写权限。之所以采用 read-write 模式是因为 XtraBackup 采用了其内置的 innodb 库来打开文件,而 innodb 库打开文件
的时候就是rw的。 
  XtraBackup要从文件系统中复制大量的数据,所以它尽可能地使用posix_fadvise(),来告诉OS不要缓存读取到的数据,从而提升性能。因为这些
数据不会重用到了,OS却没有这么聪明。如果要缓存一下的话,几个G的数据,会对OS的虚拟内存造成很大的压力,其它进程,比如mysqld很有可
能被swap出去,这样系统就会受到很大影响了。 
  在备份 innodb page 的过程中,XtraBackup 每次读写 1MB 的数据,1MB/16KB=64 个 page。这个不可配置。读 1MB 数据之后,XtraBackup
一页一页地遍历这 1MB 数据,使用 innodb 的 buf_page_is_corrupted()函数检查此页的数据是否正常,如果数据不正常,就重新读取这一页,最多重
新读取10次,如果还是失败,备份就失败了,退出。在复制transactions log的时候,每次读写512KB的数据。同样不可以配置。 
D、Xtrabackup 实现细节
基于以上原理,xtrabackup 备份恢复工具比较适合数据增长型数据库。对于数据增长型的库,由于数据的增长导致数据备份和恢复的空间和时
间上的压力较大。而xtrabackup有增量备份的功能,在短时间内可以通过进行增量备份来保证数据的安全性。而长期来看,仍然需要间断性的进行全库
备份。此外,由于xtrabackup对innodb的数据库不进行锁定,因此对要求不影响线上服务的数据备份和恢复较适合。 
       而对于数据量无明显增长,且更新为主的数据更新型数据库,xtrabackup显得过于复杂。xtrabackup操作反而不如mysqldump的性能高。 
E、Xtrabackup 应用场景
个人理解: 
    1、无需停止数据库进行InnoDB热备,快速、可靠的完成备份 
    2.备份期间不间断事务处理 
    3.节省磁盘空间和网络带宽 
    4.自动对备份文件进行验证 
    5.快速恢复,保障在线运行时间持久性 
官方说明: 
    1.在不停库的情况下,对InnoDB数据库进行热备 
    2.增量备份MySQL数据库 
    3.通过流压缩备份MySQL数据到另外一台服务器 
4.在线MySQL服务器之间进行表空间迁移
F、Xtrabackup 优势

Xtrabackup 安装

官网下载:https://www.percona.com/downloads/XtraBackup/LATEST/

本文示例安装包下载

下载链接:https://pan.baidu.com/s/1C88-Ninf0cTG3ghBWdMPEw 密码:0kp1

安装软件

[root@Admin ~]# yum install libev -y 

[root@Admin ~]# rpm -ivh percona-xtrabackup-24-2.4.7-2.el6.x86_64.rpm 

Xtrabackup 实例

创建测试数据

建库:mysql> create database ceshi;

建表:mysql> create table users (id int primary key auto_increment,name varchar(20) not null unique,password varchar(100) not null,address 
varchar(200))ENGINE=MyISAM; 

添加数据:mysql> insert into users (id,name,password,address) values (1,'zhang','1234',null),(2,'wang','4321','湖北武汉'), (3,'li','5678','北京海淀'); 

建库:mysql> create database test2;

建表:mysql> create table articles (id int primary key auto_increment,content longtext not null);

添加数据:mysql> insert into articles (id,content) values (11,'hahahahahaha'),(12,'xixixixixix'),(13,'aiaiaiaia'),(14,'hohoahaoaooo');

全库备份与恢复操作过程

创建备份目录:

[root@Admin ~]# mkdir -p /backup/{full_data,dk_data,zl_data}

注:full_data 全库备份目录
       dk_data  单库备份目录
       zl_data   增量备份目录

全库备份(All DB)

官方备份用法说明:

$ innobackupex --defaults-file=/tmp/other-my.cnf --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/ 

官方恢复用法说明:

用法一:$ innobackupex --apply-log /path/to/BACKUP-DIR 
用法二:$ innobackupex --apply-log --use-memory=4G /path/to/BACKUP-DIR

注:--use-memory=4G 该参数在 prepare 的时候使用,控制 prepare 时 innodb 实例使用的内存量

全库备份操作步骤:

第一步:执行备份全库命令

[root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 /backup/full_data
 注:--defaults-file:默认配置文件的路径,如果不该参数,xtrabackup 将从依次从以下位置查找配置文件/etc/my.cnf、/etc/mysql/my.cnf、/usr/local/etc/my.cnf、 ~/.my.cnf,并读取配置文件中的[mysqld]和[xtrabackup]配置段。[mysqld]中只需要指定datadir、innodb_data_home_dir、innodb_data_file_path、innodb_log_group_home_dir、innodb_log_files_in_group、innodb_log_file_size6个参数即可让xtrabackup正常工作。
     --user:授权的数据库用户
     --password:数据库用户的密码
     --target-dir=name备份文件的存放目录路径(即:/backup/full_data )

第二步:恢复准备:

[root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 --apply-log /backup/full_data/2018-10-18_20-58-04

第三步:停库:

[root@Admin ~]# /etc/init.d/mysqld stop

第四步:把备份文件拷贝至原数据目录下并授权:

[root@Admin ~]# rm -rf /data/DB/*        # 把数据目录删除测试

[root@Admin ~]# cp /backup/full_data/2018-10-18_20-58-04/* /data/DB/

[root@Admin ~]# chown -R mysql. /data/DB/

第五步:重启数据库:

[root@Admin ~]# /etc/init.d/mysqld start

第六步:查看数据:

mysql> show databases;

mysql> use ceshi;

mysql> show tables;

mysql> select * from users;

单库备份与恢复操作过程

单库备份跟全库用法是一样的,只不过单库在备份里,要指定要备份的数据库名,即: --databases=LIST

单库备份操作步骤:

全量备份:

[root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 --database=ceshi /backup/dk_data
注:如果是备份从库的话,需要添加参数:--slave-info,即:
[root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 --slave-info --database=ceshi /tmp

删除ceshi库,方便后面测试是否恢复成功:

mysql> drop database ceshi;

恢复单库操作步骤:

  • 1) 关闭数据库
    [root@Admin ~]# /etc/init.d/mysqld stop
  • 2) 恢复日志文件   apply-log
    [root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 --apply-log /backup/dk_data/2018-10-18_21-10-51
  • 3) 把备份文件拷贝至原数据目录下
    [root@Admin ~]# cp -ap /backup/dk_data/2018-10-18_21-10-51/ceshi/ /data/DB/
  • 4) 检查数据目录的所有者和权限是否正确
    [root@Admin ~]# chown -R mysql. /data/DB/ 
  • 5) 重启 mysql
    [root@Admin ~]# /etc/init.d/mysqld start
  • 6) 检查数据
    mysql> show databases;
    
    mysql> use ceshi;
    
    mysql> show tables;
    
    mysql> select * from users;
    
    mysql> show create table users\G

单库增量备份与恢复操作过程

单库增量备份操作步骤:

增量的备份:

  • 1)首先对单库执行一次全备
    [root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 --database=ceshi /backup/dk_data/
  • 2)插入数据
    mysql> select * from users;
    mysql> insert into users (id,name,password,address) values (4,'liu','1122',null),(5,'zou','4311','湖南长沙'), (6,'zhou','6789','北京八 宝山'), (7,'ding','7891','深圳西丽');
  • 3)  对单库进行增量备份
    [root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123  --database=ceshi --incremental --incremental-basedir=/backup/dk_data/2018-10-18_21-33-20 /backup/zl_data
    注: --incremental 指备份类型为增量备份,做增量备份之前首先要做一次全量备份,所以 
         --incremental-basedir=/backup/dk_data/2014-05-30_23-26-22  的目录 就是--incremental-basedir=BASEDIR  
         /backup/zl_data就是 --incremental-basedir=INCREMENTAL-DIR-1 
         INCREMENTAL-DIR-1是指第一次的增量备份,INCREMENTAL-DIR-2是指第二次的增量备份,以此类推。

增量的恢复:

  • 1) 关闭数据库
    [root@Admin ~]# /etc/init.d/mysqld stop
  • 2) 恢复全备份日志文件(回滚未完成的日志)
    [root@Admin ~]# innobackupex --defaluts-file=/etc/my.cnf --user=root --password=123 --apply-log --redo-only /backup/dk_data/2018-10-18_21-33-20
    加选项:--apply-log-only作用是:只应用redo log,不对数据的rollback,起到先合并事务日志# 
  • 3) 恢复增量备份日志文件
    [root@Admin ~]# innobackupex --defaluts-file=/etc/my.cnf --user=root --password=123 --apply-log --red-only /backup/dk_data/2018-10-18_21-33-20 --incremental-dir=/backup/zl_data/2018-10-18_22-17-33
    注:其中BASE-DIR是指全备目录,INCREMENTAL-DIR-1是指第一次的增量备份,INCREMENTAL-DIR-2是指第二次的增量备份,以此类推。 
     BASE-DIR:/backup/dk_data/2014-05-30_11-56-51 
     INCREMENTAL-DIR-1:/backup/zl_data/2014-05-31_03-01-33 
     以上语句执行成功之后,最终数据在BASE-DIR(即全备目录)下 
  • 4) 恢复增量备份数据文件(拷贝数据)
    [root@Admin ~]# \cp -afp /backup/dk_data/2018-10-18_21-33-20/* /data/DB/
  • 5) 授权
    [root@Admin ~]# chown -R mysql. /data/DB/
  • 6) 启动数据库
    [root@Admin ~]# /etc/init.d/mysqld start
  • 7) 检查数据
    mysql> show databases;
    
    mysql> select * from ceshi.users;

使用innobackupex 加 binlog 日志恢复数据到最新

创建测试数据

建库:mysql> create database db01;
建表:mysql> create table db01.t1(id int, name varchar(10)) engine=myisam;
增加数据:mysql> insert into db01.t1 values(1,'mona');

建表:mysql> create table db01.t2(id int, name varchar(10)) engine=innodb;
增加数据:mysql> insert into db01.t2 values(2,'tom');

查看当前表里的数据

mysql> select * from t1;
+------+------+
| id   | name |
+------+------+
|    1 | mona |
+------+------+
1 row in set (0.02 sec)

mysql> select * from t2;
+------+------+
| id   | name |
+------+------+
|    2 | tom  |
+------+------+
1 row in set (0.00 sec)

开启二进制日志

[root@Admin ~]# vim /etc/my.cnf
log-bin=mysql-bin

[root@Admin ~]# /etc/init.d/mysqld restart

备份操作步骤:

1、创建备份目录

[root@Admin ~]# mkdir -p /backup/innobackupex

2、使用innobackupex对数据库做全库备份

[root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123 /backup/innobackupex/

3、数据库更新

mysql> insert into db01.t1 values(2,'jack');

mysql> insert into db01.t2 values(2,'aaa');

mysql> update db01.t1 set name='harry' where id=1;

查看数据

mysql> select * from t1;
+------+-------+
| id   | name  |
+------+-------+
|    1 | harry |
|    2 | jack  |
+------+-------+
2 rows in set (0.00 sec)

mysql> select * from t2;
+------+------+
| id   | name |
+------+------+
|    2 | tom  |
|    2 | aaa  |
+------+------+
2 rows in set (0.00 sec)

4、预备过程

[root@Admin ~]# innobackupex --apply-log /backup/innobackupex/2018-10-19_12-13-06/

5、备份二进制日志

查看备份目录里面的日志文件是从哪里开始记录的,再做相应的备份
[root@Admin ~]# cat /backup/innobackupex/2018-10-19_12-13-06/xtrabackup_binlog_info mysql-bin.000004 1119 [root@Admin ~]# mysqlbinlog --start-position=1119 /data/DB/mysql-bin.000004 > /backup/innobackupex/update.sql 这里备份只是备份改变后的数据就可以了

6、恢复演练

  • 1> 删除所有的数据文件
    [root@Admin ~]# rm -rf /data/DB/*
  • 2> 停止数据库
    [root@Admin ~]# killall -9 mysqld
  • 3> 使用innobackupex做恢复
    [root@Admin ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back /backup/innobackupex/2018-10-19_12-13-06/
  • 4> 数据目录权限恢复
    [root@Admin ~]# chown mysql. /data/DB/ -R
  • 5> 启动数据库查并查看恢复数据
    [root@Admin ~]# /etc/init.d/mysqld start
    
    恢复后可以看见数据库里面的文件是最初始化时候的,也就是备份完成时的内容
    mysql> select * from db01.t1;
    +------+------+
    | id   | name |
    +------+------+
    |    1 | mona |
    +------+------+
    1 row in set (0.00 sec)
    
    mysql> select * from db01.t2;
    +------+------+
    | id   | name |
    +------+------+
    |    2 | tom  |
    +------+------+
    1 row in set (0.00 sec)
  • 6> 使用binlog日志恢复到最新状态
    可以直接在数据库里面source备份的日志文件(因为备份的日志文件里面是sql语句)
    mysql> source /backup/innobackupex/update.sql
    
    恢复完成后再次查看数据,可以发现已经恢复到最新状态的数据
    mysql> select * from db01.t2;
    +------+------+
    | id   | name |
    +------+------+
    |    2 | tom  |
    |    2 | aaa  |
    +------+------+
    2 rows in set (0.00 sec)
    
    mysql> select * from db01.t1;
    +------+-------+
    | id   | name  |
    +------+-------+
    |    1 | harry |
    |    2 | jack  |
    +------+-------+
    2 rows in set (0.00 sec)

     

 

posted @ 2018-10-19 14:26  别来无恙-  阅读(1813)  评论(0编辑  收藏  举报