暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一个基于Xtrabackup进行MySQL全量备份的脚本

81

上篇文章介绍了基于Xtrabackup重建MySQL备库的流程,相信大家对于Xtrabackup在MySQL备份恢复场景的应用建立了基础认知。本文将会提供一个基于Xtrabackup的MySQL全量备份脚本,该脚本整合了全量备份、目录打包、阿里云OSS上传和本地备份文件清理、钉钉通知等功能,实现了MySQL数据的全量备份和异地转储的功能。

mysql_xtrabackup.sh

#!/bin/bash
set -euo pipefail

START_TIME=$(date +%s)

# 日期和路径变量
DATE=$(date +%F)
BACKUP_DIR="/data/mysqlbackup/fullbackup_$DATE"
ARCHIVE_NAME="mysql_fullbackup_$DATE.tar.gz"
ARCHIVE_PATH="/data/mysqlbackup/$ARCHIVE_NAME"
LOG="/data/mysqlbackup/xtrabackup_$DATE.log"

# Xtrabackup 配置(从环境变量读取,支持默认值)
DATADIR="/data/mysql/mysqldata"
MYSQL_USER="${MYSQL_USER:-backup_user}"
MYSQL_PASS="${MYSQL_PASS:-backup_password}"

# OSS 配置
OSSUTIL="/usr/local/bin/ossutil"
OSS_BUCKET="oss://your_bucket/mysql-backups/"
OSS_ENDPOINT="http://oss-your_region.aliyuncs.com"

# 钉钉机器人 Webhook(替换成你的)
DINGDING_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=your_token"

# 记录日志
log() {
    echo"[$(date '+%F %T')$1" | tee -a "$LOG"
}
# 发送钉钉消息
send_dingding() {
    local status="$1"
    local msg="$2"
    curl -s "$DINGDING_WEBHOOK" \
        -H 'Content-Type: application/json' \
        -d "{
            \"msgtype\": \"text\",
            \"text\": {
                \"content\": \"MySQL 备份通知:$status\n时间:$(date '+%F %T')\n$msg\"
            }
        }"
 >/dev/null 2>&1
}

# ========================
# 1. 执行备份
# ========================
if [ -d "$BACKUP_DIR" ]; then
    log"检测到备份目录已存在,跳过 xtrabackup 备份阶段"
else
    log"=== 开始备份 ==="
    if ! xtrabackup --backup \
        --target-dir="$BACKUP_DIR" \
        --datadir="$DATADIR" \
        --user="$MYSQL_USER" \
        --compress \
        --password="$MYSQL_PASS" >> "$LOG" 2>&1; then
        log"备份失败"
        send_dingding "备份失败""步骤:xtrabackup --backup\n错误:执行失败"
        exit 1
    fi
fi

# ========================
# 2. 备份目录打包
# ========================
if [ -f "$ARCHIVE_PATH" ]; then
    log"检测到打包文件已存在,跳过打包阶段"
else
    log"=== 开始打包 ==="
    tar -cf "$ARCHIVE_PATH" -C data/mysqlbackup "$(basename "$BACKUP_DIR")"
    log"备份打包完成:$ARCHIVE_PATH"
fi

# 计算包大小
ARCHIVE_SIZE=$(du -sh "$ARCHIVE_PATH" | awk '{print $1}')


# ========================
# 3. 上传到 OSS
# ========================
if ! $OSSUTIL cp "$ARCHIVE_PATH""$OSS_BUCKET" --force --bigfile-threshold 104857600 -j 3 >> "$LOG" 2>&1; then
    log"上传 OSS 失败"
    send_dingding "备份失败""步骤:上传 OSS\n错误:执行失败\n本地文件已保留:$ARCHIVE_PATH"
    exit 1
fi
log"上传至 OSS 成功:$OSS_BUCKET$ARCHIVE_NAME"

# ========================
# 4. 清理本地备份(OSS 成功后)
# ========================
rm -rf "$BACKUP_DIR"
rm -f "$ARCHIVE_PATH"
log"本地备份已清理,仅保留 OSS 版本"

# ========================
# 5. 统计耗时
# ========================
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
HOURS=$((DURATION 3600))
MINUTES=$(((DURATION % 3600) 60))
SECONDS=$((DURATION % 60))
DURATION_FORMAT="${HOURS}h${MINUTES}m${SECONDS}s"

# ========================
# 6. 发送成功通知
# ========================
send_dingding "备份成功""备份文件:$ARCHIVE_NAME\n大小:$ARCHIVE_SIZE\n耗时:$DURATION_FORMAT\n已上传至:$OSS_BUCKET"

log"=== 备份流程完成 ==="

以下内容是对该脚本的解析。

基础设置

1.bash的执行模式

set -euo pipefail

set -euo pipefail
,表示bash脚本的严格模式:

  • -e
    (errexit):遇到非零退出状态(错误)就立即退出脚本。
  • -u
    (nounset):引用未定义变量时报错。
  • -o pipefail
    :默认情况下,A | B | C 这种管道命令,脚本只会检查最后一个命令的退出码。有了 pipefail,整个管道的退出状态会是 第一个失败命令的退出码。避免命令假成功。

2.定义路径和文件名

DATE=$(date +%F)
BACKUP_DIR="/data/mysqlbackup/fullbackup_$DATE"
ARCHIVE_NAME="mysql_fullbackup_$DATE.tar.gz"
ARCHIVE_PATH="/data/mysqlbackup/$ARCHIVE_NAME"
LOG="/data/mysqlbackup/xtrabackup_$DATE.log"

  • DATE
    :当天日期(格式 2025-09-07
    )。
  • BACKUP_DIR
    :xtrabackup 生成的目录。
  • ARCHIVE_NAME
     / ARCHIVE_PATH
    :打包后的包路径。
  • LOG
    :日志文件路径。

3.MySQL 相关配置

DATADIR="/data/mysql/mysqldata"
MYSQL_USER="${MYSQL_USER:-backup_user}"
MYSQL_PASS="${MYSQL_PASS:-backup_password}"

  • DATADIR
    :MySQL 数据目录。
  • MYSQL_USER
     / MYSQL_PASS
    :备份账号,支持从环境变量传入,否则用默认值。

4.OSS相关配置

# OSS 配置
OSSUTIL="/usr/local/bin/ossutil"
OSS_BUCKET="oss://your_bucket/mysql-backups/"
OSS_ENDPOINT="http://oss-your_region.aliyuncs.com"

  • ossutil
    :阿里云 OSS 上传工具。
  • OSS_BUCKET
    :存储桶路径。
  • OSS_ENDPOINT
    :OSS 区域节点。

5.定义Log方法log()

# 记录日志
log() {
    echo "[$(date '+%F %T')$1" | tee -a "$LOG"
}

echo "[$(date '+%F %T')] $1"
: $(date '+%F %T')
:获取当前时间,格式为 YYYY-MM-DD HH:MM:SS
$1
,函数的第一个参数,也就是你传进去的日志内容,当前时间拼接日志内容形成完整日志,如:[2025-09-07 18:20:30] 开始备份

6.定义发送钉钉消息的方法send_dingding()

# 发送钉钉消息
send_dingding() {
    local status="$1"
    local msg="$2"
    curl -s "$DINGDING_WEBHOOK" \
        -H 'Content-Type: application/json' \
        -d "{
            \"msgtype\": \"text\",
            \"text\": {
                \"content\": \"MySQL 备份通知:$status\n时间:$(date '+%F %T')\n$msg\"
            }
        }"
 >/dev/null 2>&1
}

执行备份

if [ -d "$BACKUP_DIR" ]; then
    log "检测到备份目录已存在,跳过 xtrabackup 备份阶段"
else
    xtrabackup --backup \
        --target-dir="$BACKUP_DIR" \
        --datadir="$DATADIR" \
        --user="$MYSQL_USER" \
        --compress \
        --password="$MYSQL_PASS"
fi

  • 判断当天目录是否已存在,如果存在就跳过。
  • 否则执行 xtrabackup --backup
    :把 MySQL 数据做热备份到 $BACKUP_DIR
    ,并开启压缩。
  • 如果失败,会发钉钉通知并退出。

备份文件打包

# ========================
# 2. 备份目录打包(可跳过)
# ========================
if [ -f "$ARCHIVE_PATH" ]; then
    log"检测到打包文件已存在,跳过打包阶段"
else
    log"=== 开始打包 ==="
    tar -cf "$ARCHIVE_PATH" -C data/mysqlbackup "$(basename "$BACKUP_DIR")"
    log"备份文件打包完成:$ARCHIVE_PATH"
fi

# 计算包大小
ARCHIVE_SIZE=$(du -sh "$ARCHIVE_PATH" | awk '{print $1}')

上传至OSS

# ========================
# 3. 上传到 OSS
# ========================
if ! $OSSUTIL cp "$ARCHIVE_PATH" "$OSS_BUCKET" --force --bigfile-threshold 104857600 -j 3 >> "$LOG" 2>&1; then
    log "上传 OSS 失败"
    send_dingding "备份失败" "步骤:上传 OSS\n错误:执行失败\n本地文件已保留:$ARCHIVE_PATH"
    exit 1
fi
log "上传至 OSS 成功:$OSS_BUCKET$ARCHIVE_NAME"

  • ! $OSSUTIL cp ...
    :执行上传,如果命令返回非 0,则判定上传失败。
  • --force
    :强制覆盖 OSS 上同名文件。
  • --bigfile-threshold 104857600
    :指定大文件阈值为 100MB(以便 OSSUTIL 使用分片上传)。
  • -j 3
    :开启多线程(3 个线程)。
  • >> "$LOG" 2>&1
    :将 OSSUTIL 的 stdout/stderr 都写入日志。
  • 上传失败时:
    • 写日志 "上传 OSS 失败"
    • 通过 send_dingding
       发钉钉告警
    • 保留本地文件并退出脚本
  • 上传成功时,写日志 "上传至 OSS 成功"

收尾部分

# ========================
# 4. 清理本地备份(OSS 成功后)
# ========================
rm -rf "$BACKUP_DIR"
rm -f "$ARCHIVE_PATH"
log"本地备份已清理,仅保留 OSS 版本"

# ========================
# 5. 统计耗时
# ========================
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
HOURS=$((DURATION 3600))
MINUTES=$(((DURATION % 3600) 60))
SECONDS=$((DURATION % 60))
DURATION_FORMAT="${HOURS}h${MINUTES}m${SECONDS}s"

# ========================
# 6. 发送成功通知
# ========================
send_dingding "备份成功""备份文件:$ARCHIVE_NAME\n大小:$ARCHIVE_SIZE\n耗时:$DURATION_FORMAT\n已上传至:$OSS_BUCKET"

log"=== 备份流程完成 ==="

本地备份文件清理:防止磁盘占用过大 耗时统计:计算备份总耗时 钉钉通知:通过钉钉发送通知,告知备份文件名、大小、耗时和 OSS 位置。

脚本执行

后台执行:
nohup ./mysql_xtrabackup.sh > backup.out 2>&1 &




参考: https://help.aliyun.com/zh/oss/command-line-tools-ossutil-quickstart


 or  


👇👇👇 

文章转载自PostgreSQL运维技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论