Docker环境下的MySQL全库分离备份及还原教程
作者:凡间晨光
引言
在Docker容器化部署成为主流的今天,MySQL数据库的备份与还原面临着“环境隔离”与“数据安全”的双重挑战。传统全库备份不仅占用大量资源,还难以应对单库异常的快速恢复需求。
本文基于实战经验,详细介绍Docker环境下MySQL全库分离备份方案——通过按业务库拆分备份、自动化脚本执行、压缩存储等技术,实现“轻量备份-精准还原-安全存储”的全流程管理。

一、Docker中mysql分离备份
1. 数据准备(待备份机器上MySQL的容器id、用户、密码)
执行docker ps | grep pxc或者docker ps | grep mysql查看mysql容器,一般是3306端口的那个容器,记录容器id(一般为第一列)

2. 数据库备份步骤
1.创建并执行备份脚本(bak.sh)
#修改以下脚本中的配置项内容,直接执行以下命令即可完成数据库备份
cat > /bak/bak.sh << 'EOF'
#!/bin/bash
# ========== 配置(请根据实际情况修改) ==========
CONTAINER_NAME="xxxxx" #您的MySQL容器名称或id
BACKUP_DIR="/bak/mysql" #修改为要备份的位置目录
MYSQL_USER="xxxxx" #修改为真实数据库用户名
MYSQL_PASSWORD="xxxxx" #修改为真实数据库密码
DATE=$(date +%Y%m%d_%H%M%S)
# ========== 创建备份目录==========
mkdir -p ${BACKUP_DIR}
# ========== 获取数据库列表(过滤系统库) ==========
DATABASES=$(docker exec ${CONTAINER_NAME} mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SHOW DATABASES;" 2>/dev/null | \
grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$")
# ========== 逐个备份 ==========
for DB in ${DATABASES}; do
echo "正在备份数据库: ${DB}"
BACKUP_FILE="${BACKUP_DIR}/${DB}_${DATE}.sql"
docker exec ${CONTAINER_NAME} mysqldump -u${MYSQL_USER} -p${MYSQL_PASSWORD} \
--single-transaction \
--routines \
--triggers \
--events \
-B ${DB} > ${BACKUP_FILE} 2>/dev/null
if [ $? -eq 0 ]; then
echo "✓ 备份成功: ${BACKUP_FILE}"
else
echo "✗ 备份失败: ${DB}"
rm -f ${BACKUP_FILE}
fi
done
echo "所有数据库备份完成!备份目录:${BACKUP_DIR}"
EOF
chmod +x /bak/bak.sh
echo "已更新并添加执行权限,开始备份数据库"
/bak/bak.sh
2.压缩备份结果
tar -czf /bak/mysql_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /bak mysql
注意:如果在Windows上创建的脚本,在粘贴到Linux后,需要将Windows 风格的换行符(CRLF,即\r\n)换成 Linux 系统期望的是 Unix 风格的换行符(LF,即\n),执行以下命令即可:sed -i 's/\r$//' /bak/bak.sh
二、Docker中mysql一键还原
1.数据准备(查看待还原机器上MySQL的容器id、用户、密码)
执行docker ps | grep pxc或者docker ps | grep mysql查看mysql容器,一般是3306端口的那个容器,记录容器id(一般为第一列)

2.数据库还原步骤
1. 创建目录bak,将备份文件复制并解压到bak目录
#创建目录bak mkdir -p /bak/mysql #解压缩命令 tar -zxvf /bak/mysql_backup_20260608_112915.tar.gz -C /bak
2. 创建并执行还原脚本(restore.sh)
#修改以下脚本中的配置项内容,直接执行以下命令即可完成数据库恢复
cat > /bak/restore.sh << 'EOF'
#!/bin/bash
# ===== 配置区(与备份脚本保持一致) =====================
CONTAINER_NAME="xxxxx" #您的MySQL容器名称或id
BACKUP_DIR="/bak/mysql" #修改为备份文件的位置目录
MYSQL_USER="xxxxx" #修改为真实数据库用户名
MYSQL_PASSWORD="xxxxx" #修改为真实数据库密码
# =============================================
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 定义需要跳过的系统数据库列表(恢复时忽略)
SKIP_DATABASES=(
"mysql"
"information_schema"
"performance_schema"
"sys"
"test"
)
# 校验备份目录
if [ ! -d "${BACKUP_DIR}" ]; then
echo -e "${RED}错误:备份目录 ${BACKUP_DIR} 不存在!${NC}"
exit 1
fi
# 检查容器是否运行
if ! docker ps --filter "id=${CONTAINER_NAME}" --format "{{.ID}}" | grep -q "${CONTAINER_NAME}"; then
echo -e "${RED}错误:容器 ${CONTAINER_NAME} 未运行或不存在!${NC}"
exit 1
fi
# 测试 MySQL 连接
echo -e "${YELLOW}测试 MySQL 连接...${NC}"
if ! docker exec -i "${CONTAINER_NAME}" mysql -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" -e "SELECT 1;" >/dev/null 2>&1; then
echo -e "${RED}错误:无法连接 MySQL,请检查用户名或密码!${NC}"
exit 1
fi
echo -e "${GREEN}✓ 连接成功${NC}"
# 统计变量
TOTAL=0
SUCCESS=0
SKIPPED=0
FAILED=0
# 遍历所有 sql 文件
for SQL_FILE in "${BACKUP_DIR}"/*.sql; do
[ -e "$SQL_FILE" ] || continue
# 提取数据库名:删除末尾时间戳(_YYYYMMDD_HHMMSS.sql),保留完整名称(含 - 等特殊字符)
DB_NAME=$(basename "${SQL_FILE}" | sed 's/_[0-9]\{8\}_[0-9]\{6\}\.sql$//')
# 检查是否在跳过列表中
SKIP=0
for SKIP_DB in "${SKIP_DATABASES[@]}"; do
if [ "${DB_NAME}" == "${SKIP_DB}" ]; then
SKIP=1
break
fi
done
if [ ${SKIP} -eq 1 ]; then
echo "=========================================="
echo -e "${YELLOW}⏭️ 跳过系统数据库:${DB_NAME}${NC}"
((SKIPPED++))
continue
fi
echo "============================================="
echo -e "${YELLOW}开始恢复数据库:${DB_NAME}${NC}"
echo "文件:${SQL_FILE}"
((TOTAL++))
# 执行恢复,捕获输出
TEMP_LOG=$(mktemp)
docker exec -i "${CONTAINER_NAME}" mysql -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" --force < "${SQL_FILE}" > "${TEMP_LOG}" 2>&1
EXIT_CODE=$?
# 判断是否真正失败:排除 ERROR 1105(PXC 严格模式警告)
OTHER_ERRORS=$(grep -i "ERROR" "${TEMP_LOG}" | grep -v "ERROR 1105")
if [ ${EXIT_CODE} -eq 0 ] && [ -z "${OTHER_ERRORS}" ]; then
# 检查是否只有 1105 警告
# if grep -qi "ERROR 1105" "${TEMP_LOG}"; then
# echo -e "${YELLOW}⚠️ 检测到 PXC 严格模式警告(已忽略),数据已正常恢复${NC}"
# fi
echo -e "${GREEN}✅ ${DB_NAME} 恢复成功${NC}"
((SUCCESS++))
else
echo -e "${RED}❌ ${DB_NAME} 恢复失败,错误信息:${NC}"
if [ -n "${OTHER_ERRORS}" ]; then
echo "${OTHER_ERRORS}" | head -10
else
tail -5 "${TEMP_LOG}"
fi
((FAILED++))
fi
rm -f "${TEMP_LOG}"
done
# 输出汇总
echo "============================================="
echo -e "${GREEN}批量恢复执行完毕!${NC}"
echo "总计处理:$((TOTAL + SKIPPED)) 个文件"
echo " ✅ 成功恢复:${SUCCESS}"
echo " ⏭️ 跳过系统库:${SKIPPED}"
if [ ${FAILED} -gt 0 ]; then
echo -e " ${RED}❌ 恢复失败:${FAILED}${NC}"
else
echo " ❌ 恢复失败:0"
fi
EOF
chmod +x /bak/restore.sh
echo "已更新并添加执行权限,开始恢复数据库"
/bak/restore.sh

三、总结
这套Docker环境下的MySQL全库分离备份还原方案,适合中小规模业务,脚本可直接复用。核心是按库分离备份(方便单独还原某个库)和自动化脚本(减少人工操作)。可以结合crontab设置定时备份,比如每天凌晨3点执行:
crontab -e # 添加一行 0 3 * * * /bak/bak.sh && tar -czf /bak/mysql_backup_$(date +%Y%m%d).tar.gz -C /bak mysql --remove-files
数据安全无小事,定期备份+定期还原测试,才能确保关键时刻不掉链子。有问题欢迎在评论区交流,觉得有用的话别忘了点赞收藏!
以上就是Docker环境下的MySQL全库分离备份及还原教程的详细内容,更多关于Docker下MySQL分离备份及还原的资料请关注脚本之家其它相关文章!
