使用xtrabackup(innobackupex)备份还原mysql数据库
一、背景
随着数据库数据的不断增长,通过mysqldump进行完整备份的时间越来越长。所以当数据库的数据量比较大时就需要把完全备份改为增量备份。
增量备份的方法有很多,比如基于mysql自带的binlog日志进行增量备份。这里我们主要是讲如何通过xtrabackup来进行备份。
二、软件安装
软件的安装官网有相应的教程,可以直接到官网查看,地址如下:
https://www.percona.com/downloads/XtraBackup/LATEST
三、全量备份与还原
xtrabackup包含xtrabackup和innobackupex两个工具,前者支持innodb, xtradb类型的表,后者支持innodb, myisam的表。这里我们主要以innobackupex来进行讲解。
1.全量备份
1)普通备份
innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 /var/backup
其中,--defaults-file为mysql配置文件路径,/var/backup为备份存储目录
2)xbstream压缩备份
innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 --stream=xbstream --compress --extra-lsndir=/var/backup/$(date +%Y%m%d_%H%M%S) /var/backup >/var/backup/full$(date +%Y%m%d_%H%M%S).xbstream
其中--extra-lsndir参数是在需要增量备份时才需要指定,他是存储xtrabackup_checkpoints目录的路径。就是增量备份时要要依赖上一次备份的checkpoints的。
2.全量备份还原
1)普通全量备份还原步骤如下:
#准备备份 innobackupex --apply-log /var/backup/2017-05-19_12-45-26/ #备份还原,执行之前需要先停止mysql服务并删除清空mysql数据目录下的文件。 innobackupex --copy-back /var/backup/2016-09-20_14-45-26/
2)xbstream压缩备份还原步骤如下:
#解压xbstream文件,如果提示目标文件夹不存在,则先新建对应文件夹 xbstream -x < /var/backup/full20170519_134847.xbstream -C /var/backup/full20170519_134847 #进一步解压内部文件,如果提示qpress没有安装,则进行该软件安装即可 innobackupex --decompress /var/backup/full20170519_134847 #准备备份 innobackupex --apply-log /var/backup/full20170519_134847/ #备份还原,执行之前需要先停止mysql服务并删除清空mysql数据目录下的文件。 innobackupex --copy-back /var/backup/full20170519_134847/
文件还原后需要修改文件所有者。
chgrp -R mysql /var/lib/mysql chown -R mysql /var/lib/mysql
关于innobackupex工具的更多参数,请查看官网说明:
四、增量备份与还原
增量备份是基于完全备份的,所以进行增量备份时需要先进行一次全量备份。
1.增量备份
1)普通增量备份
innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 --incremental /var/backup --incremental-basedir=/var/backup/2017-05-19_12-45-26/
其中,--incremental-basedir参数指定上一次备份的目录,第一次增量备份则为全量备份目录,往后就是最新的一次增量备份目录。
2)xbstream压缩备份
innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 --compress --stream=xbstream --extra-lsndir=/var/backup/$(date +%Y%m%d_%H%M%S) --incremental --incremental-basedir=/var/backup/20170519_134847/ /var/backup > /var/backup/inc$(date +%Y%m%d_%H%M%S).xbstream
其中--incremental-basedir目录为备份时--extra-lsndir指定的目录。
2.备份还原
1)普通备份还原步骤如下:
#对全备份进行准备 innobackupex --apply-log --redo-only /var/backup/full20170519_134847 #第一次增量备份 innobackupex --apply-log --redo-only /var/backup/full20170519_134847 --incremental-dir=/var/backup/inc20170519_140254 #第二次增量备份,如果是最后一个增量则不要--redo-only参数 innobackupex --apply-log /var/backup/full20170519_134847 --incremental-dir=/var/backup/inc20170519_141388 #最后再进行一次全量备份准备,最后的全量准备也不要--redo-only参数 innobackupex --apply-log /var/backup/full20170519_134847 #备份还原,执行之前需要先停止mysql服务并删除清空mysql数据目录下的文件。 innobackupex --copy-back /var/backup/full20170519_134847
2)xbstream压缩备份还原
压缩备份还原,只需要将全量和增量备份都解压之后再按普通备份还原的步骤进行即可。解压参看全量备份还原章节。
文件还原后需要修改文件所有者。
chgrp -R mysql /var/lib/mysql chown -R mysql /var/lib/mysql
五、错误解决
1.innobackupex Character set 'utf8mb4' is not a compiled character错误
出现该错误的原因的是我们的mysql配置文件中配置了使用utf8mb4进行连接,而该编码在/usr/share/mysql/charsets/index.xml中不存在。
解决该错误可以通过再mysql配置文件my.cnf添加xtrabackup节点来指定编码为utf8,如下:
[xtrabackup] default-character-set = utf8
当然也可以通过在/usr/share/mysql/charsets/index.xml文件中添加utf8mb4编码节点来解决。
四、完整脚本
为了方便备份和还原,我们将他们写成自动脚本文件。
1.全量备份
全量备份比较简单,主要指定各种存储目录然后执行备份。
#!/bin/bash backup_time=$(date +%Y%m%d_%H%M%S) log_dir="/mnt/mysql_data_bak/bak/logs" log_file="${log_dir}/bak.log" backup_file="/mnt/mysql_data_bak/bak/data/full${backup_time}.xbstream" backup_data_dir="/mnt/mysql_data_bak/bak/data" backup_info_dir="/mnt/mysql_data_bak/bak/info/${backup_time}" user=root password="123456" [ ! -d $backup_data_dir ] && mkdir -p $backup_data_dir [ ! -d $backup_info_dir ] && mkdir -p $backup_info_dir [ ! -d $log_dir ] && mkdir -p $log_dir [ ! -f $log_file ] && touch $log_file innobackupex --defaults-file=/etc/my.cnf --user=${user} --password=${password} --compress --use-memory=1024 --parallel=8 --throttle=400 --stream=xbstream --extra-lsndir=${backup_info_dir} ${backup_data_dir} 2>&1 >> $backup_file reset=$? finish_time=$(date +%Y%m%d_%H%M%S) [ ${reset} -eq 0 ] && echo "${finish_time} bakup finished">> $log_file || echo "${finish_time} bakup failed" >> $log_file
2.增量备份
增量备份需要依赖上次备份,所以执行第一次增量备份之前需要执行一次全量备份。该脚本会自动寻找最近的一次备份作为basedir。
#!/bin/bash backup_time=$(date +%Y%m%d_%H%M%S) log_file="/mnt/mysql_data_bak/bak/logs/bak.log" backup_file="/mnt/mysql_data_bak/bak/data/inc${backup_time}.xbstream" backup_data_dir="/mnt/mysql_data_bak/bak/data" backup_info_dir="/mnt/mysql_data_bak/bak/info" backup_info_subdir="/mnt/mysql_data_bak/bak/info/${backup_time}" user=root password="123456" check_dir=$(ls ${backup_info_dir} |sort -V |tail -n 1) [ ! -d $backup_info_subdir ] && mkdir -p $backup_info_subdir [ ! -d $log_file ] && touch $log_file innobackupex --defaults-file=/etc/my.cnf --user=${user} --password=${password} --compress --use-memory=1024 --parallel=8 --throttle=400 --stream=xbstream --extra-lsndir=${backup_info_subdir} --incremental-basedir=${backup_info_dir}/${check_dir} --incremental ${backup_data_dir} 2>&1 >> $backup_file finish_time=$(date +%Y%m%d_%H%M%S) [ $? -eq 0 ] && echo "${finish_time} bakup finished">> $log_file || echo "${finish_time} bakup failed" >> $log_file
3.还原
该脚本还原的原理是以最旧的一次备份当做全量备份,然后后面的当做增量备份,依次准备还原文件然后回滚。如果全量备份不止一次,那就用最新的一次全量备份和它之后的增量备份进行还原,之前的备份需要删除掉或者移走之后才可以执行该文件进行还原。
特别注意:在删除mysql数据时会有提示确认,一定要看清楚目录路径对不对以免误删文件!!!
#!/bin/bash backup_data_dir="/mnt/mysql_data_bak/bak/data" temp_dir="/mnt/mysql_data_bak/bak/data/temp" mysql_dir="/mnt/mysql_data/mysql" rm -rf $temp_dir mkdir -p $temp_dir file_list=$(ls $backup_data_dir -tr) file_count=0 for filename in $file_list do if [[ $filename == *.xbstream ]] then (( file_count=$file_count+1)) [ ! -d ${temp_dir}/${filename%.*} ] && mkdir -p ${temp_dir}/${filename%.*} xbstream -x < ${backup_data_dir}/${filename} -C ${temp_dir}/${filename%.*} innobackupex --parallel=8 --decompress ${temp_dir}/${filename%.*} fi done if [ $file_count -le 0 ] then echo Nothing to do! exit fi full_dir="" index=0 dir_list=$(ls $temp_dir -tr) echo $dir_list for dir_name in $dir_list do if [ "$full_dir" = "" ] then full_dir=$dir_name fi if [ $file_count -le 1 ] then break fi (( index=$index+1)) if [ "$dir_name" = "$full_dir" ] then echo "innobackupex --apply-log --redo-only ${temp_dir}/${dir_name}" echo continue?[y/n]: read answer innobackupex --apply-log --redo-only ${temp_dir}/${dir_name} else if [ $index -eq $file_count ] then echo "innobackupex --apply-log ${temp_dir}/${full_dir} --incremental-dir=${temp_dir}/${dir_name}" echo continue?[y/n]: read answer innobackupex --apply-log ${temp_dir}/${full_dir} --incremental-dir=${temp_dir}/${dir_name} else echo "innobackupex --apply-log --redo-only ${temp_dir}/${full_dir} --incremental-dir=${temp_dir}/${dir_name}" echo continue?[y/n]: read answer innobackupex --apply-log --redo-only ${temp_dir}/${full_dir} --incremental-dir=${temp_dir}/${dir_name} fi fi done echo "innobackupex --apply-log ${temp_dir}/${full_dir}}" echo continue?[y/n]: read answer innobackupex --apply-log ${temp_dir}/${full_dir} echo All the data is ready for restore, continue?[y/n]: read answer if [ "$answer" = "y" ] then service mysqld stop echo Are you sure to delete [${mysql_dir}], continue?[y/n]: read answer if [ "$answer" = "y" ] then rm -rf ${mysql_dir}/* else exit fi innobackupex --copy-back ${temp_dir}/${full_dir} chgrp -R mysql ${mysql_dir} chown -R mysql ${mysql_dir} service mysqld start fi
- 标签: xtrabackup innobackupex mysql 数据库 备份 还原
- 分类: mysql
- 阅读: (1330)
- 评论: (0)