MariaDB 备份自动化落地方案
一 方案选型与准备
二 自动化脚本示例
#!/usr/bin/env bash
set -Eeuo pipefail
# ===== 用户配置 =====
MYSQL_USER="buser"
MYSQL_PASSWORD="tmrQ"
BACKUP_DIR="/opt/mysql_backup"
FULL_BACKUP_INTERVAL=7 # 全量间隔:天
RETENTION_DAYS=30 # 保留天数
LOG_FILE="/var/log/mariadb_backup.log"
# ===== 内部变量 =====
FULL_DIR="$BACKUP_DIR/full"
INCR_DIR="$BACKUP_DIR/incr"
LAST_FULL_FILE="$BACKUP_DIR/last_full_backup"
XBK="/usr/bin/mariabackup"
log() {
echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"
}
cleanup() {
local target="$1"
if [[ -d "$target" ]]; then
rm -rf "$target"
log "已清理临时目录: $target"
fi
}
check_db() {
if ! mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SELECT 1" &>/dev/null; then
log "ERROR: 无法连接 MariaDB,请检查账号/网络/权限"
return 1
fi
}
full_backup() {
local ts
ts=$(date +"%Y%m%d_%H%M%S")
local target_dir="$FULL_DIR/full-$ts"
mkdir -p "$target_dir"
log "开始全量备份 -> $target_dir"
if "$XBK" --backup \
--user="$MYSQL_USER" \
--password="$MYSQL_PASSWORD" \
--target-dir="$target_dir" >>"$LOG_FILE" 2>&1; then
echo "$target_dir" > "$LAST_FULL_FILE"
log "全量备份成功: $target_dir"
else
log "全量备份失败: $target_dir"
cleanup "$target_dir"
return 1
fi
}
incremental_backup() {
local base_dir
base_dir=$(cat "$LAST_FULL_FILE" 2>/dev/null || true)
if [[ -z "$base_dir" || ! -d "$base_dir" ]]; then
log "未找到可用基准备份,回退执行全量备份"
full_backup
return $?
fi
local ts
ts=$(date +"%Y%m%d_%H%M%S")
local target_dir="$INCR_DIR/incr-$ts"
mkdir -p "$target_dir"
log "开始增量备份 -> $target_dir(基于: $(basename "$base_dir"))"
if "$XBK" --backup \
--user="$MYSQL_USER" \
--password="$MYSQL_PASSWORD" \
--target-dir="$target_dir" \
--incremental-basedir="$base_dir" >>"$LOG_FILE" 2>&1; then
log "增量备份成功: $target_dir"
else
log "增量备份失败: $target_dir"
cleanup "$target_dir"
return 1
fi
}
purge_old() {
log "清理超过 $RETENTION_DAYS 天的备份..."
find "$FULL_DIR" -mindepth 1 -type d -mtime "+$RETENTION_DAYS" -print -delete | while read d; do
log "删除旧全备: $d"
done
find "$INCR_DIR" -mindepth 1 -type d -mtime "+$RETENTION_DAYS" -print -delete | while read d; do
log "删除旧增备: $d"
done
}
main() {
log "===== 备份开始 ====="
check_db || exit 1
local need_full=false
if [[ ! -f "$LAST_FULL_FILE" ]]; then
need_full=true
elif [[ $(find "$LAST_FULL_FILE" -mtime "+$FULL_BACKUP_INTERVAL" | wc -l) -gt 0 ]]; then
need_full=true
fi
if $need_full; then
full_backup
else
incremental_backup
fi
purge_old
log "===== 备份完成 ====="
}
main "$@"
0 4 * * * /usr/bin/bash /opt/scripts/mariadb_backup.sh
三 远程备份与传输
# 本地脚本备份完成后执行
rsync -avz --delete -e ssh /opt/mysql_backup/ backup@10.0.0.111:/data/mysqlbak/
# 全量
mariabackup --backup --user=buser --password=tmrQ --stream=xbstream | \
gzip | ssh backup@10.0.0.111 "cat > /data/mysqlbak/full_$(date +%F_%H%M%S).xbstream.gz"
# 增量(基于上一次备份目录)
mariabackup --backup --user=buser --password=tmrQ \
--incremental-basedir=/opt/mysql_backup/full/full-YYYYMMDD_HHMMSS \
--stream=xbstream | gzip | \
ssh backup@10.0.0.111 "cat > /data/mysqlbak/incr_$(date +%F_%H%M%S).xbstream.gz"
四 还原流程要点
mariabackup --prepare --target-dir=/data/restore/base
mariabackup --prepare --apply-log-only --target-dir=/data/restore/base \
--incremental-dir=/data/restore/incr_YYYYMMDD_HHMMSS_01
mariabackup --prepare --apply-log-only --target-dir=/data/restore/base \
--incremental-dir=/data/restore/incr_YYYYMMDD_HHMMSS_02
# 最后一个增量可不加 --apply-log-only
mariabackup --prepare --target-dir=/data/restore/base \
--incremental-dir=/data/restore/incr_YYYYMMDD_HHMMSS_NN
systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysql.bak_$(date +%F_%H%M%S)
mkdir -p /var/lib/mysql
mariabackup --copy-back --target-dir=/data/restore/base
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld
五 监控校验与最佳实践