xiaolingzi's blog

每天都在成长...

欢迎您:亲

使用xtrabackup(innobackupex)备份还原mysql数据库

xiaolingzi 发表于 2017-05-31 17:53:27

一、背景

随着数据库数据的不断增长,通过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工具的更多参数,请查看官网说明:

https://www.percona.com/doc/percona-xtrabackup/LATEST/innobackupex/innobackupex_option_reference.html


四、增量备份与还原

增量备份是基于完全备份的,所以进行增量备份时需要先进行一次全量备份。

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


      

转载请注明出处:http://www.xxling.com/article/3109.aspx

  • 分类: mysql
  • 阅读: (1408)
  • 评论: (0)
拍砖 取消
请输入昵称
请输入邮箱
*
 选择评论类型
300字以内  请输入评论内容