如果你的备份已经躺了三个月没验证过,建议先看看这几家的机器配置和技术说明:eugamehost(自有数据中心服务器),需要一台干净的机器做恢复演练、或者把备份放到异地机房的,可以对比一下他们的配置和线路。
做异地容灾演练还要一台干净的落地机器、并且数据自己攥在手里的话,pqs 私有云(自建私有云方案) 这类自建私有云的方案也可以放进对比表里,看看是不是更贴合你的恢复环境要求。

去年冬天,一个客户给我打电话,说磁盘阵列坏了一块,RAID 重建完数据是回来了,但整个网站起不来。原话是:「备份我天天跑,哪儿会有问题。」
我过去一看,他的备份策略写得很漂亮:每天凌晨两点 mysqldump 全量,加 binlog 增量,脚本跑完往对象存储里一传,保留 30 天。定时任务面板上一片绿色,监控从不报警。
问题在于,这套东西除了「备份」这一步,从来没被「恢复」过。我们花了两个通宵,才把那份三个月的备份文件跑通,问题就出在几个特别朴素的地方,每一个单独看都不算错,凑在一起就是一次完整的翻车。
最常见的一种。他的 dump 文件是压缩后传到远端的,脚本只检查了「文件存在」和「大小不为 0」,没做校验。三个月前有一台机器的磁盘开始出现坏道,mysqldump 报了一行 warning 就退出了,因为脚本没检查退出码,那个残缺的 gz 文件照样进了对象存储。
更狠的是,坏道是渐进的。恢复演练的时候才发现,最早那份 dump 解压到最后一行直接截断,尾部的建表语句和全部 INSERT 都没了。
所以备份完别急着睡觉。三件事必须做:dump 完检查命令退出码,不是 0 就报警;压缩包做一次实际解压测试,别只看文件大小;至少给一份做校验和(md5 或 sha256),恢复演练时对得上才算数。我现在的习惯是每周挑一个最早的文件,解压出来丢进临时库跑一遍 SELECT COUNT(*),比什么监控都实在。
数据库数据恢复了,应用起不来。缺的是 /etc 下的应用配置、SSL 证书、密钥文件、crontab 里那些没人记得的定时任务,以及 systemd 自定义的 unit 文件。
这类东西的特点是:不备份的时候你根本不会想到它,恢复的时候才发现少一块。我们最后的做法是给每台机器做一份配置清单,把 nginx 配置、systemd unit、密钥文件(加密后)打包成一个独立的包,跟着数据备份一起走,同时单独存一份到密码管理器。

生产上是 MySQL 8.0,恢复用的机器上装的是 5.7,导进去直接报语法错误。PostgreSQL 这边更明显,pg_dump 的版本必须大于等于目标库的版本,老版本导出的备份在新的机器上根本用不了。
反过来也一样:pg_dump 12 生成的备份,恢复到 14 上没问题,但恢复到 11 就会失败。这不是配置问题,是格式的问题。
解决办法是固定恢复环境的版本,并在演练脚本里把版本检查放在第一步。别指望「随便找台机器恢复一下」,恢复环境本身就是方案的一部分。
这个坑最隐蔽。演练的时候我们先起了应用再导数据,结果应用启动时就去读数据库,连接池全部报错,日志刷屏,后面导数据的任务被拖慢甚至超时中断。
正确的顺序是:先确认网络和存储就绪,再导数据并做校验,然后按依赖顺序拉起中间件和缓存,最后才启动应用,而且要用受控流量启动,等健康检查过了再切全量。这个顺序我后来写进了 playbook,演练时严格照着走,不再临场发挥。

很多团队的灾备文档里写着「RTO 4 小时」,这个数字是怎么来的?没人知道,通常是开会时拍脑袋定的。
真正做一次演练才发现,端到端恢复花了 6 小时 40 分钟,其中 5 小时耗在从远端拉备份文件上,因为演练机只有 100M 带宽,一个 80G 的压缩包传了整整一晚上。这不是演练机的问题,是方案的问题:真出事的时候,你不可能慢慢传。
所以演练要记录具体数字:数据恢复耗时、依赖服务恢复耗时、应用可用耗时、总共多少人参与。另外要注意演练机器本身的规格,别拿一台低配的玩具机跑演练,测出来的数据对生产没有参考价值,反倒会误导人。

我现在的做法是:每季度一次完整演练(换一台干净的机器,从零恢复,跑通业务验证);每月一次抽样演练(随便挑一份备份,只验证能不能解开、数据行数对不对);每半年一次带时间压力测的演练(记录真实 RTO,并和文档里的目标对齐)。
演练的产出不是一份 PPT,而是三样东西:一份能跑的 playbook、一组真实的时间数据、一条明确的改进项。改进项要有人跟、有人改,改完在下次演练里验证,不然它就只是躺在文档里的一句漂亮话。
说到底,备份的价值不在于你存了多少,而在你最需要它的那天,它能不能在两小时内变成一个能用的系统。没演练过的备份,本质上只是一个让你感觉安全的文件。