Docker版Percona Xtrabackup全量压缩脚本

简单记录一下Percona Xtrabackup常用的每天定时备份的压缩脚本

目录

场景说明

  • Linux环境
  • Docker容器运行的备份目标MySQL
  • Docker容器运行的Percona Xtrabackup
  • 每天定时全量备份一次
  • 使用操作系统自带的cron定时任务管理器
  • 使用工具镜像版本为 percona/percona-xtrabackup:8.0.35-34.1

镜像信息:

shell 复制代码
[root@cn1920vm0064 backup]# docker image ls | grep -E '*backup|mysql*'
percona/percona-xtrabackup   8.0.35-34.1   11c6f241e3b3   6 weeks ago    1.78GB
mysql                        8.0.22        d4c3cafb11d5   4 years ago    545MB

运行容器:

shell 复制代码
[root@cn1920vm0064 backup]# docker ps | grep -E '*backup|mysql*'
99c8448c9387   mysql:8.0.22      "docker-entrypoint.s..."   19 hours ago   Up 18 hours                                                                                          mysql8

上面的 Docker容器 mysql8 为要备份的业务数据库,已经做了数据目录映射,之前创建该业务数据库的Docker容器命令如下:

shell 复制代码
 docker run -u root \
  --cap-add=SYS_NICE \
  --network=host \
  --restart=always \
  --name mysql8 \
  -v /data/apps/mysql/conf/my.cnf:/etc/mysql/my.cnf \
  -v /data/apps/mysql/files:/var/lib/mysql-files \
  -v /data/apps/mysql/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=YourPassword \
  -d mysql:8.0.22

可以看到数据库的数据目录映射到物理宿主机的 /data/apps/mysql/data 目录下了,这里假设数据库端口为3309

一、创建备份脚本文件

shell 复制代码
sudo touch mysqlbackup.sh
sudo chmod +x mysqlbackup.sh

假设备份数据放在如下目录中:

shell 复制代码
sudo mkdir -p /data/apps/xtrabackup/backup

假设运行产生的日志放在文件/var/log/xtrabackup/backup.log 中:

shell 复制代码
sudo mkdir -p /var/log/xtrabackup
sudo touch /var/log/xtrabackup/backup.log
sudo chmod 644 /var/log/xtrabackup/backup.log

需要在目标业务数据库中创建专门的用于备份的账号密码:

sql 复制代码
 CREATE USER 'xtrabackup'@'%' IDENTIFIED WITH mysql_native_password BY 'yourbackpassword';
 
 GRANT SELECT, RELOAD, PROCESS, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO `xtrabackup`@`%`;

 GRANT BACKUP_ADMIN ON *.* TO `xtrabackup`@`%`;
 
 FLUSH PRIVILEGES;

脚本内容如下:

bash 复制代码
#!/usr/bin/env bash
#
# MySQL XtraBackup Daily Backup Script (Docker)
# 每天备份一次,保留最近3天(可调)

set -euo pipefail
# 建议:限制新建文件/目录权限,提升安全性
umask 077

########## 可配置变量 BEGIN ##########

# 备份保留天数(只保留最近多少个备份目录)
RETENTION_DAYS=3

# Docker 镜像
XTRABACKUP_IMAGE="percona/percona-xtrabackup:8.0.35-34.1"

# 宿主机 MySQL 数据卷所在的容器名称
MYSQL_DATA_CONTAINER="mysql8"

# 备份容器运行时名称(临时)
BACKUP_CONTAINER_NAME="pxb"

# 备份根目录(宿主机路径)
BACKUP_ROOT="/data/apps/xtrabackup/backup"

# MySQL 连接信息(从备份容器访问 MySQL)
MYSQL_HOST="172.17.0.1"
MYSQL_PORT="3309"
MYSQL_USER="xtrabackup"
MYSQL_PASSWORD="yourbackpassword"

# MySQL 数据目录(在 mysql8 容器里的路径)
MYSQL_DATADIR="/var/lib/mysql"

# 备份选项(可按需修改压缩等参数)
XTRABACKUP_OPTIONS="--backup --compress --compress-threads=4"

# 备份目录命名前缀
BACKUP_PREFIX="full_backup_"

# 日志文件
LOG_FILE="/var/log/xtrabackup/backup.log"

########## 可配置变量 END ##########

# 确保日志目录存在
mkdir -p "$(dirname "$LOG_FILE")"

# 从这里开始,所有输出(包括 docker run 的 stdout/stderr)都写入日志
exec >> "$LOG_FILE" 2>&1

echo "==== $(date '+%F %T') 开始 MySQL XtraBackup 备份 ===="

# 安全检查:防止 BACKUP_ROOT 为空或指向根目录
if [[ -z "${BACKUP_ROOT:-}" || "${BACKUP_ROOT}" == "/" ]]; then
  echo "ERROR: BACKUP_ROOT 未定义或为 '/',为防止误删数据,中止执行!"
  exit 1
fi

# 创建备份根目录(如不存在)
mkdir -p "${BACKUP_ROOT}"

# 生成当日备份目录名,例如 full_backup_2025-12-01
TODAY_DATE="$(date +%F)"
TARGET_DIR_NAME="${BACKUP_PREFIX}${TODAY_DATE}"
TARGET_DIR="${BACKUP_ROOT}/${TARGET_DIR_NAME}"

echo "== 当日备份目录: ${TARGET_DIR}"

# 如果当天目录已存在,可以选择退出或覆盖,这里选择退出防止覆盖
if [[ -d "${TARGET_DIR}" ]]; then
  echo "WARN: 备份目录已存在:${TARGET_DIR},本次备份中止以避免覆盖。"
  exit 1
fi

echo "== 启动 Docker 容器执行备份 =="
echo "   镜像: ${XTRABACKUP_IMAGE}"
echo "   MySQL: ${MYSQL_HOST}:${MYSQL_PORT}"
echo "   数据目录: ${MYSQL_DATADIR}"
echo "   目标目录: ${TARGET_DIR}"

docker run --name "${BACKUP_CONTAINER_NAME}" \
  --rm \
  -u root \
  --volumes-from "${MYSQL_DATA_CONTAINER}" \
  -v "${BACKUP_ROOT}":/backup \
  "${XTRABACKUP_IMAGE}" \
  /bin/bash -c "
    xtrabackup ${XTRABACKUP_OPTIONS} \
      --datadir=${MYSQL_DATADIR} \
      --target-dir=/backup/${TARGET_DIR_NAME} \
      --host=${MYSQL_HOST} \
      --port=${MYSQL_PORT} \
      --user=${MYSQL_USER} \
      --password=${MYSQL_PASSWORD}
  "

echo "== 备份完成: ${TARGET_DIR} =="

########## 清理旧备份(安全版) ##########

echo "== 清理旧备份,保留最近 ${RETENTION_DAYS} 个 =="

cd "${BACKUP_ROOT}" || {
  echo "ERROR: 无法进入备份目录 ${BACKUP_ROOT}"
  exit 1
}

# 收集所有符合前缀的备份目录,按时间倒序排列(最新在前)
BACKUP_DIRS=( $(ls -dt ${BACKUP_PREFIX}* 2>/dev/null || true) )

TOTAL=${#BACKUP_DIRS[@]}

if (( TOTAL == 0 )); then
  echo "当前没有任何备份目录,无需清理。"
elif (( TOTAL <= RETENTION_DAYS )); then
  echo "当前备份数量 ${TOTAL} 个,不超过保留上限 ${RETENTION_DAYS},无需删除。"
else
  TO_DELETE_COUNT=$(( TOTAL - RETENTION_DAYS ))
  echo "当前共有 ${TOTAL} 个备份,将删除最旧的 ${TO_DELETE_COUNT} 个:"

  for (( i=RETENTION_DAYS; i<TOTAL; i++ )); do
    OLD_BACKUP="${BACKUP_DIRS[$i]}"
    # 双重保险:只删除以 BACKUP_PREFIX 开头的目录
    if [[ -d "${OLD_BACKUP}" && "${OLD_BACKUP}" == ${BACKUP_PREFIX}* ]]; then
      echo "  删除旧备份目录: ${OLD_BACKUP}"
      rm -rf "${OLD_BACKUP}"
    else
      echo "  跳过(非备份目录或不存在): ${OLD_BACKUP}"
    fi
  done
fi

echo "==== $(date '+%F %T') 备份及清理完成 ===="

要点说明:

  • BACKUP_ROOT 替换实际备份文件存放的目录
  • MYSQL_USER MYSQL_PASSWORD 替换实际创建的备份账号密码
  • MYSQL_DATA_CONTAINER 替换实际业务数据库mysql容器名称
  • RETENTION_DAYS 这里设置备份保存3天,根据实际情况修改
  • MYSQL_DATADIR 指的是实际mysql容器里面的数据目录,一般默认就是 /var/lib/mysql

二、创建对应的日志管理配置

上面脚本中设置了输出的日志归档到 /var/log/xtrabackup/backup.log ,为了防止日志太大太多我们需要创建一个用于日志文件自动轮换、压缩、删除的工具。

Linux系统自带了一个工具:Logrotate

Logrotate 是一个 Linux/Unix 系统工具,主要用来管理系统生成的日志文件,这里我们直接创建对应我们脚本的日志管理配置内容:

shell 复制代码
sudo sh -c 'echo "/var/log/xtrabackup/backup.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    create 644 root root
    dateext
    dateformat -%Y%m%d
}" | tee /etc/logrotate.d/xtrabackup'
配置参数 含义说明
文件路径 管理 /var/log/xtrabackup/backup.log 日志。
daily 每天轮换一次。
rotate 7 保留最近 7 份旧日志。
compress 压缩旧日志。
delaycompress 延迟压缩旧日志。
copytruncate 复制旧日志后,清空原文件,让程序继续写入。
create 创建新日志文件的权限和所有者。
dateext 旧日志以日期命名。
missingok 日志不存在不报错。
notifempty 空日志不轮换。

测试一下

shell 复制代码
sudo logrotate -f /etc/logrotate.d/xtrabackup

正常情况日志目录下会生成:

backup.log-yyyymmdd

backup.log

三、创建定时任务

创建定时任务可以先手动执行一下脚本看下

shell 复制代码
sudo ./mysqlbackup.sh

上面的脚本放在 /data/apps/xtrabackup/backup/mysqlbackup.sh

shell 复制代码
sudo crontab -e

输入:

复制代码
0 6 * * * /data/apps/xtrabackup/backup/mysqlbackup.sh

这里是每天早上6点执行,可以根据实际情况修改时间。

查看定时任务

shell 复制代码
sudo crontab -l

结束语

本次脚本也是借助AI工具生产,经过了多次修改调试,适用于中小型业务场景的数据库备份操作。

欢迎各位测试交流其中的不足之处。

相关推荐
好好生活_1 天前
【Docker基础学习】从VM虚拟机到Docker
运维·docker
孤岛悬城1 天前
46 Docker资源管理
docker·容器·云计算
I · T · LUCKYBOOM1 天前
30.Firewalld-Linux
linux·运维·安全
沙滩小绵羊1 天前
Linux常见命令
linux·运维·服务器
cab51 天前
如何解决由于 Docker 的大日志文件导致磁盘空间不足的问题
docker
iru1 天前
nginx被报CVE-2025-1695漏洞,检查后反馈是误报
运维·nginx
天河归来1 天前
本地windows环境升级dify到1.11.1版本
java·spring boot·docker
么么...1 天前
在 Ubuntu 上安装 Docker 并部署 MySQL 容器
linux·运维·经验分享·笔记·mysql·ubuntu·docker
翼龙云_cloud1 天前
亚马逊云渠道商:Lightsail 如何制定备份与快照策略以平衡安全及成本?
运维·安全·云计算·aws
学Linux的语莫1 天前
kompose、docker转k8s
docker·容器·kubernetes