备份做了不等于能恢复:采集数据恢复演练的工程实践
我们的采集数据备份跑了整整一年,每天自动执行,日志一片绿。直到有一天 SQLite 文件损坏,轮到「恢复」上场——结果恢复流程在文档里只有一句话「复制回去就行」,真执行时各种报错,折腾了大半天。那一刻我才明白:没演练过的备份,等于没有备份。 这篇记录我们后来补上的恢复演练机制。
第一步:先盘点备份现状
演练之前,先回答四个问题:
- 备了什么:数据库文件、原始响应归档、日志,是否都在备份范围内?
- 多久一次、保留多久:日备份?周归档?保留期覆盖「重放地平线」吗?
- 备份方式:SQLite 用在线
backup()(比直接复制文件安全);PostgreSQL 用pg_dump还是pg_basebackup? - 备份文件是否被验证过:能打开吗?行数对吗?
这轮盘点通常就有惊喜——比如发现某个「备份」脚本其实一直输出到错误路径。
第二步:定演练周期与范围
- 每月快速演练:把最近一份备份恢复到临时库,校验行数和最新日期,确认「备份本身健康」
- 每季度完整演练:恢复 + 跑一轮完整的日报流程(采集→入库→报表),对比产出的报表和当前环境的差异
- 演练要测出 RTO/RPO:恢复花了多久(RTO)、丢失了多少数据(RPO)——别把没测过的数字写进承诺里
第三步:写演练脚本(恢复 + 校验)
import sqlite3
BACKUP = "backup/serp-2026-09-01.db"
def verify_restore():
# 恢复:把备份灌进一个临时库(不动任何生产数据)
restored = sqlite3.connect("restore_check.db")
src = sqlite3.connect(BACKUP)
src.backup(restored) # SQLite 官方在线备份方式
src.close()
# 校验 1:能打开 + 基本查询正常
row = restored.execute("SELECT COUNT(*) FROM results").fetchone()
count = row[0]
# 校验 2:数据新鲜度(备份里最新的采集日)
latest = restored.execute("SELECT MAX(day) FROM results").fetchone()[0]
# 校验 3:抽一条业务查询,比对生产库的近期结果
sample = restored.execute(
"SELECT keyword, day, MIN(rank) FROM results "
"WHERE day >= ? GROUP BY keyword LIMIT 5",
(latest,),
).fetchall()
print(f"行数: {count} | 最新数据日: {latest}")
for row in sample:
print(" ", row)
restored.close()
verify_restore()
要点:在临时库里恢复(别直接覆盖生产),校验要落在数据层面(行数、最新日期、业务查询),而不是「能打开」就完事。
PostgreSQL 同理:pg_restore 到一个临时库(或 Docker 起的临时实例),然后跑同样的行数与抽样校验。
第四步:恢复后的「业务验证」
光校验数字还不够,还要证明「业务能接着跑」:
- 用恢复出来的库跑一遍日报生成的完整流程
- 对比产出的报表和当前环境同一天的数字(差异即信号)
- 跑一次采集写入,确认恢复后的库「能写、不报错、幂等正常」
备份健康 ≠ 业务可用——这一步补上的是最后一环。
第五步:记录演练结果
每次演练记录:日期、恢复耗时(RTO)、校验数字、发现的问题。文档化有两个作用:一是下次演练有对比基线;二是审计时「我们证明过备份可用」是有据可查的,不是口头保证。
踩坑记录
坑 1:备份文件是坏的但没人发现。 备份脚本静默失败、文件 0 字节、或者只备份了半截——不校验的备份等于没备份。每次备份后自动跑一次校验(能打开 + 行数 > 0)。
坑 2:恢复流程只在生产环境验证过。 换个环境(新服务器、容器)恢复就失败:版本差异、路径权限、依赖缺失。演练就为了暴露这些——尽量在「全新环境」里演练。
坑 3:只验证「能打开」。 SQLite 能打开但缺了最近的表、Postgres 恢复一半报错却没人看退出码。校验要落数据层面。
坑 4:演练直接覆盖生产数据。 一个手滑,演练变成事故。永远在临时库/临时实例上演,演练脚本里禁止连生产路径。
坑 5:把没测过的 RTO/RPO 写进文档。 「30 分钟内恢复」如果没有演练数据支撑,出事时就是违约。演练记录就是这两个数字的唯一来源。
坑 6:演练结果不存档。 三个月后问「上次演练怎么样」答不上来。记录进文档,最好也进审计。
工程清单
- 盘点备份范围、频率、方式、是否验证过
- 月快速 + 季完整的演练节奏,测出 RTO/RPO
- 演练脚本:临时库恢复 + 行数/日期/业务查询三层校验
- 恢复后跑一遍完整业务流程(日报 + 写入)
- 演练结果存档,作为审计依据
- 备份任务本身带校验,静默失败要告警
恢复演练的本质,是把「我们相信备份有效」换成「我们验证过备份有效」。前者是自我安慰,后者是工程事实。采集数据的备份尤其值得演练——数据是时间序列,丢一天的窗口永远补不回来,而「恢复不了」比「丢数据」更糟:前者是灾难,后者至少还有备份。
校验和业务查询里用到的字段(day、rank)语义见 SerpBase 官方文档。你们的备份演练过恢复吗?评论区聊聊第一次演练翻车的经历。

浙公网安备 33010602011771号