本文详细介绍了一个专为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全量备份结束 ===
设置每日凌晨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备份解决方案提供了生产环境所需的完整功能,包括智能错误处理、自动化清理和详细日志记录。通过合理的配置调整,可以满足不同规模的数据库备份需求,为企业数据安全提供可靠保障。