发布于 2026-06-30 / 2 阅读
0
0

mysql自动备份

# 准备工作: MySQL 必须开启 binlog

#!/bin/bash
# MySQL 周一全量、周二至周日差异备份脚本
# 差异逻辑:每次备份本周一全量之后全部binlog,恢复只需要全量+当天一份差异包

########################### 【配置区,请自行修改】###########################
# MySQL 连接信息
DB_HOST="127.0.0.1"
DB_PORT="3306"
DB_USER="root"
DB_PASS="root123456"
# --all-databases 全部库;指定单库填数据库名
DB_TARGET="--all-databases"

# 备份根目录
BACKUP_ROOT="/data/mysql_backup"
# MySQL binlog 存放路径(my.cnf log_bin 对应目录)
BINLOG_PATH="/var/lib/mysql"
# 备份保留天数
RETENTION=30
# 告警邮箱,不需要填空
MAIL_ADMIN=""
#############################################################################

# 自动创建目录
FULL_DIR="${BACKUP_ROOT}/full"
DIFF_DIR="${BACKUP_ROOT}/diff"
LOG_FILE="${BACKUP_ROOT}/backup_log.log"
mkdir -p "${FULL_DIR}" "${DIFF_DIR}"

# 日期、星期变量
TODAY=$(date +%Y%m%d)
WEEK_NUM=$(date +%w) # 0周日 1周一 2周二 ...6周六

# 日志输出函数
log() {
    echo "[$(date +%Y-%m-%d\ %H:%M:%S)] $1" | tee -a "${LOG_FILE}"
}

# 异常退出+邮件告警
err_exit() {
    log "ERROR: $1"
    if [ -n "${MAIL_ADMIN}" ]; then
        echo "MySQL备份失败:$1" | mail -s "【MySQL备份告警】${TODAY}" "${MAIL_ADMIN}"
    fi
    exit 1
}

# 清理过期备份
clean_old_backup() {
    log "开始清理${RETENTION}天前过期备份"
    find "${FULL_DIR}" -name "mysql_full_*.sql.gz" -mtime +${RETENTION} -delete
    find "${DIFF_DIR}" -name "mysql_diff_*.binlog.tar.gz" -mtime +${RETENTION} -delete
}

# 周一全量备份函数
full_backup() {
    log "========== 执行周一全量备份 ${TODAY} =========="
    FULL_FILE="${FULL_DIR}/mysql_full_${TODAY}.sql.gz"

    # InnoDB专用一致性备份,刷新binlog并记录位点
    mysqldump -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS}" \
        --single-transaction --flush-logs --master-data=2 --quick ${DB_TARGET} \
        | gzip > "${FULL_FILE}"

    [ $? -ne 0 ] && err_exit "全量mysqldump导出失败"
    log "全量备份文件:${FULL_FILE}"

    # 提取本次全量对应的起始binlog文件名,保存给本周差异使用
    grep "^CHANGE MASTER TO" "${FULL_FILE}" | awk -F\' '{print $2}' > "${FULL_DIR}/this_week_start_binlog.txt"
    log "记录本周差异起始binlog位点完成"
}

# 周二至周日 差异备份函数
diff_backup() {
    log "========== 执行差异备份 ${TODAY} =========="
    START_BINLOG_FILE="${FULL_DIR}/this_week_start_binlog.txt"
    # 判断本周是否存在周一全量位点文件
    [ ! -f "${START_BINLOG_FILE}" ] && err_exit "缺少本周一全量备份位点文件,请先手动执行一次周一全量备份"

    START_BIN=$(cat "${START_BINLOG_FILE}")
    DIFF_PACK="${DIFF_DIR}/mysql_diff_${TODAY}.binlog.tar.gz"

    # 找出从周一起始binlog到当前所有binlog文件打包(差异:本周一至今所有变更)
    cd "${BINLOG_PATH}" || err_exit "无法进入binlog目录${BINLOG_PATH}"
    bin_list=$(ls ${START_BIN}* 2>/dev/null)
    [ -z "${bin_list}" ] && err_exit "未找到从${START_BIN}开始的binlog文件"

    tar -zcf "${DIFF_PACK}" ${bin_list}
    [ $? -ne 0 ] && err_exit "差异binlog打包失败"
    log "差异备份包:${DIFF_PACK}"
}

########################### 主执行流程 ###########################
log "===== 备份任务启动,星期${WEEK_NUM} ====="
clean_old_backup

# 判断星期:1=周一全量,其余差异
if [ "${WEEK_NUM}" -eq 1 ]; then
    full_backup
else
    diff_backup
fi

log "===== ${TODAY} 备份任务执行完成 ===="
echo -e "\n" >> "${LOG_FILE}"
exit 0
crontab -e
# 添加一行
# 每日凌晨 2 点执行
0 2 * * * /data/script/mysql_backup_diff.sh


评论