【增量备份】使用xtrabackup每天一个增量一周一个全量备份

127

【增量备份】使用xtrabackup每天一个增量一周一个全量备份

前置知识铺垫

备份类型

  • 物理备份
    直接对mysql的数据存储目录data进行备份
    优点:备份速度和恢复速度快,
    缺点:恢复数据对环境和mysql版本有要求,最好保证操作系统环境和mysql版本一致的情况下进行恢复,否则有可能恢复失败
  • 逻辑备份
    将mysql数据转换成sql语句进行备份
    优点:可读性高,大版本一致情况下,在不同操作系统上进行恢复,基本上恢复不会出现问题
    缺点:备份速度慢

xtrabackup属于是物理备份,所以备份工作只能在mysql所在的服务器上进行

脚本执行的必要条件

  1. 电脑上安装了docker(脚本中xtrabackup运行在docker容器中)
  2. 修改脚本前几行的配置信息
  3. 保证xtrabackup版本能够兼容mysql的版本,具体可以在xtrabackup官网找到版本对应关系
    https://docs.percona.com/percona-xtrabackup/8.0/
    WeChat3ac997dc97f2b093bf1181dac2a84f97.jpg

配置描述

参数示例值说明
MYSQL_HOST192.168.20.30mysql服务的host,不要填127.0.0.1,容器内的127.0.0.1和宿主机ip不一样,最好填写宿主机的局域网ip
MYSQL_PORT3307宿主机mysql的端口
MYSQL_USERrootmysql的用户名
MYSQL_PWD123456mysql的密码
HOST_MYSQL_DATA_DIR/mysql/data宿主机的mysql数据存储目录
HOST_BACKUP_WORK_DIR/backup/data准备一个目录,作为备份的工作目录,备份日志、打包备份的压缩文件等,都会保存在该目录下
XTRABACKUP_VERSION8.2xtrabackup的版本号
BARK_URLhttps://api.day.app/xxxxxbark的通知服务域名,用于备份失败时,发送通知,具体设置见bark官网,https://bark.day.app/

脚本内容

#!/bin/bash

# 配置部分
MYSQL_HOST="192.168.20.30"
MYSQL_PORT="3307"
MYSQL_USER="root"
MYSQL_PWD="12345678"
HOST_MYSQL_DATA_DIR="/Users/macos/Desktop/docker/mysql/data"   # 宿主机MySQL 数据目录
HOST_BACKUP_WORK_DIR="/Users/macos/Downloads/backup-test/data" # 宿主机备份的工作目录
XTRABACKUP_VERSION="8.2"
BARK_URL="https://api.day.app/xxxxx" # 使用bark进行备份通知,如果失败了会发送通知








# ==========开始备份==========
DATE=$(date +%Y%m%d%H%M%S) # 当前时间
HOST_FULL_BACKUP_DIR="$HOST_BACKUP_WORK_DIR/full"
HOST_LOG_DIR="$HOST_BACKUP_WORK_DIR/logs"
HOST_TAR_DIR="$HOST_BACKUP_WORK_DIR/tar"
HOST_INC_BASE_DIR="$HOST_BACKUP_WORK_DIR/inc-base-dir" # 用于做增量备份时的基础对比目录[软链接]


# 声明一个名为 print_message 的函数
print_log() {
  echo "[$(date +'%F %T')] $1" >> $LOG_FILE
}

main() {
  # 每周天做全量备份,那么周天的时候就清除掉旧全量和增量
  if [ "$(date +%u)" -eq 7 ]; then
    rm -rf $HOST_FULL_BACKUP_DIR
    rm -rf $HOST_BACKUP_WORK_DIR/inc
  fi

  # 创建备份目录
  mkdir -p $HOST_LOG_DIR
  mkdir -p $HOST_TAR_DIR
  chmod -R 755 $HOST_LOG_DIR

  # 检查是否有全备份(判定是否存在全量备份目录)
  if [ ! -d "$HOST_FULL_BACKUP_DIR" ]; then
      LOG_FILE="$HOST_LOG_DIR/backup-$DATE-full.log"  # 日志文件

      # 如果没有全备份,创建全备份
      print_log "开始全量备份"

      # 创建保存备份的目录
      mkdir -p $HOST_FULL_BACKUP_DIR
      chmod -R 755 $HOST_FULL_BACKUP_DIR

      # 执行备份,报错不退出
      set +e
      docker rm pxback-full > /dev/null 2>&1
      docker run --name pxback-full -v $HOST_MYSQL_DATA_DIR:/var/lib/mysql -v $HOST_FULL_BACKUP_DIR:/backup:z -it --user root percona/percona-xtrabackup:$XTRABACKUP_VERSION /bin/bash -c "xtrabackup --backup --datadir=/var/lib/mysql --target-dir=/backup --host=$MYSQL_HOST --port=$MYSQL_PORT --user=$MYSQL_USER --password=$MYSQL_PWD --compress" >> $LOG_FILE 2>&1

      # 判断备份是否成功
      if [ $? -eq 0 ]; then
          # 删除容器
          docker rm pxback-full > /dev/null 2>&1
          set -e

          # 创建软链接,用于做增量备份的时候与该备份版本进行增量对比
          rm -f $HOST_INC_BASE_DIR
          ln -s $HOST_FULL_BACKUP_DIR $HOST_INC_BASE_DIR

          # 将备份打包
          cd $HOST_FULL_BACKUP_DIR
          tar -czvf $HOST_TAR_DIR/$DATE-full.tar.gz *  >> $LOG_FILE 2>&1
          print_log "全量备份完成"
      else
          # 删除全量备份的目录,下次再次备份时会重新创建(避免下次备份时进入增量备份)
          rm -rf $HOST_FULL_BACKUP_DIR

          # 发送错误通知
          print_log "error 发送错误通知"
          response=$(curl -s -X POST "$BARK_URL" -d "body=全量备份失败(full-$DATE)")
          print_log "error 发送错误通知响应: $response"
          set -e

          print_log "error 全量备份失败"
          exit 1
      fi
  else
      LOG_FILE="$HOST_LOG_DIR/backup-$DATE-inc.log"  # 日志文件
      print_log "开始增量备份"

      # 创建本次增量备份的目录
      HOST_INC_BACKUP_DIR=$HOST_BACKUP_WORK_DIR/inc/inc-$DATE
      mkdir -p $HOST_INC_BACKUP_DIR
      chmod -R 755 $HOST_INC_BACKUP_DIR

      # 执行备份,报错不退出
      set +e
      docker rm pxback-inc > /dev/null 2>&1
      docker run --name pxback-inc -v $HOST_MYSQL_DATA_DIR:/var/lib/mysql -v $HOST_INC_BASE_DIR:/basedir -v $HOST_INC_BACKUP_DIR:/inc -it --user root percona/percona-xtrabackup:$XTRABACKUP_VERSION /bin/bash -c "xtrabackup --backup --incremental-basedir=/basedir --target-dir=/inc --host=$MYSQL_HOST --port=$MYSQL_PORT --user=$MYSQL_USER --password=$MYSQL_PWD --compress" >> $LOG_FILE 2>&1

      # 判断备份是否成功
      if [ $? -eq 0 ]; then
          # 删除容器
          docker rm pxback-inc > /dev/null 2>&1
          set -e

          # 创建软链接,用于做增量备份的时候与该备份版本进行增量对比
          rm -f $HOST_INC_BASE_DIR
          ln -s $HOST_INC_BACKUP_DIR $HOST_INC_BASE_DIR

          # 将备份打包
          cd $HOST_INC_BACKUP_DIR
          tar -czvf $HOST_TAR_DIR/$DATE-inc.tar.gz *  >> $LOG_FILE 2>&1
          print_log "增量备份成功($HOST_INC_BACKUP_DIR)"
      else
          # 删除备份目录
          rm -rf $HOST_INC_BACKUP_DIR

          # 发送错误通知
          print_log "error 发送错误通知"
          response=$(curl -s -X POST "$BARK_URL" -d "body=增量备份失败(inc-$DATE)")
          print_log "error 发送错误通知响应: $response"
          set -e

          print_log "error 增量备份失败($HOST_INC_BACKUP_DIR)"
          exit 1
      fi
  fi

}

main