找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

181

积分

0

好友

23

主题
发表于 3 天前 | 查看: 6| 回复: 0

本文详细介绍了一个专为MySQL 8.0设计的物理备份解决方案,基于Xtrabackup 8.0最新版本实现全量备份自动化。该脚本集成了完整的备份管理功能,包括错误处理、日志记录、自动清理和耗时统计等企业级特性。

脚本核心功能

数据库备份脚本专门针对MySQL 8.0环境设计,具备以下完整功能:

  • 全量物理备份
  • 智能错误处理机制
  • 详细的日志记录系统
  • 自动清理过期备份
  • 备份耗时统计分析

完整脚本代码

#!/bin/bash
# ===============================================
# MySQL XtraBackup 全量备份脚本 (默认未启用压缩) 
# 功能:全量备份 + 错误处理 + 日志记录 + 自动清理 + 耗时统计
# 版本:1.0
# 日期:2025-11-04
# ===============================================

# 可配置变量(修改此处适应环境)
BACKUP_BASE_DIR="/data/backup"                 # 备份根目录
LOG_DIR="${BACKUP_BASE_DIR}/logs"              # 日志目录
FULL_BACKUP_DIR="${BACKUP_BASE_DIR}/full"      # 全量备份目录

# MySQL 连接配置
MYSQL_USER="root"                              # 备份专用用户(需提前授权)
MYSQL_PASSWORD="mysql"                         # 用户密码
MYSQL_SOCKET="/data/mysql/3306/run/mysql.sock" # MySQL Socket路径
MYSQL_CNF="/etc/my.cnf"                        # MySQL配置文件路径

# 备份参数
RETENTION_DAYS=7                               # 备份保留天数(默认7天)
COMPRESS_ENABLED=0                             # 是否启用压缩(0-禁用,1-启用,默认禁用)
COMPRESS_ALGORITHM="zstd"                      # 压缩算法
COMPRESS_THREADS=4                             # 压缩线程数(默认4)
PARALLEL=4                                     # 备份并行线程数(默认4)

# XtraBackup路径
XTRABACKUP_PATH="/data/soft/xtrabackup8.0.35-34-glibc2.36/bin/xtrabackup"

# 函数定义
log_message() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local log_entry="[${timestamp}] [${level}] ${message}"
    echo "${log_entry}" | tee -a "${CURRENT_LOG_FILE}"
}

error_exit() {
    log_message "ERROR" "脚本执行失败: $1"
    exit 1
}

calculate_duration() {
    local start_seconds="$1"
    local end_seconds="$2"
    local total_seconds=$((end_seconds - start_seconds))

    local days=$((total_seconds / 86400))
    local hours=$(( (total_seconds % 86400) / 3600 ))
    local minutes=$(( (total_seconds % 3600) / 60 ))
    local seconds=$((total_seconds % 60))

    local duration_str=""
    if [ $days -gt 0 ]; then
        duration_str="${days}天"
    fi
    if [ $hours -gt 0 ] || [ -n "$duration_str" ]; then
        duration_str="${duration_str}${hours}小时"
    fi
    if [ $minutes -gt 0 ] || [ -n "$duration_str" ]; then
        duration_str="${duration_str}${minutes}分钟"
    fi
    duration_str="${duration_str}${seconds}秒"
    echo "$duration_str"
}

cleanup_old_backups() {
    log_message "INFO" "开始清理超过 ${RETENTION_DAYS} 天的旧备份..."
    local deleted_count=0

    if find "${BACKUP_BASE_DIR}" -name "full_*" -type d -mtime +${RETENTION_DAYS} | grep -q .; then
        find "${BACKUP_BASE_DIR}" -name "full_*" -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \;
        deleted_count=$(find "${BACKUP_BASE_DIR}" -name "full_*" -type d -mtime +${RETENTION_DAYS} | wc -l)
        log_message "INFO" "已清理 ${deleted_count} 个过期全量备份"
    else
        log_message "INFO" "未找到需要清理的过期备份"
    fi

    find "${LOG_DIR}" -name "backup_*.log" -type f -mtime +30 -delete
}

check_dependencies() {
    local deps=("${XTRABACKUP_PATH}" "mysql")
    for cmd in "${deps[@]}"; do
        if ! command -v "${cmd}" &> /dev/null; then
            error_exit "未找到所需命令: ${cmd},请确保已安装并配置PATH"
        fi
    done

    if [ ! -w "${BACKUP_BASE_DIR}" ]; then
        error_exit "备份目录不可写: ${BACKUP_BASE_DIR}"
    fi
}

pre_backup_checks() {
    log_message "INFO" "开始备份前置检查..."

    if ! mysql --user="${MYSQL_USER}" --password="${MYSQL_PASSWORD}" --socket="${MYSQL_SOCKET}" -e "SELECT 1;" &> /dev/null; then
        error_exit "MySQL连接测试失败,请检查凭据和Socket路径"
    fi

    local xtrabackup_version
    xtrabackup_version=$(${XTRABACKUP_PATH} --version 2>&1 | tail -n1 || echo "未知")
    log_message "INFO" "使用XtraBackup版本: ${xtrabackup_version}"

    local available_space
    available_space=$(df "${BACKUP_BASE_DIR}" | awk 'NR==2 {print $4}')
    if [ "${available_space}" -lt 10485760 ]; then
        error_exit "磁盘空间不足10GB,当前可用: ${available_space}KB"
    fi
}

# 主脚本逻辑
main() {
    local backup_timestamp=$(date '+%Y%m%d_%H%M%S')
    local backup_name="full_${backup_timestamp}"
    local current_backup_dir="${FULL_BACKUP_DIR}/${backup_name}"
    CURRENT_LOG_FILE="${LOG_DIR}/backup_${backup_timestamp}.log"

    local backup_start_time=$(date +%s)
    local backup_start_readable=$(date '+%Y-%m-%d %H:%M:%S')

    mkdir -p "${FULL_BACKUP_DIR}" "${LOG_DIR}"
    log_message "INFO" "=== MySQL全量备份开始 ==="
    log_message "INFO" "备份开始时间: ${backup_start_readable}"
    log_message "INFO" "备份名称: ${backup_name}"
    log_message "INFO" "备份目录: ${current_backup_dir}"
    log_message "INFO" "保留天数: ${RETENTION_DAYS}"

    check_dependencies
    pre_backup_checks

    local backup_cmd="${XTRABACKUP_PATH} --defaults-file=${MYSQL_CNF} --backup"
    backup_cmd+=" --target-dir=${current_backup_dir}"
    backup_cmd+=" --user=${MYSQL_USER} --password=${MYSQL_PASSWORD}"
    backup_cmd+=" --socket=${MYSQL_SOCKET} --parallel=${PARALLEL}"

    if [ "${COMPRESS_ENABLED}" -eq 1 ]; then
        log_message "INFO" "启用压缩算法: ${COMPRESS_ALGORITHM}, 线程数: ${COMPRESS_THREADS}"
        backup_cmd+=" --compress=${COMPRESS_ALGORITHM} --compress-threads=${COMPRESS_THREADS}"
    else
        log_message "INFO" "备份未启用压缩"
    fi

    log_message "INFO" "开始执行 XtraBackup 全量备份..."
    log_message "DEBUG" "备份命令: ${backup_cmd//--password=* /--password=*** }"

    local backup_operation_start=$(date +%s)
    if eval "${backup_cmd}" >> "${CURRENT_LOG_FILE}" 2>&1; then
        local backup_operation_end=$(date +%s)
        local backup_duration=$(calculate_duration $backup_operation_start $backup_operation_end)
        log_message "INFO" "XtraBackup全量备份完成,备份操作耗时: ${backup_duration}"

        if [ -f "${current_backup_dir}/xtrabackup_checkpoints" ]; then
            local backup_type
            backup_type=$(grep "backup_type" "${current_backup_dir}/xtrabackup_checkpoints" | cut -d= -f2)
            log_message "INFO" "备份类型验证: ${backup_type}"
        else
            error_exit "备份完整性检查失败: xtrabackup_checkpoints文件缺失"
        fi
    else
        error_exit "XtraBackup备份过程失败,请检查日志: ${CURRENT_LOG_FILE}"
    fi

    cleanup_old_backups

    local backup_end_time=$(date +%s)
    local backup_end_readable=$(date '+%Y-%m-%d %H:%M:%S')
    local total_duration=$(calculate_duration $backup_start_time $backup_end_time)

    local backup_size
    backup_size=$(du -sh "${current_backup_dir}" | awk '{print $1}')
    log_message "INFO" "备份完成: ${backup_name} (大小: ${backup_size})"
    log_message "INFO" "备份开始: ${backup_start_readable}"
    log_message "INFO" "备份结束: ${backup_end_readable}"
    log_message "INFO" "备份总耗时: ${total_duration}"
    log_message "INFO" "备份日志: ${CURRENT_LOG_FILE}"
    log_message "INFO" "=== MySQL全量备份结束 ==="
}

trap 'log_message "ERROR" "脚本被用户中断"; exit 2;' INT TERM
main "$@"

关键配置说明

在实际部署前,需要根据数据库环境调整以下配置参数:

BACKUP_BASE_DIR="/data/backup"                 # 备份根目录
LOG_DIR="${BACKUP_BASE_DIR}/logs"              # 日志目录
FULL_BACKUP_DIR="${BACKUP_BASE_DIR}/full"      # 全量备份目录

# MySQL 连接配置
MYSQL_USER="root"                              # 备份专用用户(需提前授权)
MYSQL_PASSWORD="mysql"                         # 用户密码
MYSQL_SOCKET="/data/mysql/3306/run/mysql.sock" # MySQL Socket路径
MYSQL_CNF="/etc/my.cnf"                        # MySQL配置文件路径

# 备份参数
RETENTION_DAYS=7                               # 备份保留天数
COMPRESS_ENABLED=0                             # 压缩开关
COMPRESS_ALGORITHM="zstd"                      # 压缩算法
PARALLEL=4                                     # 并行线程数

使用指南

1. 脚本部署与权限设置

chmod +x xtrabackup8.0_full.sh

2. 手动执行备份

[root@VM-8-4-opencloudos backup]# ./xtrabackup8.0_full.sh
[2025-11-04 17:34:34] [INFO] === MySQL全量备份开始 ===
[2025-11-04 17:34:34] [INFO] 备份名称: full_20251104_173434
[2025-11-04 17:34:34] [INFO] 备份目录: /data/backup/full/full_20251104_173434
[2025-11-04 17:34:34] [INFO] 保留天数: 7
[2025-11-04 17:34:34] [INFO] 开始备份前置检查...
[2025-11-04 17:34:35] [INFO] 使用XtraBackup版本: /data/soft/xtrabackup8.0.35-34-glibc2.36/bin/xtrabackup version 8.0.35-34 based on MySQL server 8.0.35 Linux (x86_64) (revision id: c8a25ff9)
[2025-11-04 17:34:35] [INFO] 启用压缩算法: zstd, 线程数: 4
[2025-11-04 17:34:35] [INFO] 开始执行XtraBackup全量备份...
[2025-11-04 17:34:35] [DEBUG] 备份命令: /data/soft/xtrabackup8.0.35-34-glibc2.36/bin/xtrabackup --defaults-file=/etc/my.cnf --backup --target-dir=/data/backup/full/full_20251104_173434 --user=root --password=*** --compress-threads=4
[2025-11-04 17:34:41] [INFO] XtraBackup全量备份完成
[2025-11-04 17:34:41] [INFO] 备份类型验证:  full-backuped
[2025-11-04 17:34:41] [INFO] 开始清理超过 7 天的旧备份...
[2025-11-04 17:34:41] [INFO] 未找到需要清理的过期备份
[2025-11-04 17:34:41] [INFO] 备份完成: full_20251104_173434 (大小: 43M)
[2025-11-04 17:34:41] [INFO] 备份日志: /data/backup/logs/backup_20251104_173434.log
[2025-11-04 17:34:41] [INFO] === MySQL全量备份结束 ===

3. 自动化运维配置

设置每日凌晨1点自动执行备份:

# 编辑crontab:crontab -e 添加如下内容并保存
0 1 * * * /path/to/xtrabackup8.0_full.sh

数据恢复流程

1. 解压缩处理(如启用压缩)

xtrabackup --decompress --remove-original --target-dir=/data/backup/full/full_20251104_173434

解压缩过程会逐文件处理并显示详细进度,最终输出"completed OK!"表示成功。

2. 执行Prepare操作

Prepare是物理备份恢复前的关键步骤,用于确保数据文件的一致性:

/data/soft/xtrabackup8.0.35-34-glibc2.36/bin/xtrabackup --prepare --target-dir=/data/backup/full/full_20251104_173434

此步骤通过应用redo日志修复备份期间可能的数据不一致状态,确保数据库能够正常启动。当输出显示"completed OK!"时表示准备完成。

3. 停止服务并清理数据目录

# 停止MySQL服务
systemctl stop mysqld

# 清理数据目录(请确认路径)
rm -rf /var/lib/mysql/*

4. 执行数据恢复

xtrabackup --copy-back --target-dir=/data/backup/full/full_20251104_173434

5. 权限调整

chown -R mysql:mysql /var/lib/mysql

6. 启动验证

systemctl start mysqld

启动后检查错误日志并验证数据库状态。

技术要点解析

Prepare步骤的重要性:在物理备份过程中,prepare环节确保数据文件恢复到一致性状态。XtraBackup采用快照方式备份,期间数据库可能仍在处理事务,导致数据文件状态不一致。prepare通过应用redo日志修复这种不一致性,使备份集达到可启动状态。

压缩选项优化:脚本支持zstd、lz4等多种压缩算法,可根据存储空间和性能需求灵活配置。启用压缩时建议提前安装对应解压工具。

总结

MySQL备份解决方案提供了生产环境所需的完整功能,包括智能错误处理、自动化清理和详细日志记录。通过合理的配置调整,可以满足不同规模的数据库备份需求,为企业数据安全提供可靠保障。

您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-1 14:50 , Processed in 0.058502 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表