备份正在运行的 MySQL 容器数据卷的最小停机方案
解读
国内生产环境普遍要求 7×24 可用,MySQL 又是多数业务的核心库,直接 docker stop 再 tar 会触发 主备切换、告警风暴、客诉升级。因此“最小停机”≠零停机,而是把 不可写窗口压缩到秒级甚至毫秒级,并保证 备份一致性、可验证、可回滚。面试官想看到:
- 你能用 Docker 原生能力 解决,而不是简单甩给 DBA;
- 你熟悉 MySQL 事务日志、锁、刷盘机制;
- 你能给出 回滚预案 与 自动化脚本,而不是只背命令。
知识点
- 数据卷类型:named volume、bind mount、tmpfs,备份前必须
docker inspect确认 驱动类型(local、nfs、cephfs)与 挂载点。 - 一致性模型:MySQL 默认 REPEATABLE READ,需借助 FLUSH TABLES WITH READ LOCK(FTWRL) 或 快照备份(xtrabackup) 保证 InnoDB 页级一致性。
- Docker 卷快照:overlay2 不支持原子快照,必须 冻结 IO 或使用 外部存储快照(如 LVM thin-pool、阿里云云盘快照、Ceph RBD snapshot)。
- 二进制日志坐标:备份瞬间需记录 binlog file & position,用于 主从增量补偿。
- 非 root 运行:官方镜像
mysql:8默认 mysql(999) 用户,备份脚本需--user $(id -u mysql)避免权限漂移。 - 安全传输:国内合规要求 备份落盘即加密,使用 aes-256-cbc 或 KMS 信封加密,再通过 内网 OSS 或 MinIO 转储。
答案
核心思路:“快照+增量”双保险,秒级冻结,秒级恢复写。
步骤如下,全部用 Docker CLI 完成,不依赖宿主机 root 权限(满足企业 最小权限 审计):
-
预检
docker exec mysql sh -c 'mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT @@global.binlog_format,@@global.gtid_mode;"'确认 binlog=ROW 且 gtid_mode=ON,为后续 增量补偿 做准备。
-
创建一致性快照(秒级停机)
a. 进入容器加 全局读锁:docker exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e " FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS\G system echo 'lock-$(date +%s)' > /var/lib/mysql/backup_lock_point;"b. 在 宿主机 对数据卷做 原子快照(以 LVM 为例):
lvcreate -s -n mysql-snap -L 5G /dev/mapper/vg-mysql耗时 <1s,锁期间 IO 冻结,但 不关闭连接。
c. 立即 解锁:docker exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "UNLOCK TABLES;"不可写窗口 ≈ 快照创建时间,生产实测 300~800 ms。
-
备份快照
挂载快照到临时容器,流式压缩加密 直传对象存储:docker run --rm \ -v mysql-snap:/snapshot:ro \ -v /backup:/backup \ -e PASSPHRASE=$BACKUP_KEY \ alpine \ tar -C /snapshot -czf - . | \ gpg --symmetric --cipher-algo AES256 --compress-algo 1 --passphrase-fd 3 3<<<"$PASSPHRASE" | \ rclone rcat minio:mysql-backup/full-$(date +%F).tar.gz.gpg -
清理快照
lvremove -y /dev/mapper/vg-mysql-snap -
验证
启动 临时实例 做 crash-recovery:docker run --rm \ -e MYSQL_ALLOW_EMPTY_PASSWORD=1 \ -v mysql-snap-recovery:/var/lib/mysql \ mysql:8 \ --initialize-insecure \ --skip-networking &>/dev/null && \ docker logs mysql-recovery 2>&1 | grep -q "ready for connections"确保 ibd 文件无损坏,gtid 集合连续。
-
增量补偿(可选)
若窗口 >1s 或 业务敏感,用 binlog 补偿:docker exec mysql mysqlbinlog --start-position=$POSITION --stop-datetime="$(date -d '+1 hour' -Iseconds)" mysql-bin.000123 > inc.sql恢复时先全量 snapshot,再 source inc.sql,达到 秒级 RPO。
回滚预案:
- 快照失败 → 解锁 后重试,最多 3 次,仍失败则降级到 xtrabackup 热备(无锁,但 CPU 飙升 30%)。
- 上传中断 → rclone 支持 chunked retry,断点续传。
- 加密 key 丢失 → KMS 定期轮转,备份头 32 byte 存于 Vault,可解密历史文件。
拓展思考
- Serverless 场景:阿里云 FC + NAS 无 LVM,可用 NAS 快照 API 替代,快照时间 100 ms,费用 0.02 元/GB/月。
- K8s sidecar 模式:用 Velero + Restic 做 Pod 级备份,但 Restic 不支持 FTWRL,需改 xtrabackup sidecar,镜像体积 +180 MB,需评估 调度压力。
- 跨 Region 容灾:国内 华北-华东 延迟 25 ms,可 异步复制 binlog 到 OSS,再用 DLA(数据湖分析) 做 即时查询,实现 15 min 级容灾演练。
- 合规审计:等保 2.0 要求 备份保留 6 个月,加密密钥与数据分离存储,建议 **备份文件命名带 shard-id 与 hash,防止 勒索篡改。