首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【AlmaLinux+Docker MySQL 实战】:自动化备份与恢复(备份策略·脚本编写·恢复演练)

【AlmaLinux+Docker MySQL 实战】:自动化备份与恢复(备份策略·脚本编写·恢复演练)

作者头像
IT咸鱼
发布2025-06-09 17:56:40
发布2025-06-09 17:56:40
5230
举报

作为 DBA,万一一场“你以为的备份”没有发生,就可能让业务在一秒内崩塌。怎样才能保证备份脚本一键跑起、有问题及时知晓、恢复流程随时可演练?这篇文章将从“备份策略”“脚本编写”到“恢复演练”三个知识节点,带你一步一步彻底搞定 MySQL 自动化备份与恢复。

一、环境概览与组件关系

在正式操作之前,我们先回顾一下整个环境里都有哪些组件,它们之间是什么关系,日常命令应该在什么地方执行。

服务器

容器名称

MySQL 角色

职责与关系

命令执行环境

master

mysql-master

主库

负责所有写操作并生成 binlog,用于从库同步。需要在备份脚本里从主库导出数据,然后把备份文件存到宿主机或远程存储。

在 master宿主机终端执行 Docker 相关命令,脚本也写在宿主机里,通过 docker exec进入容器执行 mysqldump。

node1

mysql-node1

从库1

从主库实时读取 binlog,保持数据同步;一般只读。备份时可针对从库做逻辑备份(可选)。

在 node1宿主机终端执行 Docker 命令,若需要从容器里做恢复演练,可进入容器执行 mysql 命令。

node2

mysql-node2

从库2

同上,从主库读取 binlog。

与 node1 相同。

  • 备份脚本:通常挂载在主库宿主机的某个目录下,执行时会通过 docker exec mysql-master进入容器,调用 mysqldump导出数据。
  • 恢复演练:可以把备份文件拷到任意服务器(比如 node1),然后在从库容器或一个新容器上恢复,确保备份可靠。

提示:后面所有涉及到 dockermysqldumpgziptarmysql等命令的操作,都分别在宿主机(安装 Docker、脚本存放地)或容器内(数据库操作)执行。文中会在每个命令块前标注“执行场景:xxx”。


二、备份策略 & 目录规划

2.1 为什么要先规划目录?

如果随意把备份文件放在 /root/home里,一旦磁盘满了或者误删,就会非常麻烦。

建议把所有脚本、备份文件都放在一个统一目录,比如:

代码语言:javascript
复制

/home/dba/backup-scripts     # 脚本、日志
/home/dba/mysql-backups      # 真正的备份数据存放

按照“每日一份”、“周全备”、“月全备” 的方式命名子目录:

代码语言:javascript
复制

/home/dba/mysql-backups/daily/YYYY-MM-DD/
/home/dba/mysql-backups/weekly/YYYY-MM-DD/
/home/dba/mysql-backups/monthly/YYYY-MM/
2.2 执行场景与命令

在 master 宿主机终端执行:

代码语言:javascript
复制

# 创建脚本存放目录
mkdir-p /home/dba/backup-scripts

# 创建备份文件统一存放目录
mkdir-p /home/dba/mysql-backups/{daily,weekly,monthly}

# 查看目录结构
ls-R /home/dba
  • 如果出现 bash: mkdir: 未找到命令,说明系统基础工具缺失,需要执行: sudo yum install-y coreutils
  • 如果出现权限问题,可在命令前加 sudo,或切换到 root用户再操作。

创建日志目录和权限检查:

代码语言:javascript
复制

mkdir-p /home/dba/backup-scripts/logs
ls-ld /home/dba/backup-scripts /home/dba/mysql-backups

确保目录权限为 dba:dba用户组可读写,避免在脚本执行时因为写文件权限报错。


三、编写自动化备份脚本

下面我们将一步步写一个脚本:backup_mysql_automation.sh,放在 /home/dba/backup-scripts/下,实现每日备份+压缩+清理旧备份功能。

3.1 创建并编辑脚本文件

执行场景:在 master 宿主机终端执行

代码语言:javascript
复制

cd /home/dba/backup-scripts
vim backup_mysql_automation.sh

提示:如果报 bash: vim: 未找到命令,可以先安装 vim或用更简单的 vi

代码语言:javascript
复制

sudo yum install-yvim

或者:

代码语言:javascript
复制

vi backup_mysql_automation.sh

3.2 脚本内容与详细注释

backup_mysql_automation.sh里,粘贴并写好以下内容,每行代码都加注释,方便小白理解。

代码语言:javascript
复制

#!/bin/bash
# ===========================================================================
# backup_mysql_automation.sh —— MySQL 自动化备份脚本
# 环境:AlmaLinux 8.x + Docker + MySQL (主库容器名称:mysql-master)
# 目标:每日凌晨2点做一次逻辑备份,保留7天的备份,按日期分类存放
# ===========================================================================

# —— 一、变量定义 —— 
# 数据库容器名称(必须与实际容器名保持一致)
CONTAINER_NAME="mysql-master"

# 备份存放根目录(宿主机路径)
BACKUP_ROOT="/home/dba/mysql-backups"

# 日志目录,用于记录备份过程
LOG_DIR="/home/dba/backup-scripts/logs"

# 保留天数(超过此天数的备份自动删除)
RETENTION_DAYS=7

# 当前日期,用于生成目录和文件名
DATE=$(date +"%F")
TIME=$(date +"%H%M")

# 当天的备份目录,如 /home/dba/mysql-backups/daily/2025-06-10
TODAY_DIR="${BACKUP_ROOT}/daily/${DATE}"

# 备份文件名称,如 mysql_master_2025-06-10_0200.sql.gz
BACKUP_FILE="${TODAY_DIR}/mysql_master_${DATE}_${TIME}.sql.gz"

# 日志文件,如 /home/dba/backup-scripts/logs/backup_2025-06-10.log
LOG_FILE="${LOG_DIR}/backup_${DATE}.log"

# —— 二、命令检查 —— 
# 确保宿主机上有 docker、gzip、tar 等命令,否则脚本无法正常执行

forcmdindockergziptar;do
command-v$cmd>/dev/null 2>&1
if[$?-ne0];then
echo"[ERROR] 未检测到命令:$cmd,请先安装后再运行脚本。"|tee-a"$LOG_FILE"
echo"[INFO] 安装命令示例:sudo yum install -y $cmd"|tee-a"$LOG_FILE"
exit1
fi
done

# —— 三、创建当天备份目录和日志目录 —— 
mkdir-p"$TODAY_DIR"
if[$?-ne0];then
echo"[ERROR] 创建目录 $TODAY_DIR 失败,请检查权限。"|tee-a"$LOG_FILE"
exit1
fi

mkdir-p"$LOG_DIR"
if[$?-ne0];then
echo"[ERROR] 创建目录 $LOG_DIR 失败,请检查权限。"|tee-a"$LOG_FILE"
exit1
fi

# —— 四、备份开始 —— 
echo"[$(date +"%F %T")] 开始备份 MySQL 主库 ($CONTAINER_NAME)"|tee-a"$LOG_FILE"

# 在宿主机上执行 docker exec 进入容器并调用 mysqldump,然后通过管道 gzip 压缩输出到备份文件
# 执行场景:宿主机终端
dockerexec$CONTAINER_NAME\
sh-c"mysqldump -uroot -p'你的密码' --all-databases --single-transaction --quick"\
|gzip>"$BACKUP_FILE"

# 检查备份是否成功
if[$?-eq0];then
echo"[$(date +"%F %T")] 备份成功:$BACKUP_FILE"|tee-a"$LOG_FILE"
else
echo"[$(date +"%F %T")] 备份失败"|tee-a"$LOG_FILE"
exit1
fi

# —— 五、清理过期备份 —— 
echo"[$(date +"%F %T")] 开始清理 ${RETENTION_DAYS} 天前的备份"|tee-a"$LOG_FILE"
find"$BACKUP_ROOT/daily"-maxdepth1-type d -mtime +$RETENTION_DAYS\
-execrm-rf{}\;\
-print|tee-a"$LOG_FILE"
echo"[$(date +"%F %T")] 清理完成"|tee-a"$LOG_FILE"

# —— 六、结束 —— 
echo"[$(date +"%F %T")] MySQL 备份脚本执行结束"|tee-a"$LOG_FILE"
exit0
关键点说明

命令检查

  • command -v docker:判断宿主机是否安装 Docker。
  • 如果报 bash: docker: 未找到命令,执行: sudo yum install-y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install-y docker-ce docker-ce-cli containerd.io sudo systemctl start docker sudo systemctl enabledocker
  • 同理,若 gziptar缺失,可执行 sudo yum install -y gzip tar

进入容器执行 mysqldump

  • --single-transaction保证 InnoDB 表一致性备份;
  • --quick减少内存占用;
  • 如果主库里有大量数据,用 --single-transaction能避免锁表时间过长。
  • docker exec $CONTAINER_NAME sh -c "mysqldump ..."
  • 如果容器中未安装 mysqldump(极少见,因为官方镜像自带),进入容器后安装: dockerexec-it mysql-master bash # 在容器内部 yum install-y mysql

清理旧版本目录

  • -mtime +7:找到 7 天前的目录;
  • -maxdepth 1:只在一级子目录查找;
  • -print:打印删除的目录路径,便于日志记录。
  • find "$BACKUP_ROOT/daily" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;

日志记录

  • 使用 tee -a "$LOG_FILE"同时输出到终端和日志。
  • 日志文件按日期区分,方便排查哪天备份成功或失败。

兼容性与权限

  • 确保 /home/dba/mysql-backups/home/dba/backup-scriptsdba用户可读写,否则脚本执行时会报“Permission denied”。
  • 一般用 chown -R dba:dba /home/dba来设置权限。

四、配置定时任务(crontab)让备份自动跑

写完脚本后,还需让它 每天凌晨自动执行,否则“手动记得跑”就没用。这里我们用系统自带的 crontab来做。

4.1 检查 crond 服务是否安装并启动

执行场景:在 master 宿主机终端运行

代码语言:javascript
复制

# 检查 crond 服务状态
systemctl status crond

# 如果返回类似 “Unit crond.service could not be found” 或 inactive
sudo yum install-y cronie
sudo systemctl start crond
sudo systemctl enable crond
  • 如果报 bash: systemctl: 未找到命令,说明没有安装或环境问题。先安装 systemd,一般操作系统自带,无需额外安装。若实在缺失,需联系系统管理员。

4.2 编辑 crontab

代码语言:javascript
复制

crontab-e

如果是第一次,会让你选择编辑器,推荐 vimnano

在打开的编辑器里添加一行(示例:每天凌晨 2:00 执行):

代码语言:javascript
复制

0 2 * * * /home/dba/backup-scripts/backup_mysql_automation.sh >> /home/dba/backup-scripts/logs/cron_backup.log 2>&1
  • 0 2 * * *:表示每天 02:00
  • >> /home/dba/backup-scripts/logs/cron_backup.log 2>&1:把脚本所有输出(含错误)追加到 cron_backup.log,便于后续排查

保存退出 (:wq),然后执行:

代码语言:javascript
复制

crontab-l

确认输出里包含刚才添加的任务。

注意:如果执行 crontab -e报错 bash: crontab: 未找到命令,则需要安装 cronie

代码语言:javascript
复制

sudo yum install-y cronie
sudo systemctl start crond
sudo systemctl enable crond

五、备份恢复演练

备份如果没有经过恢复演练,就相当于“没有备份”。下面演示如何把一个备份文件恢复到一个新容器或现有容器,确保流程可行。

5.1 测试恢复:创建一个新的 MySQL 容器(仅用于测试)

执行场景:master 宿主机终端执行

代码语言:javascript
复制

# 下载并运行一个临时测试容器(与生产环境隔离)
docker run -d\
--name mysql-test \
-eMYSQL_ROOT_PASSWORD=testpwd \
-p3307:3306 \
  mysql:8.0

# 等待容器启动
sleep10

# 检查容器状态
dockerps|grep mysql-test
  • 这里把宿主机的 3307 端口映射到容器 3306,用来避免与生产环境冲突。
  • 如果出现 bash: docker: 未找到命令,参考上文命令安装 Docker。

5.2 将备份文件复制到测试容器宿主机下的一个目录

假设最新的备份目录是 /home/dba/mysql-backups/daily/2025-06-10,文件名是 mysql_master_2025-06-10_0200.sql.gz

代码语言:javascript
复制

# 为方便操作,把备份文件复制到一个统一的 restore 目录
mkdir-p /home/dba/restore-test
cp /home/dba/mysql-backups/daily/2025-06-10/mysql_master_2025-06-10_0200.sql.gz /home/dba/restore-test/

5.3 进入测试容器内部并恢复

进入容器

代码语言:javascript
复制

dockerexec-it mysql-test bash

容器内安装必要工具(如果缺少)

代码语言:javascript
复制

# 确保容器里有 gzip 和 mysql 客户端
command-vgzip>/dev/null 2>&1|| yum install-ygzip
command-v mysql >/dev/null 2>&1|| yum install-y mysql
  • 如果报 yum: 未找到命令,说明基础镜像可能是非 yum 系统或缺少 repos。一般官方 mysql:8.0 镜像自带了基本工具,无需额外安装。若出现问题,可跳过,直接在宿主机解压后复制到容器再导入。

在容器内创建一个目录用于放置备份文件

代码语言:javascript
复制

mkdir-p /tmp/restore/

把宿主机的备份文件拷贝到容器内退出容器(exit),然后在宿主机执行:

代码语言:javascript
复制

dockercp /home/dba/restore-test/mysql_master_2025-06-10_0200.sql.gz mysql-test:/tmp/restore/
  • 如果报 bash: docker: 未找到命令,同样先安装 Docker。

再次进入容器

代码语言:javascript
复制

dockerexec-it mysql-test bash

解压并导入备份文件

代码语言:javascript
复制

cd /tmp/restore

# 解压文件
gzip-d mysql_master_2025-06-10_0200.sql.gz
# 解压后的文件名默认为 mysql_master_2025-06-10_0200.sql

# 导入到 MySQL
mysql -uroot -p'testpwd'< mysql_master_2025-06-10_0200.sql

# 如果导入成功,终端无报错
  • 若出现 bash: gzip: 未找到命令,在容器内执行: yum install-ygzip
  • 若出现 bash: mysql: 未找到命令,在容器内执行: yum install-y mysql

5.4 恢复后验证数据

在同一个容器内执行 MySQL 客户端:

代码语言:javascript
复制

mysql -uroot -p'testpwd'

# 进入后查看数据库列表
SHOW DATABASES;

# 进入某个业务数据库,比如 testdb
USE testdb;
SHOW TABLES;

# 随便查一条数据
SELECT * FROM users LIMIT 5;

如果能看到期望的表和数据,说明恢复成功。

5.5 恢复到生产从库(可选)

如果需要把备份恢复到现有从库(谨慎操作,建议先停止从库同步后再恢复):

停止从库容器里的 MySQL 服务

代码语言:javascript
复制

dockerexec-it mysql-node1 bash
mysql -uroot-p# 进入 MySQL
STOP SLAVE;# 停止复制线程
exit# 退出 MySQL
exit# 退出容器 shell

在宿主机停止容器

代码语言:javascript
复制

docker stop mysql-node1

清空容器内旧数据(注意:此操作会删除所有数据,请务必先备份)

代码语言:javascript
复制

# 删除容器内部数据文件夹(示例路径,具体视挂载情况而定)
dockerexec-it mysql-node1 bash
rm-rf /var/lib/mysql/*
exit

把备份导入到从库容器

  • 先像前面一样把备份文件拷贝到 /tmp/restore/
  • 进入容器,解压后导入: dockerexec-it mysql-node1 bash cd /tmp/restore gzip-d mysql_master_2025-06-10_0200.sql.gz mysql -uroot -p'yourpassword'< mysql_master_2025-06-10_0200.sql

重设主从复制位置

代码语言:javascript
复制

dockerexec-it mysql-node1 bash
mysql -uroot-p

RESET SLAVE;# 清空 relay log 等
CHANGE MASTER TO 
MASTER_HOST='主库IP',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='mysql-bin.000005',  # 需要根据 master 最新的 binlog 文件名
MASTER_LOG_POS=120;# 根据 SHOW MASTER STATUS 输出
START SLAVE;
SHOW SLAVE STATUS\G  # 确认 Slave_IO_Running 和 Slave_SQL_Running 都是 Yes
exit
exit

重启从库容器

代码语言:javascript
复制

docker start mysql-node1

验证主从同步是否恢复

代码语言:javascript
复制

dockerexec-it mysql-node1 bash
mysql -uroot-p-e"SHOW SLAVE STATUS\G"

如果两项都正常,说明恢复到从库也成功了。


六、常见问题及排查

6.1 “bash: docker: 未找到命令”

原因:宿主机未安装 Docker。

解决

代码语言:javascript
复制

sudo yum install-y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install-y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enabledocker

完成后执行 docker version,确认安装成功。

6.2 “bash: mysqldump: 未找到命令”

原因:尝试在宿主机上直接运行 mysqldump,但它在容器内。

解决方案

  • 正确做法:使用 docker exec mysql-master mysqldump ...
  • 如果确实希望在宿主机安装客户端: sudo yum install-y mysql
  • 然后: mysqldump -h 主库IP -P3306-uroot -p'yourpassword' --all-databases > backup.sql

6.3 “bash: gzip: 未找到命令” 或 “bash: tar: 未找到命令”

原因:脚本里用了 gziptar,但系统没有安装。

解决

代码语言:javascript
复制

sudo yum install-ygziptar

6.4 容器内报 “yum: 未找到命令”

  • 原因:容器镜像较精简,没带 yum 源,或者基础镜像只带 rpm。
  • 解决
    • 首选方案:不在容器内装包,避免改变镜像。将备份文件在宿主机解压后再拷贝到容器,仅用容器内的 mysql命令恢复。
    • 如果确实需要在容器内安装:先在 Dockerfile 里自定义镜像,或者在容器内先搭建 yum 源。

6.5 “Error 1045: Access denied for user 'root'@'localhost'”

  • 原因:密码错误或权限被修改。
  • 解决
    • 确认脚本里 -p'你的密码'是否正确;
    • 确认复制账号、root 账号是否存在并授权。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT咸鱼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、环境概览与组件关系
  • 二、备份策略 & 目录规划
    • 2.1 为什么要先规划目录?
    • 2.2 执行场景与命令
  • 三、编写自动化备份脚本
    • 3.1 创建并编辑脚本文件
    • 3.2 脚本内容与详细注释
      • 关键点说明
  • 四、配置定时任务(crontab)让备份自动跑
    • 4.1 检查 crond 服务是否安装并启动
    • 4.2 编辑 crontab
  • 五、备份恢复演练
    • 5.1 测试恢复:创建一个新的 MySQL 容器(仅用于测试)
    • 5.2 将备份文件复制到测试容器宿主机下的一个目录
    • 5.3 进入测试容器内部并恢复
    • 5.4 恢复后验证数据
    • 5.5 恢复到生产从库(可选)
  • 六、常见问题及排查
    • 6.1 “bash: docker: 未找到命令”
    • 6.2 “bash: mysqldump: 未找到命令”
    • 6.3 “bash: gzip: 未找到命令” 或 “bash: tar: 未找到命令”
    • 6.4 容器内报 “yum: 未找到命令”
    • 6.5 “Error 1045: Access denied for user 'root'@'localhost'”
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档