全量备份至少保留2个完整周期加3天缓冲,金融系统≥28天且含每月锚点;命名须含类型、实例、时间戳;目录按月分层;清理需校验依赖关系而非仅按时间。

全量备份保留天数不能只看磁盘空间
保留多少天全备,核心不是“还能塞下几个文件”,而是“最远能恢复到哪一天”。如果业务要求RPO(最大数据丢失量)≤24小时,且采用“每周全量+每日增量”策略,那至少得保留2个完整周期的全备——比如每周日做全备,就得存最近2周的全备,否则一旦上上周的全备被删,中间那7天的增量就失去基线,无法恢复。
常见错误是直接设 DAYS_TO_KEEP_FULL=7,结果周一发现上周日的全备刚被清理,而周六的增量又依赖它,整个恢复链断裂。真实生产中建议:全备最少保留 2 × 全备间隔天数,再加3天缓冲(应对备份失败、延迟上传等)。
- 金融/订单类系统:强制保留 ≥28 天(4周),且必须包含每月1号或第一个周三的全备作为长期锚点
- 中小业务系统:可设为14天,但需确认 binlog 保留时长 ≥ 全备间隔 + 7天(例如全备间隔7天 → binlog 至少留14天)
- 严禁用
find ... -mtime +7这类简单时间判断清理全备,它不识别备份逻辑依赖关系
归档目录结构必须带备份类型和时间戳
备份文件命名混乱是后期清理失败的主因。不要用 backup.sql 或 mysql_backup.tar 这类无信息文件名,它会让脚本无法区分全备/增量、日期、来源实例。
正确命名规则应固化为:full_backup_<em>instance_name</em>_<em>YYYYMMDD</em>_<em>HHMMSS</em>.tar.gz(物理备份)或 dump_<em>db_name</em>_<em>YYYYMMDD</em>.sql.gz(逻辑备份)。目录结构推荐按月分层:/backups/2026/09/full/、/backups/2026/09/inc/,避免所有文件堆在一层导致 find 效率骤降。
- 增量备份文件名里必须含参照的全备日期,例如
inc_20260901_20260902.tar.gz,便于清理时反查基线是否还存在 - 不同MySQL实例的备份必须隔离目录,避免误删(如
/backups/prod-app/vs/backups/staging-api/) - 归档脚本执行前,先
ls -t检查文件名是否符合规则,不符合则报错退出,不自动清理
清理脚本必须区分“过期”和“不可删”两类全备
单纯按时间删会吃大亏。某次事故中,运维脚本清掉了“最近28天外”的全备,但没跳过每月第一个周三的备份,结果审计要求追溯6个月前某笔交易时,发现唯一可用的长期锚点已被删除。
真正安全的清理逻辑是两阶段:先标记“可删”,再校验“是否被增量依赖”,最后才删除。bash 脚本里不能只靠 ! -newermt,得配合 grep -v 排除关键日期:
find "$BACKUP_DIR" -name "full_backup_*" -type f | \
while read f; do
date_part=$(basename "$f" | grep -oE '[0-9]{8}'); \
if [[ $(date -d "$date_part" +%u) == "3" && $(date -d "$date_part" +%d) -le 7 ]]; then
echo "skip monthly anchor: $f"; continue;
fi;
[[ "$date_part"
- 每月第一个周三的全备,用
date -d "2026-09-01" +%u判断星期几,再结合%d ≤ 7确认是否为当月首周 - 清理前务必检查该全备对应的增量备份是否已全部归档完毕,否则删了基线,增量变废纸
- 删除操作必须加
-i或先输出到日志文件人工复核,禁止无确认自动删
binlog 归档与全备生命周期必须对齐
全备只是半条腿,真正实现时间点恢复(PITR)靠的是 binlog。如果全备保留28天,但 binlog_expire_logs_seconds 只设了604800(7天),那超过7天的任何时间点都恢复不了——因为 binlog 早被 MySQL 自动 purge 了。
binlog 保留时长公式必须严格执行:binlog 保留秒数 ≥ (全备间隔小时数 × 3600) + 最大恢复窗口小时数 × 3600 + 3600×24(传输/压缩缓冲)。例如全备每周一次(168小时),要求支持恢复到任意72小时内,则至少要留 168 + 72 + 24 = 264 小时 ≈ 11天,实际配置建议设为14天(1209600秒)。
- 必须定期运行
SHOW BINARY LOGS;和SELECT @@binlog_expire_logs_seconds;核对状态 - binlog 归档不能只靠
cp /var/lib/mysql/mysql-bin.*,正在写的文件会被截断;应使用mysqlbinlog --read-from-remote-server拉取,或依赖FLUSH BINARY LOGS后拷贝新生成的文件 - binlog 文件名也需统一前缀+时间戳,例如
binlog_prod_20260904_120000.000001,方便与全备时间对齐











