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/
在线(热)备份整个库的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保持数据
的一致。
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)备份等,通过复制数据文件,复制日志文件和提交日志到数据文件(前滚)实现了各种复合备份方 式。
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的数据。同样不可以配置。
基于以上原理,xtrabackup 备份恢复工具比较适合数据增长型数据库。对于数据增长型的库,由于数据的增长导致数据备份和恢复的空间和时
间上的压力较大。而xtrabackup有增量备份的功能,在短时间内可以通过进行增量备份来保证数据的安全性。而长期来看,仍然需要间断性的进行全库
备份。此外,由于xtrabackup对innodb的数据库不进行锁定,因此对要求不影响线上服务的数据备份和恢复较适合。
而对于数据量无明显增长,且更新为主的数据更新型数据库,xtrabackup显得过于复杂。xtrabackup操作反而不如mysqldump的性能高。
个人理解:
1、无需停止数据库进行InnoDB热备,快速、可靠的完成备份
2.备份期间不间断事务处理
3.节省磁盘空间和网络带宽
4.自动对备份文件进行验证
5.快速恢复,保障在线运行时间持久性
官方说明:
1.在不停库的情况下,对InnoDB数据库进行热备
2.增量备份MySQL数据库
3.通过流压缩备份MySQL数据到另外一台服务器
4.在线MySQL服务器之间进行表空间迁移
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)
人生是条无名的河,是浅是深都要过;
人生是杯无色的茶,是苦是甜都要喝;
人生是首无畏的歌,是高是低都要唱。