Xtrabackup备份恢复原理是什么

46次阅读
没有评论

共计 10267 个字符,预计需要花费 26 分钟才能阅读完成。

这篇文章给大家介绍 Xtrabackup 备份恢复原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

一、Xtrabackup 备份恢复原理
  备份 innodb 表时,xtrabackup 若干个线程拷贝独立表空间的.ibd 文件,并不停监视此过程中 redo log 的变化,添加到自己的事务日志文件(xtrabackup_logfile)中。在此过程中,发生的
物理写操作越多,xtrabackup_logfile 越大。在拷贝完成后的第一个 prepare 阶段,xtrabackup 采用类似于 innodb 崩溃恢复的方法,把数据文件恢复到与日志文件一致的状态,并把未提交的事
务回滚。如果同时需要备份 myisam 表以及 innodb 表结构等文件,那么就需要用 flush tables with lock 来获得全局锁,开始拷贝这些不再变化的文件,同时获得 binlog 位置,拷贝结束后释放锁,
也停止对 redo log 的监视。
  很多同学对上面的理解有混淆,以为拷贝.ibd 文件就跟操作系统拷贝文件一样。其实这里涉及到 fractured page 的问题,他应该会重新读取(应该也有重试次数,超过后备份不成功)。
  其实这个原理很简单,了解下 doublewrite 就可以理解了“本段摘录自《MySQL 技术内幕:InnoDB 存储引擎》”:
  如果说插入缓冲带给 InnoDB 存储引擎的是性能,那么两次写带给 InnoDB 存储引擎的是数据的可靠性。当数据库宕机时,可能发生数据库正在写一个页面,而这个页只写了一部分(比如 16K 的
页,只写前 4K 的页)的情况,我们称之为部分写失效(partial page write)。在 InnoDB 存储引擎未使用 double write 技术前,曾出现过因为部分写失效而导致数据丢失的情况。
  有人也许会想,如果发生写失效,可以通过重做日志进行恢复。这是一个办法。但是必须清楚的是,重做日志中记录的是对页的物理操作,如偏移量 800,写“aaaa”记录。如果这个页本身
已经损坏,再对其进行重做是没有意义的。这就是说,在应用(apply)重做日志前,我们需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是 doublewrite。

二、备份脚本    
#!/bin/sh
#===================================================================================================
## 备份工具:
##  percona-xtrabackup-2.2.6
##
## 备份策略:
##  (1)、每天凌晨 04:20 点进行全量备份一次;
##  (2)、每隔 1 小时增量备份一次;
##
#===================================================================================================
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
 
## DB 备份基路径
BACKUP_BASE_DIR= /data/mysql_backup
 
## 增量备份时,用到的基准目录列表文件
## 内容格式:基准目录 | 本次备份目录 | 备份类型【full|inc】
INC_BASE_LIST= ${BACKUP_BASE_DIR}/incremental_basedir_list.txt
 
## 备份工具路径
XTRABACKUP_PATH= /usr/local/xtrabackup/bin/innobackupex
 
## MySQL 配置路径
MYSQL_CNF_PATH= /etc/my.cnf
 
## 线程数
THREAD_CNT=6
 
#===================================================================================================
function print_help_info()
{
  echo ————————————————————–
  echo Usage: $0 full | inc | help
  echo ————————————————————–
  echo
  exit 1
}
 
[[$# -lt 1]] print_help_info
[[-d ${BACKUP_BASE_DIR} ]] || mkdir -p ${BACKUP_BASE_DIR}
 
## xtrabackup 基础套件不存在时,进行自动下载安装
if [[! -e ${XTRABACKUP_PATH} ]]; then
  cd /usr/local
  wget -q -O xtrabackup-2.2.6.tgz http://www.percona.com/redir/downloads/XtraBackup/LATEST/binary/tarball/percona-xtrabackup-2.2.6-5042-Linux-x86_64.tar.gz
  tar xvzf xtrabackup-2.2.6.tgz /dev/null 2 1 rm -f xtrabackup-2.2.6.tgz
  mv percona-xtrabackup-2.2.6-Linux-x86_64 xtrabackup-2.2.6
  rm -rf xtrabackup ln -s xtrabackup-2.2.6 xtrabackup
   
  for FNAME in `ls -1t /usr/local/xtrabackup/bin`
  do
  rm -f /usr/bin/${FNAME} ln -s /usr/local/xtrabackup/bin/${FNAME} /usr/bin/${FNAME}
  done
fi
 
## 只允许一个副本运行,以避免全量备份与增量备份出现交叉,发生数据错乱的可能性
##[[-n `ps uax | grep innobackupex | grep -v grep`]] exit 1
 
## 目录名默认精确到分钟,为避免意外情况,导致备份任务失败,可以精确到秒
CURRENT_BAK_PATH= ${BACKUP_BASE_DIR}/ `date +%F_%H-%M`
[[-d ${CURRENT_BAK_PATH} ]] CURRENT_BAK_PATH= ${BACKUP_BASE_DIR}/ `date +%F_%H-%M-%S`
 
#===================================================================================================
## 全量备份
if [[$1 == full]]; then
  ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
  echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
 
## 增量备份
elif [[$1 == inc]]; then
  ## 基准目录列表文件不存在或者为空的情况,需要做一次全量备份
  if [[! -f ${INC_BASE_LIST} || `sed /^$/d ${INC_BASE_LIST} | wc -l` -eq 0 ]]; then
  ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
  echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
   
  ## 不存在任何目录的情况,需要做一次全量备份,以避免增量备份失败
  elif [[`find ${BACKUP_BASE_DIR} -maxdepth 1 -type d | wc -l` -eq 1 ]]; then
  ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
  echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
   
  ## 在上一次备份的基础上,进行增量备份
  else
  PREV_BACKUP_DIR=`sed /^$/d ${INC_BASE_LIST} | tail -1  | awk -F | {print $2} `
  ## 上次的备份目录不存在或者目录为空的情况,以避免人为删除的可能性【针对部分恶意删除的情况,目前还没有较好的检查方法】
  if [[! -d ${PREV_BACKUP_DIR} || -z `ls ${PREV_BACKUP_DIR}` ]]; then
  ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
  echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
  else
  ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp –incremental ${CURRENT_BAK_PATH} –incremental-basedir=${PREV_BACKUP_DIR}
  echo ${PREV_BACKUP_DIR}|${CURRENT_BAK_PATH}|inc ${INC_BASE_LIST}
  fi
  fi
 
elif [[$1 == help]]; then
  print_help_info
 
else
  print_help_info
fi
 
## 删除 2 周前的数据备份
rm -rf ${BACKUP_BASE_DIR}/`date -d 14 days ago + %F `_*
sed -i /`date -d 14 days ago + %F `/d ${INC_BASE_LIST}
 
#===================================================================================================
##The End
 
####################################################################################################
## 需要添加的 crontab 信息:
##  (1)、全量备份
##  20 04 * * * /data/scripts/mysql_backup.sh full /dev/null 2 1
##
##  (2)、增量备份
##  00 * * * * /data/scripts/mysql_backup.sh inc /dev/null 2 1
##
####################################################################################################
 
####################################################################################################
## DB 数据恢复步骤:
##  (1)、应用基准
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log –redo-only /data/mysql_backup/full
##
##  (2)、应用第一个增量备份
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log –redo-only /data/mysql_backup/full –incremental-dir=/data/mysql_backup/inc_one
##
##  (3)、应用第二个增量备份
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log /data/mysql_backup/full –incremental-dir=/data/mysql_backup/inc_two
##
##  (4)、再次应用基准
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log /data/mysql_backup/full
##
##  (5)、恢复
##  innobackupex –user=root –defaults-file=/etc/my.cnf –copy-back /data/mysql_backup/full
####################################################################################################

三、效果展示

# cat mysql_backup.sh

#!/bin/sh
#===================================================================================================
## 备份工具:
##  percona-xtrabackup-2.2.6
##
## 备份策略:
##  (1)、每天凌晨 04:20 点进行全量备份一次;
##  (2)、每隔 1 小时增量备份一次;
##
#===================================================================================================
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

## DB 备份基路径
BACKUP_BASE_DIR= /data/mysql_backup

## 增量备份时,用到的基准目录列表文件
## 内容格式:基准目录 | 本次备份目录 | 备份类型【full|inc】
INC_BASE_LIST= ${BACKUP_BASE_DIR}/incremental_basedir_list.txt

## 备份工具路径
XTRABACKUP_PATH= /usr/local/xtrabackup/bin/innobackupex

## MySQL 配置路径
MYSQL_CNF_PATH= /etc/my.cnf

## 线程数
THREAD_CNT=6

#===================================================================================================
function print_help_info()
{
   echo ————————————————————–
   echo Usage: $0 full | inc | help
   echo ————————————————————–
   echo
   exit 1
}

[[$# -lt 1]] print_help_info
[[-d ${BACKUP_BASE_DIR} ]] || mkdir -p ${BACKUP_BASE_DIR}

## xtrabackup 基础套件不存在时,进行自动下载安装
if [[! -e ${XTRABACKUP_PATH} ]]; then
   cd /usr/local
   wget -q -O xtrabackup-2.2.6.tgz http://www.percona.com/redir/downloads/XtraBackup/LATEST/binary/tarball/percona-xtrabackup-2.2.6-5042-Linux-x86_64.tar.gz
   tar xvzf xtrabackup-2.2.6.tgz /dev/null 2 1 rm -f xtrabackup-2.2.6.tgz
   mv percona-xtrabackup-2.2.6-Linux-x86_64 xtrabackup-2.2.6
   rm -rf xtrabackup ln -s xtrabackup-2.2.6 xtrabackup
   
   for FNAME in `ls -1t /usr/local/xtrabackup/bin`
   do
     rm -f /usr/bin/${FNAME} ln -s /usr/local/xtrabackup/bin/${FNAME} /usr/bin/${FNAME}
   done
fi

## 只允许一个副本运行,以避免全量备份与增量备份出现交叉,发生数据错乱的可能性
##[[-n `ps uax | grep innobackupex | grep -v grep`]] exit 1

## 目录名默认精确到分钟,为避免意外情况,导致备份任务失败,可以精确到秒
CURRENT_BAK_PATH= ${BACKUP_BASE_DIR}/ `date +%F_%H-%M`
[[-d ${CURRENT_BAK_PATH} ]] CURRENT_BAK_PATH= ${BACKUP_BASE_DIR}/ `date +%F_%H-%M-%S`

#===================================================================================================
## 全量备份
if [[$1 == full]]; then
   ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
   echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}

## 增量备份
elif [[$1 == inc]]; then
   ## 基准目录列表文件不存在或者为空的情况,需要做一次全量备份
   if [[! -f ${INC_BASE_LIST} || `sed /^$/d ${INC_BASE_LIST} | wc -l` -eq 0 ]]; then
     ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
     echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
   
   ## 不存在任何目录的情况,需要做一次全量备份,以避免增量备份失败
   elif [[`find ${BACKUP_BASE_DIR} -maxdepth 1 -type d | wc -l` -eq 1 ]]; then
     ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
     echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
   
   ## 在上一次备份的基础上,进行增量备份
   else
     PREV_BACKUP_DIR=`sed /^$/d ${INC_BASE_LIST} | tail -1  | awk -F | {print $2} `
     ## 上次的备份目录不存在或者目录为空的情况,以避免人为删除的可能性【针对部分恶意删除的情况,目前还没有较好的检查方法】
     if [[! -d ${PREV_BACKUP_DIR} || -z `ls ${PREV_BACKUP_DIR}` ]]; then
       ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp ${CURRENT_BAK_PATH}
       echo NULL|${CURRENT_BAK_PATH}|full ${INC_BASE_LIST}
     else
       ${XTRABACKUP_PATH} –user=root –defaults-file=${MYSQL_CNF_PATH} –parallel=${THREAD_CNT} –no-timestamp –incremental ${CURRENT_BAK_PATH} –incremental-basedir=${PREV_BACKUP_DIR}
       echo ${PREV_BACKUP_DIR}|${CURRENT_BAK_PATH}|inc ${INC_BASE_LIST}
     fi
   fi

elif [[$1 == help]]; then
   print_help_info

else
   print_help_info
fi

## 删除 2 周前的数据备份
rm -rf ${BACKUP_BASE_DIR}/`date -d 14 days ago + %F `_*
sed -i /`date -d 14 days ago + %F `/d ${INC_BASE_LIST}

#===================================================================================================
##The End

## 需要添加的 crontab 信息:
##  (1)、全量备份
##  20 04 * * * /data/scripts/mysql_backup.sh full /dev/null 2 1
##
##  (2)、增量备份
##  00 * * * * /data/scripts/mysql_backup.sh inc /dev/null 2 1

## DB 数据恢复步骤:
##  (1)、应用基准
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log –redo-only /data/mysql_backup/full
##
##  (2)、应用第一个增量备份
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log –redo-only /data/mysql_backup/full –incremental-dir=/data/mysql_backup/inc_one
##
##  (3)、应用第二个增量备份
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log /data/mysql_backup/full –incremental-dir=/data/mysql_backup/inc_two
##
##  (4)、再次应用基准
##  innobackupex –user=root –defaults-file=/etc/my.cnf –use-memory=8G –apply-log /data/mysql_backup/full
##
##  (5)、恢复
##  innobackupex –user=root –defaults-file=/etc/my.cnf –copy-back /data/mysql_backup/full

关于 Xtrabackup 备份恢复原理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-19发表,共计10267字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)