利用xtrabackup实现MySQL备份,做个记录。
基本原理
xtrabackup 是物理备份工具,直接操作MySQL数据文件。
xtrabackup 以读写方式打开数据文件,这是因为它调用InnoDB库提供的函数打开文件,而后者以读写模式访问数据文件。
xtrabackup 针对数据访问模式进行了优化,
例如,避免OS缓存大量数据,
posix_fadvise(file, 0, 0, POSIX_FADV_DONTNEED)
并进行预读优化
posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL)
数据文件拷贝,一次读写1MB,不可配置。
log文件拷贝,一次读写512字节,不可配置,但Percona Server有一个例外,可以通过innodb_log_block_size修改。
安装配置
OS: CentOS 7
MySQL: mariadb-10.1.20-1.el7.x86_64
XtraBackup: 这里使用 2.3,版本要与数据库匹配。
配置yum源
# yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
查看版本
# yum list | grep percona-xtrabackup
percona-xtrabackup.x86_64 2.3.10-1.el7 percona-release-x86_64
percona-xtrabackup-22.x86_64 2.2.13-1.el7 percona-release-x86_64
percona-xtrabackup-22-debuginfo.x86_64 2.2.13-1.el7 percona-release-x86_64
percona-xtrabackup-24.x86_64 2.4.11-1.el7 percona-release-x86_64
percona-xtrabackup-24-debuginfo.x86_64 2.4.11-1.el7 percona-release-x86_64
percona-xtrabackup-debuginfo.x86_64 2.3.10-1.el7 percona-release-x86_64
percona-xtrabackup-test.x86_64 2.3.10-1.el7 percona-release-x86_64
percona-xtrabackup-test-22.x86_64 2.2.13-1.el7 percona-release-x86_64
percona-xtrabackup-test-24.x86_64 2.4.11-1.el7 percona-release-x86_64
安装xtrabackup
# yum install percona-xtrabackup
创建备份用户和权限
MariaDB [(none)]> CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY 's3cret';
MariaDB [(none)]> GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';
MariaDB [(none)]> FLUSH PRIVILEGES;
备份方式
建议将全量备份和增量备份结合起来。
备份操作的序列
- 一次全量备份
- 每日增量备份
- 适时合并增量
每一个 InnoDB page 包含一个LSN,这个LSN是全局的,增量的,相当于整个数据库的系统版本号。
通过LSN实现增量备份。增量备份实际上不做数据文件比较。只要知道上次备份的LSN,然后就可以执行增量备份,甚至可以完全不访问上次的备份。
在执行backup之后,要进行恢复,需要两步:先prepare,然后restore。
要使数据库达到一致的状态:
对于全量备份,已提交的事务被replay到数据文件,未提交的事务被回滚。
对于增量备份,必须跳过未提交事务的回滚,因为这些事务正在处理中,很可能会在下一次增量备份时提交。xtrabackup 使用 –apply-log-only 只处理log,而不去做事务回滚。
全量备份举例
# xtrabackup --backup --target-dir=/home/bak.201805041300
# cat /home/bak.201805041300/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 89476685861
last_lsn = 89476788005
compact = 0
recover_binlog_info = 0
# xtrabackup --prepare --target-dir=/home/bak.201805041300
增量备份举例
# xtrabackup --backup --target-dir=/home/bak.201805041331 \
--incremental-basedir=/home/bak.201805041300
# cat /home/bak.201805041331/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 89476685861
to_lsn = 89529958032
last_lsn = 89529979375
compact = 0
recover_binlog_info = 0
再次增量备份
# xtrabackup --backup --target-dir=/home/bak.201805041415 \
--incremental-basedir=/home/bak.201805041331
查看一下备份大小
4.1G /home/bak.201805041300/
94M /home/bak.201805041331/
35M /home/bak.201805041415/
进行prepare,合并增量备份
# xtrabackup --prepare --apply-log-only \
--target-dir=/home/bak.201805041300
# xtrabackup --prepare --apply-log-only \
--target-dir=/home/bak.201805041300 \
--incremental-dir=/home/bak.201805041331
# xtrabackup --prepare --target-dir=/home/bak.201805041300 \
--incremental-dir=/home/bak.201805041415
注意,最后一个prepare不需要 –apply-log-only 参数。
然后可以再次做增量备份1,增量备份2,。。。合并增量备份。
# xtrabackup --backup --target-dir=/home/bak.201805041430 \
--incremental-basedir=/home/bak.201805041300
注意事项
- 如果备份到NFS目录,需要nfs的mount选项包含sync。
恢复 restore
# xtrabackup --copy-back --target-dir=/home/bak.201805041300
主要是拷贝的过程,要求 datadir 目录例如/var/lib/mysql/ 为空。
适当配置目录权限。
# chown -R mysql:mysql /var/lib/mysql
备份脚本
最后给出一个自动化的xtrabackup备份脚本,供参考。例如,配置到crond任务,每日执行一次。
脚本初始进行一次全量备份,然后平时进行增量备份。几次增量之后,做一次增量的合并。然后开始下一个增量备份周期。
- 备份以0,1,2,…命名,max配置了增量备份周期。
- dst是目标目录,存放备份。建议放在远程。
#!/bin/bash
dst="/home/backups"
xbk="/usr/bin/xtrabackup"
# 1 base + `max' incrementals
max=7
mkdir -p $dst || exit 1
if [ ! -d $dst/0 ]; then
# create base, 0/
$xbk --backup --target-dir=${dst}/0 || exit $?
$xbk --prepare --apply-log-only --target-dir=${dst}/0 || { ret=$?; rm -rf ${dst}/0; exit $ret; }
exit 0
fi
IFS=$'\n'; for x in $(ls -1 -t $dst); do
unset IFS
# create incremental, 1/, 2/, ..., $max/
$xbk --backup --target-dir=${dst}/$((x+1)) --incremental-basedir=${dst}/$x || { ret=$?; rm -rf ${dst}/$((x+1)); exit $ret; }
if (($x+1 >= $max)); then
break
fi
exit 0
done
# apply the deltas to the base
errdir="error_$(date +%Y%m%d_%H%M%S)"
IFS=$'\n'; for x in $(ls -1 -t -r $dst); do
unset IFS
if (($x == 0)); then
continue
fi
$xbk --prepare --apply-log-only --target-dir=${dst}/0 --incremental-dir=${dst}/$x
if [ $? -ne 0 ]; then
# error occurs and cleanup
mkdir -p $dst/$errdir && mv $dst/[0-9]* $dst/$errdir
exit 1
else
rm -rf ${dst}/$x
fi
done
参考链接
- https://mariadb.com/kb/en/library/percona-xtrabackup/
- https://www.percona.com/doc/percona-xtrabackup/LATEST/installation/yum_repo.html
- https://www.percona.com/doc/percona-xtrabackup/2.4/xtrabackup_bin/implementation_details.html
- https://www.percona.com/doc/percona-xtrabackup/2.4/xtrabackup_bin/implementation_details.html
- https://www.percona.com/doc/percona-xtrabackup/2.4/advanced/lockless_bin-log.html
- https://www.percona.com/doc/percona-xtrabackup/2.4/backup_scenarios/incremental_backup.html
- https://www.percona.com/doc/percona-xtrabackup/2.4/backup_scenarios/full_backup.html#restoring-a-backup