2763 字
约 9 分钟
18
S15-A22 · 冷备的可用性判据:备着不等于能用

团队为一次机房迁移准备了两年的冷备方案:每日备份文件上传到对象存储,脚本每月验一次文件是否完整(能解压、能读到表结构)。迁移当天真的要用时才发现,恢复一次需要十四个小时——而业务给的可接受停机窗口是四小时。

冷备的核心问题不是"有没有备份",而是恢复需要多久,以及这个时长是不是业务能接受的。前者可以测,后者必须先问清楚。两者之间往往差着一个数量级。


1. 冷备的三个指标

指标 含义 谁决定
RPO 能容忍丢多少数据(恢复点) 业务
RTO 能容忍停多久(恢复时长) 业务
实际恢复时长 真跑一遍要多久 只能实测

三者的对齐要在方案设计阶段完成,而不是在事故现场。一个可用的顺序是:先问业务"能接受丢多少、停多久",再拿这两个数倒推方案档位,最后用实测的恢复时长回填验证。反过来(先定方案再套指标)几乎总会得到"方案看起来合理、指标没人对过"的结果。

前两个是业务给的约束,第三个是技术事实。三者不一致时,方案不成立——而这三种数字经常从来没有被放在一起对齐过。常见情况是备份策略按"每天一次"设计(RPO 24 小时),而业务以为"数据一条都不会丢"。

2. 恢复时长由什么决定

组成 典型量级 可压缩性
拉取备份文件 分钟到小时(取决于体积与带宽) 中(预置副本、就近存储)
解压与导入 小时级(取决于数据量) 低(受 IO 限制)
索引重建 小时级 中(可延后)
校验与比对 小时级 中(抽样)
切换与验证 分钟到小时 低(受流程限制)

还有一个常被忽略的成本项:人员与流程。恢复往往不是一个人能完成的动作——需要权限、需要业务方确认数据截止点、需要切换到备用入口。这些协调动作在演练中通常被跳过,而在真实事故里它们可能占掉总时长的一大半。

第二项是主要成本,而它几乎不可压缩:导入一亿行要花的时间,大致等于数据量除以 IO 吞吐。所以缩短恢复时长的真正手段不是优化脚本,而是减少要恢复的数据量——增量备份、分层恢复、只恢复关键表。

// 先量出来,再谈优化:恢复流程的阶段耗时必须可观测
restore_start=$(date +%s)
fetch_backup;              echo "fetch $(( $(date +%s) - restore_start ))s"
import_dump;               echo "import $(( $(date +%s) - restore_start ))s"
rebuild_indexes;           echo "index $(( $(date +%s) - restore_start ))s"
verify_counts;             echo "verify $(( $(date +%s) - restore_start ))s"
// 只有分段耗时,才知道该压哪一段;只测总时长等于没测

3. 三种恢复粒度的取舍

粒度 数据量 恢复时长 适用
全量恢复 全部 最长 灾难、整库损坏
单库/单表恢复 部分 中 局部误删、单表损坏
行级恢复 极少 短(但需要额外工具) 误操作、误更新

三种粒度的成本差别不是线性的:全量恢复的时长随数据量线性增长,而单表与行级恢复的时长几乎与总量无关。所以随数据增长,粗粒度恢复越来越不可行,细粒度恢复的价值越来越高。

第三项最容易被忽略,而它恰恰是最常发生的场景:一条错误的 UPDATE 少了 WHERE,影响三万行。这种情况不需要恢复整个库,只需要把这三万行还原。没有行级恢复能力时,团队只能用全量恢复去解决一个小问题,代价从分钟级变成小时级。

-- 行级恢复的两种实现:从备份表或从解析的 binlog
-- 方式一:备份中带上"恢复窗口"内的表快照
CREATE TABLE orders_restore_20261110 LIKE orders;
INSERT INTO orders_restore_20261110 SELECT * FROM orders WHERE updated_at < '2026-11-10 02:00:00';

-- 方式二:用 binlog 反向解析出被误改的行(需要 binlog 保留与工具)
-- 关键:这两种能力都要在事故发生前就验证过

冷备的另一个实际约束是备份与版本的绑定。恢复出来的数据要能被当前代码正确读取,就需要知道"这份备份对应哪个版本的 schema"。没有这层记录时,恢复后第一件事往往是排查为什么应用启动失败。

// 备份元数据:五项,缺一项都可能让恢复失败
backup_id:     2026-11-09T02:00Z
schema_version: V20261105_03
app_version:    2.14.3
row_counts:    {orders: 12000000, users: 800000}
checksum:      sha256:9f2c...

4. 验证的四个层次

层次 做法 能发现什么
完整性 文件能解压、校验和匹配 备份损坏
可读性 能导入到临时库、表结构对 格式或版本不兼容
业务可用性 抽查关键表行数与业务核对 数据缺失或截断
真实恢复 完整跑一次恢复并计时 RTO 是否成立

四个层次之间存在一个跳跃:前三层验证的是"备份文件没问题",第四层验证的是"恢复流程没问题"。文件与流程是两件不同的东西,前者可以自动化检查,后者必须有人在隔离环境里真的走一遍。

前三个层次大多数团队都做过,第四个很少做——而只有第四个能回答"能不能用"。

// 真实恢复演练:在隔离环境跑完整流程并记录时长
bin/restore-drill \
  --backup s3://bucket/2026-11-09.sql.gz \
  --target db-drill.internal \
  --verify "orders:12000000,users:800000" \
  --report drill-2026-11.md
// 输出的恢复时长必须与业务给的 RTO 对比,而不是只看"成功"

5. 冷备与热备的分界

方案 切换时长 成本 适用 RTO
冷备(仅备份文件) 小时级 最低 天级
温备(定期恢复的备用环境) 十分钟到小时 中 小时级
热备(实时复制) 分钟级 高 分钟级
多活 秒级 最高 秒级

判断的关键是RTO 与成本的对应关系。要求分钟级 RTO 却只做冷备,方案本身就不成立;反之,业务能接受一天停机却做了多活,是过度投入。

四档方案的选择可以用一个简单的问题定:如果现在机房不可用,多久之后业务能继续。答案如果是"一天",冷备就够;如果是"一小时",必须温备;"几分钟"意味着热备或双活。技术方案跟着这个答案走,而不是跟着预算走。

多数系统的真实需求落在"温备"这一档,而它恰恰是最少被选择的——因为它需要"定期把一个环境真的恢复起来",这件事既有成本又要持续维护。

6. 排错:五种"备了但用不了"

现象 成因 处理方向
备份文件无法解压 传输中断或压缩工具版本不符 校验和 + 定期抽样解压
恢复后应用报错 表结构与当前代码不匹配 备份与版本绑定记录
恢复完成但数据不对 备份时点晚于业务预期 明确 RPO 并写入文档
恢复很慢超出窗口 从未实测,只有估算 做一次计时演练
需要恢复时权限不足 存储权限只在个别人手里 恢复权限至少两人可用

排错时还可以先确认一件更基础的事:最近一次成功恢复是什么时候。答不出来,说明这台机器的恢复流程从未被验证,所有关于"能恢复"的判断都是推断。

第五项是组织问题,但它在事故现场最致命:备份在,脚本在,没人有权限从对象存储拉取。恢复权限的可用性与备份的存在性同等重要。

恢复流程本身也需要版本管理。不少团队的恢复脚本是三年前写的,与当前的库版本、路径约定、权限模型都已不匹配——它躺在文档里,看起来像一份能力,实际是一份过期说明。

// 恢复脚本的自检:每次演练前先确认它还能跑通到"只差导入"这一步
bin/restore.sh --dry-run --check-access --check-tools
// 输出应包含:存储可读、解压工具在位、目标库可连、磁盘余量足够
// dry-run 不通过时立刻修脚本,而不是在事故时才发现

7. 边界:什么情况不必做完整演练

场景 为什么 做法
数据可完全重建(缓存、派生数据) 无恢复价值 不备份,直接重建
无状态服务 恢复即重新部署 不涉及数据恢复
试验环境 数据无价值 只做完整性检查
已有热备且切换演练过 冷备只是兜底 降低演练频率

判断口径一句话:这套数据丢了,业务会损失什么。答不出损失,就不必为它做恢复演练;答得出,就必须有实测的恢复时长和可用的恢复权限。


8. 自测

  1. RPO、RTO 与实际恢复时长分别由谁决定?三者不一致时方案为什么不成立?
  2. 恢复时长的主要组成部分中,哪一项几乎不可压缩?缩短总时长该从哪下手?
  3. 为什么行级恢复能力最常被忽略却最常用?没有它会发生什么?
  4. 验证的四个层次中,哪一层才能回答"能不能用"?前三层各能发现什么?
  5. 要求分钟级 RTO 却只做冷备,问题出在哪一步判断?温备为什么最少被选?
  6. 为什么"恢复权限"与"备份是否存在"同等重要?
S15-A22 · 冷备的可用性判据:备着不等于能用
https://www.clxhxhhr.top/posts/6402/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。