我们第一次真的把备份还原了
这台服务器从 8 月 11 日起每天夜里给自己做备份。日志有 163 行。「还原」这个词一行都没出现过。
到今天为止是这样。
这份备份比大多数都好
它在凌晨三点运行,导出所有数据库,把网站目录打包,用一个存储服务商没有的口令把两者都加密,然后上传。之后它做了三件很多备份脚本会跳过的事。
出错就停,而不是继续往下跑。它拒绝小于一兆字节的导出 — 理由就写在文件里:一个 885 字节的「备份」看着像备份,其实不是。上传完之后,它会问对面收到了多少字节,然后比对。
它也确实管用。8 月 26 日凌晨 3:05,打包这一步失败了,脚本中止并把这件事写进了日志,当天早上有人手动重跑了一次。二十二次启动,十九次完成,而那个缺口是看得见的,不是无声的。大声中止,图的正是这个。
这些都不是还原
上面每一项检查都是关于出去那条路的:导出做出来了吗,大小合理吗,字节到了吗。一份读不回来的备份,这些全都能通过。
所以今天,我们把昨夜那份导出里属于计数器的那一半从加密的存储里取回来,解密,从 437 兆字节的整体中切出来,装进了一个挨着线上库的数据库。104 兆字节。从头到尾一分四十四秒。
备份里三十八张表。线上库里三十八张。各处的行数都比线上少几百,对于一份凌晨三点从一个整天都在计数的服务上取的导出来说,这正是应该的样子。
只有演练才能发现的两件事
对那个会去找它的用户来说,这份备份是读不到的。夜里的任务是以 root 身份跑的。用普通登录账号去要同样的文件,存储工具会说它的访问凭证已经失效。这条消息讲的是身份验证,但在着急的时候、在不该醒着的钟点,它的样子和「这里什么都没有」分不出来。
备份本身没有任何问题。跑它的那个账号也没问题。但出事时任何人做的第一件事就是去看 — 而用错账号去看,得到的答复能把人送上一条非常糟糕的路。这一点现在写在还原说明的旁边了。
第二个发现是我的,不是备份的。装载时报了一个错,说时区变量是空的。它来自从「所有数据库」的导出里切出一个库:结尾那行恢复设置的语句引用了一个在文件头部设定的变量,而文件头部不在切片里。备份没问题。刀是我的。写在这里,是因为还原演练中出现的错误消息,恰恰是那种会被没有亲手切过文件的人当成备份缺陷报上去的东西。
还有什么没验证
脚本在自己的开头就说了:没有那两个口令文件,备份就是不可恢复的,而它们该放在一个能挺过这台机器被毁的地方。两个文件都在这台机器上。别处是否还有一份,这不是在这台机器上做的演练能回答的问题,而这篇文章也不会假装它回答了。
今天之后诚实的状态是:从加密存储到一个能用的数据库这条链,完整地走过了一次,用了不到两分钟。从一栋烧掉的房子到一个能用的数据库那条链,没有。
一般化的说法
备份任务验证的是写成功了。还原验证的是读得回来。这是穿过不同代码的两条不同路径,而人们对自己备份的那份信心,几乎全部是第一条挣来的。
这次演练大约花了十分钟写、不到两分钟跑,而它给出了一个再多绿色日志行也给不了的事实:回来的那条路上有一个从没有人走过的身份验证步骤。第二次演练只要两分钟,因为脚本已经有了。这就是该做它的理由 — 不是因为备份可疑,而是因为「我们有备份」和「我们还原过」是两句不同的话,其中只有一句是测量。