Xtrabackup 每日增量恢复 – Awaken

HH MySQL313,8906字数 7350阅读24分30秒阅读模式

前言

此恢复程序应该和上次发布的“Xtrabackup每周增量备份脚本程序”配合使用。https://www.ttlsa.com/mysql/xtrabackup-daily-backup/。本程序正式命名为:Awaken

程序用途

对于我个人来说使用每日增量恢复主要是有两个用途:文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  • 用途1:为了验证备份的备份集是否有效,会不会出现备份不可用的情况。
  • 用途2:如果出现了线上误操作,更快的能找出误操作的数据并进行恢复(一般恢复库的数据总是比线上的晚1到2天)。

(提示:用途2的场景你也可以使用mysql主从来实现,通过start slave until等语法 + crontab。这里不多说)文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

程序结构

此程序包含了4个目录(bin、conf、log、var):文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  • bin:存放运行恢复的主脚本程序(*.sh)。
  • conf:存放着程序运行的配置文件变量(*.conf)。
  • log:存放的是恢复时xtrabackup的输出内容(*.log)。
  • var:存放了索引文件(*.index)和错误记录文件(*.err)。
  1. *.index:每当恢复成功后都会记录一条信息到此文件中,此文件也是增量恢复的一个基础文件,当恢复的是增量的备份集,需要到*.index文件中找到第一次全备的记录作为增量恢复的基础。
  2. *.err:每当恢复出错了会记录一条数据到此文件。如果需要对恢复成功与否进行监控,可以通过此文件的变化来判断是否恢复成功(文件无变化就是备份成功了)。

(提示:这边的结果其实是和“Xtrabackup每周增量备份脚本程序”一致)文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

 文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

先决条件

确保你的xtrabackup 程序在机器上已经可以正确使用。文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

注意事项

为了安全请使用root以外的用户来使用本程序,本人专门使用了一个mysql用户来执行mysql相关的操作。文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

程序流程图

awaken

awaken流程

使用方式

一般此程序是配合crontab来每天执行的。文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  • 执行

#         你的程序路径文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

/bin/bash /tmp/xtrabackup_cron/bin/recover.sh文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

(提示:有时候可能需要手动执行recover.sh脚本,可以指定文件/bin/bash recover.sh xx.tar.bz2。其中xx.tar.bz2需要在你配置文件中的备份目录)文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

 文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  • 恢复成功索引文件内容

# 恢复成功 索引文件内容文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

{week_day:3,  dir:full_2015-12-31_20-11-36_4,  type:full,  date:2016-01-01 00:00:00}文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

{week_day:3,  dir:incr_2015-12-31_20-13-50_4,  type:incr,  date:2016-01-01 00:30:00}文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  • 恢复失败错误文件内容

# 恢复失败 索引文件内容文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

{week_day:3, file_name:full_2015-12-31_20-11-36_4.tar.bz2, type:full, date:2016-01-01 00:10:00}文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

{week_day:3, file_name:incr_2015-12-31_20-13-50_4.tar.bz2, type:incr, date:2016-01-01 00:20:00}文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

(提示:其实索引文件的内容格式和错误文件的一样)文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

程序展示

  • 配置文件conf
# 备份路劲
recover_dir=/tmp/recover
 
# 备份路劲文件所在的路径
backup_dir=/tmp/backup
 
# percona-xtrabackup 备份软件路径
xtrabackup_dir=/usr/local/percona-xtrabackup
 
# 恢复几天前的备份
# 0:今天,1:昨天
# 如果选择1,恢复时间是2016-01-01 00:00:00, 恢复的是2015-12-31那一天备份的
# 如果选择0,恢复时间是2016-01-01 00:00:00, 恢复的是2016-01-01那一天备份的,
#           因此可能会报错,因为还没备份。
n_day_ago=1
 
# 全量备信息名称 前缀
full_recover_prefix=full
 
# 增量备信息名称 前缀
increment_prefix=incr
 
# 增量备信息名称 前缀
backup_file_suffix=.tar.bz2
 
# 错误日志文件(更具此文件知道备份是否成功)
# format:
# {week_day:1,file_name:full/incr_2015-12-29_00-00-00_7.tar.bz2,type:full/incr,date:2015-12-30 00:00:00}
error_log=recover.err
 
# 索引文件
# format:
# {week_day:1,dir:full/incr_2015-12-29_00-00-00_7,type:full/incr,date:2015-12-30 00:00:00}
index_file=recover.index
  • 主程序说明

程序说明这里分4个模块来看(主逻辑、变量初始化、检测配置文件正确性、使用的其他方法)文章源自运维生存时间-https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/

  1. 主逻辑
function run() {
  #执行检测配置文件正确性
  test_conf_file
 
  # 备份错误日志文件
  error_log=$program_dir/var/`sed '/^error_log=/!d;s/.*=//' $conf_file`
  # 备份索引文件
  index_file=$program_dir/var/`sed '/^index_file=/!d;s/.*=//' $conf_file`
 
  if [ $# -eq 1 ]; then
    backup_file=$1
  else
    backup_file=''
  fi
 
  # 获得备份文件 可以传参数:full_2015-12-31_20-11-36_4.tar.bz2
  get_backup_file $backup_file
  # 获得恢复文件夹名称
  get_recover_folder $backup_file
  # 获得备份类型
  get_recover_type
  case $recover_type in
    full )
      # 解压备份文件
      tar_file_to_dir $backup_file
      # 应用恢复
      apply_log_full $recover_folder
      # 备份索引文件
      backup_index_file
      # 删除之前的恢复
      delete_before_recover
      # 清楚索引文件
      purge_index_from_file
      # 添加索引文件
      append_index_to_file $recover_folder $recover_type
      ;;
    incr )
      # 解压备份文件
      tar_file_to_dir $backup_file
      # 应用恢复
      apply_log_incr $recover_folder
      # 添加索引文件
      append_index_to_file $recover_folder $recover_type
      ;;
    *    )
      logging_err file_err file_named_err
      exit 2
  esac
}
 
if [ $# -eq 1 ]; then
  run $1
else
  run
fi

2. 变量初始化

# 获得程序路径名
program_dir=`dirname $0`/..
# 读取配置文件中的所有变量值, 设置为全局变量
# 配置文件
conf_file="$program_dir/conf/recover.conf"
# mysql 恢复目录
recover_dir=`sed '/^recover_dir=/!d;s/.*=//' $conf_file`
# mysql 备份目录
backup_dir=`sed '/^backup_dir=/!d;s/.*=//' $conf_file`
# percona-xtrabackup 备份软件路径
xtrabackup_dir=`sed '/^xtrabackup_dir=/!d;s/.*=//' $conf_file`
# 全备是在一周的第几天
n_day_ago=`sed '/^n_day_ago=/!d;s/.*=//' $conf_file`
# mysql 全备前缀标识
full_recover_prefix=`sed '/^full_recover_prefix=/!d;s/.*=//' $conf_file`
# mysql 增量备前缀标识
increment_prefix=`sed '/^increment_prefix=/!d;s/.*=//' $conf_file`
# mysql 增量备前缀标识
backup_file_suffix=`sed '/^backup_file_suffix=/!d;s/.*=//' $conf_file`
# 备份错误日志文件
error_log=`sed '/^error_log=/!d;s/.*=//' $conf_file`
# 备份索引文件
index_file=`sed '/^index_file=/!d;s/.*=//' $conf_file`
 
# 备份日期
recover_date=`date +%F`
# 备份日期
recover_time=`date +%H:%M:%S`
# 备份日期
recover_week_day=`date +%u`
 
# 获得需要恢复的备分日期
backup_date=`date -d "$n_day_ago day ago" +%F`
 
# 创建相关目录
log_dir=$program_dir/log/recover
var_dir=$program_dir/var
mkdir -p $recover_dir
mkdir -p $log_dir
mkdir -p $var_dir

3. 检测配置文件正确性

# 测试配置文件正确性
function test_conf_file() {
  test_ok=0
  # 判断每个变量是否在配置文件中有配置,没有则退出程序
  if [ ! -n "$recover_dir" ]; then echo 'fail: configure file recover_dir not set'; test_ok=1; fi
  if [ ! -n "$backup_dir" ]; then echo 'fail: configure file backup_dir not set'; test_ok=1; fi
  if [ ! -n "$xtrabackup_dir" ]; then echo 'fail: configure file xtrabackup_dir not set'; $test_ok=1; fi
  if [ ! -n "$n_day_ago" ]; then echo 'fail: configure file n_day_ago not set'; test_ok=1; fi
  if [ ! -n "$full_recover_prefix" ]; then echo 'fail: configure file full_backup_prefix not set'; test_ok=1; fi
  if [ ! -n "$increment_prefix" ]; then echo 'fail: configure file increment_prefix not set'; test_ok=1; fi
  if [ ! -n "$backup_file_suffix" ]; then echo 'fail: configure file backup_file_suffix not set'; test_ok=1; fi
  if [ ! -n "$error_log" ]; then echo 'fail: configure file error_log not set'; test_ok=1; fi
  if [ ! -n "$index_file" ]; then echo 'fail: configure file index_file not set'; test_ok=1; fi
  if [ 1 -eq $test_ok ]; then
    logging_err null test_conf_file
    exit 2
  fi
}

4. 使用的其他方法

# 准备全量恢复
function apply_log_full() {
  echo $log_dir/${1}.log
  $xtrabackup_dir/bin/innobackupex \
    --apply-log \
    --redo-only \
    $recover_dir/$1 > $log_dir/${1}.log 2>&1
 
  if [ $? -ne 0 ]; then
    logging_err $backup_file apply_log_err
    exit 2
  fi
}
 
# 准备增量恢复
function apply_log_incr() {
  # 获得增量 base 路径
  get_incr_base
  echo $log_dir/${1}.log
  $xtrabackup_dir/bin/innobackupex \
    --apply-log \
    --redo-only \
    $recover_dir/$base_dir \
    --incremental-dir=${recover_dir}/${1} > $log_dir/${1}.log 2>&1
 
  if [ $? -ne 0 ]; then
    logging_err $backup_file incr_recover_err
    exit 2
  fi
}
 
# 获得增量 base 路径
function get_incr_base() {
  base_dir=`grep 'type:full' $index_file | \
            sed -n '1p' | \
            awk -F '[, {}]*' '{print $3}' | \
            awk -F ':' '{print $2}'`
}
 
# 获得备份文件名
get_backup_file() {
  if [ $# -eq 1 ]; then
    backup_file=`basename $1`
  else
    backup_file=`find $backup_dir -maxdepth 1 -type f -name "*$backup_file_suffix" | \
                 grep $backup_date | \
                 sed -n '$p' | \
                 xargs basename`
  fi
  if [ ! -n "$backup_file" ]; then
    logging_err no_file cannot_find_file 
    exit 2
  fi
}
 
# 获得恢复文件夹名称
get_recover_folder() {
  recover_folder=`basename -s $backup_file_suffix $1`
}
 
# 获得恢复类型
get_recover_type() {
  recover_type=`echo $recover_folder | awk -F '_' '{print $1}'`
  if [ $# -eq 1 ]; then
    recover_type=$1
  elif [ "full" = "$recover_type" ]; then
    recover_type=full
  elif [ "incr" = "$recover_type" ]; then
    recover_type=incr
  else
    logging_err no_file type_not_in_range
    exit 2
  fi
}
 
# 解压文件到恢复目录
function tar_file_to_dir() {
  if [ -d "$recover_dir/$recover_folder" ]; then
    # logging_err $backup_file recover_folder_already_exists
    rm -rf $recover_dir/$recover_folder
  fi
 
  tar -jxf $backup_dir/$1 -C $recover_dir
}
 
# 记录错误日志
function logging_err() {
  error_log=$program_dir/var/`sed '/^error_log=/!d;s/.*=//' $conf_file`
  echo "{week_day:$recover_week_day, \
         file_name:${1}, \
         type:${2}, \
         time:${recover_date} ${recover_time}}" >> $error_log
}
 
# 备份索引文件
function backup_index_file() {
  if [ -f "$index_file" ]; then
    cp $index_file ${index_file}_$(date -d "$n_day_ago day ago" +%F)
  fi
}
 
# 删除之前的备份(一般在全备完成后使用)
function delete_before_recover() {
  cat $index_file | awk -F '[, {}]*' '{print $3}' | \
    awk -v backup_dir=$backup_dir -F ':' '{if($2!=""){printf("rm -rf %s/%s\n", backup_dir, $2)}}' | \
    /bin/bash
 
  cat $index_file | awk -F '[, {}]*' '{print $3}' | \
    awk -v log_dir=$log_dir -F ':' '{if($2!=""){printf("rm -rf %s/%s.log\n", log_dir, $2)}}' | \
    /bin/bash
}
 
# 清空索引
function purge_index_from_file() {
  if [ -f "$index_file" ]; then
    > $index_file
  fi
}
 
# 添加索引, 索引记录了当前最新的备份
function append_index_to_file() {
  echo "{week_day:$recover_week_day, \
         dir:${1}, \
         type:${2}, \
         date:${backup_date}}" >> $index_file
}

在我的机器上我将我的备份文件使用*.tar.bz2的压缩文件,因此我的配置文件的backup_file_suffix=.tar.bz2。你可以更具你自己而定。如果你没有使用压缩文件而是指定备份文件目录则可以将 apply_log_full 和 apply_log_incr 两个方法注释掉。

作者联系方式

谢谢作者的投稿,如有任何疑问可以直接联系作者,以下为联系方式:

昵称:HH

QQ:275258836

附件

awaken下载

 

感觉本文内容不错,读后有收获?

逛逛衣服店,鼓励作者写出更好文章。

weinxin
我的微信
微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~
HH
  • 本文由 发表于 07/01/2016 01:00:08
  • 转载请务必保留本文链接:https://www.ttlsa.com/mysql/xtrabackup-restore-awaken/
评论  3  访客  3
    • chen_hao
      chen_hao

      由于有些用户说需要在备份的时候加上压缩命令方便恢复使用,这边我就添加上了
      在tar_backup_file方法中添加上如下代码
      cd $backup_dir
      tar -jcf ${1}_${backup_date}_${backup_time}_${backup_week_day}.tar.bz2
      ${1}_${backup_date}_${backup_time}_${backup_week_day}
      cd – > /dev/null
      新的程序我放在网盘上 https://yunpan.cn/crF25kgIJWuXS 访问密码 724f

      • cuffs
        cuffs 0

        不错

        • mysql
          mysql 9

        评论已关闭!