1、什么是XtraBackup
Xtrabackup是由percona公司开发的数据库备份开源软件,一个用于 MySQL 数据库物理热备的备份工具,它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞地备份
Xtrabackup安装完成后有4个可执行文件,其中2个比较重要的备份工具是innobackupex、xtrabackup
1)xtrabackup 是专门用来备份InnoDB表的,和mysql server没有交互;
2)innobackupex 是一个封装xtrabackup的Perl脚本,支持同时备份innodb和myisam,但在对myisam备份时需要加一个全局的读锁。
3)xbcrypt 加密解密备份工具
4)xbstream 流传打包传输工具,类似tar
此文主要介绍innobakcupex的使用和原理
2、XtraBackup可以做什么
- 对InnoDB引擎的表做热备
- 增量备份
- 流压缩传输到另外的服务器上
- 在线移动表
- 更简单的创建从库
- 备份时不增加服务器负载
3、原理
基本原理
XtraBackup对Innodb的备份之所以是热备,无需锁表,是基于Innodb自身的崩溃恢复机制,它首先复制所有的Innodb数据文件,这样复制出来的文件肯定是不一致的,然后对每个文件进行崩溃恢复处理,最终达到一致。就和MySQL在启动Innodb的时候一样,会通过比较数据文件头和redo log文件头信息来检查数据是否是一致的,如果不一致就尝试通过前滚(把redo log中所有提交的事务写入数据文件)和回滚(从数据文件中撤销所有redo log中未提交的事务引起的修改)来使数据达到最终一致。-
备份过程
备份及恢复大致涉及三个步骤:备份 -> prepare -> 恢复
1、备份运行时,工具会记住当时的LSN号(log sequence number日志序列号),并打开xtrabackup_logfile,然后开始对datafile(所有Innodb数据文件)进行copy,即ibdata1及ibd文件。
2、这样复制出来的数据文件是不一致的,所以在复制期间,如果文件被修改(添加删除修改),工具将监视redo log file并将每一次更变记录下来,保存在xtrabackup_logfile中。
3、接下来处理非事务表如MyISAM的备份操作,这时要保证数据的一致性就会先锁表了,innobackupex通过FLUSH TABLES WITH READ LOCK来阻塞DML,
并在此时获取binlog的position[和GTID](此处我理解为和mysqldump --single-transaction处理方式类似)
在做完非事务表的copy之后,执行UNLOCK TABLES,完成备份,并停止记录xtrabackup_logfile。
接下来就是需要做prepare(准备)的过程,该过程类似InnoDB的crash-recovery。
对redo log进行前滚(把redo log中所有提交的事务写入数据文件),并将没提交的事务进行回滚操作(rollback),这样便可以保证数据的一致性,所以对于事务表,整个过程是不会影响写操作的。注:InnoDB、XtraDB、MyISAM是肯定支持的,其他的存储引擎不确定,待测。
4、权限需求
- 操作系统:
对datadir需要有rwx的权限。 - MySQL:
最小所需要的权限有:
RELOAD
LOCK TABLES(如果加上--no-lock的话可以不要)
REPLICATION CLIENT(为了获得binary log的position)
PROCESS(为了执行show engine innodb status,并且需要查看所有运行的线程)
其他可能需要用到的权限:
CREATE TABLESPACE(如果需要通过5.6+ 的TTS恢复/迁移单个表的话)
SUPER(可能需要在复制环境里启动或者停止slave线程)
CREATE\INSERT\SELECT(对PERCONA_SCHEMA.xtrabackup_history进行操作)
5、安装
安装超简单(只能在linux上用,不过但这就够了)戳进 官网选择版本down下来很容易就可以用了。
有RPM包、DEB包、源码包、二进制包。
个人推荐使用二进制包,解压,配置环境变量即可使用,在debian系或RHEL系通用,方便的一比。
解压后设置软链接即可全局使用,实验中有详细说明
6、配置
默认读取my.cnf的选项,读取优先级与MySQL相同。
比如在备份和恢复的时候无需指定datadir等,因为可以读取[mysqld]组下的选项。
同样也可以读取[client]的信息,比如可以将socket,user,password加载到(虽然因为安全因素不建议使用,但是可以这么做)。
当然也可以通过innobackupex --defaults-file=xxxx/my.cnf 去指定将要读取的配置文件。
7、全备
① 备份
innobackupex --user= --password= $basedir [--no-timestamp](当然--user/--password可以直接写作 -u $username -p $password)
若加上--no-timestamp,则不会在所指定的目录里生成一个时间戳目录,而是直接放在所指定的目录里
② prepare(准备)
第二步就是prepare,前文也提到,这个过程类似innodb的crash recovery
也可以理解为是“apply”的过程,这里是全备prepare的命令,十分简单
innobackupex --apply-log $basedir
在--apply-log的时候,可以指定--use-memory,增大其值加快速度,若不指定,默认值为100MB。
③ 恢复到datadir
恢复过程也十分简单(全备和增备都是这一个恢复命令),只需要加上--copy-back参数即可
innobackupex --copy-back $basedir
这样就可以将$basedir的东西恢复到datadir下了,datadir无需指定,将会读取my.cnf获得
- 默认是需要datadir内为空的(或者没有创建),如果要强制写,则需要加参数: --force-non-empty-directories
恢复后需要重新赋权datadir:
chown -R mysql:mysql /home/data/
8、指定数据库备份
① 备份
使用参数 –databases 用于指定要备份的数据库
innobackupex -uroot -p123456 --databases=urpcs /tmp/mysqlbackup
多个数据库备份则为:--databases="dbname1 dbname2"
② prepare(准备)
跟全备一样
innobackupex --apply-log /tmp/mysqlbackup/2018-11-29_15-46-56/
③ 恢复到datadir
停止mysql服务,
删除datadir相关文件
service mysqld stop
rm -rf /home/data/ibdata*
rm -rf /home/data/ib_logfile*
rm -rf /home/data/ib_buffer_pool
rm -rf /home/data/urpcs/ #删除相应数据库
恢复对应数据库
innobackupex --copy-back --force-non-empty-directories /tmp/mysqlbackup/2018-11-29_15-46-56/
chown -R mysql:mysql /home/data/
service mysqld start
9、增量备份
增量备份比起全备要复杂一点,本文也想主要介绍如何做增量备份。
用于有的场景,可能不需要每天对数据做全备。
比如有的场景是,每周做一次全备,每天对做一次增量备份,可以节约磁盘空间也可以减少备份时间。
增备的原理是通过对比LSN的信息,来找到被更变的数据,当有了修改操作时,LSN号会改变,和上一次全备的差异LSN号做对比,则可将差异数据备份出来。
整个过程还是分为三个步骤,备份 -> prepare -> 恢复
① 备份
innobackupex --user= --password= --incremental $new_dir --incremental-basedir=$basedir
备份的差异在目录的xtrabackup_checkpoints中查看:
比如:
$basedir中内容:
backup_type = full-prepared
from_lsn = 0
to_lsn = 304247338
last_lsn = 304247338
compact = 0
recover_binlog_info = 0
$new_bkdir中内容:
backup_type = incremental
from_lsn = 304247338
to_lsn = 304250267
last_lsn = 304250267
compact = 0
recover_binlog_info = 0
可以注意一下增备的from_lsn号
大于这个LSN号的页都是被变更过的,这些偏移量,也就是需要被增量备份出去的
② prepare
prepare过程:
从第一个备份开始(也就是全量)做prepare,再将往后的增量备份依次添加到全量备份中。
注意,此处多了一个参数即--redo-only,该参数是指将已提交的事务应用,未提交的事务回滚。
此外,--incremental-dir也是在之前没有用到过的,这个参数代表需要被合并进去的增量备份目录。
注意,此处多次的增量备份是指:针对上次的增量备份做的增量。
也就是可以理解为:
全备:500GB
第一次增量备份:2GB
第二次增量备份:1GB(针对第一次增量备份的增量数据)
……
第n次
按照备份顺序做prepare,也就是prepare的顺序为:
第一次全备 -> 增量备份1 -> 增量备份2 -> ... -> 增量备份n
第一次全备的prepare:
innobackup --apply-log --redo-only $basedir
第二次prepare:
innobackup --apply-log --redo-only $basedir --incremental-dir=$new_dir_1
(此处的$new_dir_1也就是第一次增量备份)
第n次prepare:
innobackup --apply-log $basedir --incremental-dir=$new_dir_n
(此处的$new_dir_n也就是最近也就是最后一次的增量备份
最后一次增量备份的prepare,不需要指定--redo-only
最后将增量备份和全备进行合并,将未提交的事务回滚,这个操作和全量prepare无异:
innobackup --apply-log $basedir
看起来有点复杂,但没关系,下面会有实验和图解。
③ 恢复到datadir
和全量无异,直接copyback就行了
innobackupex --copy-back $basedir
增量备份的prepare有点蛋疼,还是小结一下:
① prepare完备(加上--redo-only)
② prepare每一次增量备份到完备中,需要加上--redo-only,最后一次增量备份的prepare不需要加--redo-only
③ 对生成的最终完备做--apply-log
10、各参数说明
innobackupex Options 这里只对常用参数进行描述
–defaults-file 数据库的配置文件路径,感觉本地备份不写也可以,远程没测试过。
–apply-log 准备在一个备份上启动mysql服务。
–copy-back 从备份目录拷贝数据,索引,日志到my.cnf文件里规定的初始位置。
–no-timestamp 创建备份时不自动生成时间目录,可以自定义备份目录名例如: /backups/mysql/base
–databases 用于指定要备份的数据库, 多个库文件使用方法: “database1 database2″
–incremental 在全备份的基础上进行增量备份,后跟增量备份存贮目录路径
–incremental-basedir=DIRECTORY 增量备份所需要的全备份路径目录或上次做增量备份的目录路径
–incremental-dir=DIRECTORY 增量备份存贮的目录路径
–redo-only 用于准备增量备份内容把数据合并到全备份目录,配合–incremental-dir 增量备份目录使用。
–force-non-empty-directories 如果是特定库备份还原,不需要删掉整个mysql目录,只是特定库的及相关文件就可以,还原时加上此参数就不会报错。
其他具体参数可以参考:http://www.percona.com/doc/percona-xtrabackup/2.1/innobackupex/innobackupex_option_reference.html
11、实验
-
环境
CentOS Linux release 7.5.1804
mysql 5.1.15 -
准备工作
- 下载Xtrabackup:官网下载地址3
-
官网从2.4.10版本开始是根据libgcrypt定版本的,而我的环境中的是153的,所以我下载的是9的版本,就不考虑这个libgcrypt版本了
- 安装
将下载的包放到任一文件夹然后解压,然后做个软连接全局使用
ln -sf /home/percona-xtrabackup-2.4.9-Linux-x86_64/bin/* /usr/bin/
mysql配置加上socket,当我备份的时候,报错了:
[root@bogon /]# innobackupex -uroot -p123456 --databases=urpcs /tmp/mysqlbackup
181129 15:22:07 innobackupex: Starting the backup operation
IMPORTANT: Please check that the backup run completes successfully.
At the end of a successful backup run innobackupex
prints "completed OK!".
181129 15:22:07 version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup' as 'root' (using password: YES).
Failed to connect to MySQL server as DBD::mysql module is not installed at - line 1327.
181129 15:22:07 Connecting to MySQL server host: localhost, user: root, password: set, port: not set, socket: not set
Failed to connect to MySQL server: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2).
因此需要在/etc/my.cnf加上socker
重启mysql服务生效
在备份之前要安装perl-Digest-MD5,不然会报错
mkdir -p /tmp/mysqlbackup/
yum -y install perl-Digest-MD5
innobackupex --user=root --password=123456 /tmp/mysqlbackup/
不装perl-Digest-MD5报错
-
完全备份&恢复
-
备份
产生以下的备份文件
backup-my.cnf:配置文件备份;
ibdata —— 备份的表空间文件;
-
xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件;
xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置;
xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
xtrabackup_logfile —— 备份的重做日志文件。
-
prepare(准备)
innobackupex --apply-log /tmp/mysqlbackup/2018-11-22_17-41-39/
-
模拟数据库损坏及恢复,恢复前必须先关掉mysqld
- 关闭mysqld
service mysqld stop
- 删除数据库
rm -rf /home/data/*
- 恢复
innobackupex --copy-back /tmp/mysqlbackup/2018-11-22_17-41-39/
- 重新赋权,启动mysql
chown mysql:mysql -R /home/data/
service mysqld start
-
恢复完成
-
增量备份&恢复