GitLab.com 无法使用时,GitLab 自己也受到了影响。公司平时在这个平台上开发产品,事故发生后,一些协作工作只能停下来,面向用户的公告却仍然需要发布。[1]
团队当时用上了另一套私有 GitLab 实例。它平常用于安全发布等敏感工作,这次帮助团队继续构建和部署官网,把事故说明发出去。这个细节写在 2017 年 2 月 10 日的官方复盘里,容易被数据库误删的故事盖过去。[1]
事情发生在 2017 年 1 月 31 日。修复数据库复制时,一次误操作删除了主数据库的数据。团队寻找恢复办法,又发现常规备份因为工具版本不匹配而失败,错误通知邮件也没有正常送达。最终使用的,是一份大约六小时前的快照。[1]
按最终复盘,部分数据库变更未能找回,包括一部分项目、评论等记录。代码仓库与 Wiki 数据没有被删除,但服务在故障期间不可用。用户自行部署的实例没有受到这次托管服务事故影响。这里需要分清数据类型与使用范围,不能概括成所有用户的代码都丢了。[1][2]
恢复期间,他们公开了一份持续更新的文档,通过视频直播展示恢复进展,也在 Twitter 发布消息。同时,一个公开监控网站因访问压力无法正常承载,内部监控则仍在工作。[1]
这些记录让我想到,处理故障时至少有两项需要维持的工作:恢复服务,以及让受影响的人知道现在该怎样安排自己的工作。两者相互关联,但不一定使用同一套工具。
如果公告只能通过出故障的主站发布,客服也只能从主站读取联系方式,团队即使知道发生了什么,也可能无法把消息送到需要它的人那里。故障范围因此超出了最初坏掉的功能。这是从案例引出的判断,不是对 GitLab 当时全部系统的推测。
设想一个由两个人维护的文件转码服务。客户上传文件,等任务完成后下载结果。某天,新任务无法提交,旧任务是否完成也还没有查清。这个场景和下面的时间都是用于演练的假设。
一条可用的首次说明可以写成:“上午九点二十分起发现新任务提交失败。已接收任务的处理情况正在核对。我们会在上午十点更新影响范围和处理进度。”它没有把未知的事情写成正常,也没有把下一次更新的时间冒充为恢复时间。
之后即使还没修好,也可以按时说明查清了什么、仍不确定什么、下一次何时更新。对客户来说,这些信息能帮助决定是否调整交付安排。只把公告从“正在处理”改成“全力处理中”,没有增加可供判断的内容。
这段文字最终要能被发出去。对于这个假设团队,我会先画出几条实际依赖:公告放在哪里,通过什么账号登录,发布是否需要主站运行,另一位成员能否在负责人不在时接手。另建一个页面并不自动解决问题;如果它仍依赖同一个失效的登录入口,故障时照样用不了。
一次小范围演练就能暴露一些缺口。让另一位成员不使用主站,在专用演练页面发布一条明确标注为测试的消息,再从普通读者的视角打开。检查是否能登录、更新能否看到、手机是否读得懂,以及两个人是否知道谁负责下一次说明。测试记录保留在内部,避免让真实客户误以为服务正在出事。
公开内容也要经过取舍。GitLab 的复盘提到,最初公开文档保留了操作人员姓名,之后准备在类似情况下隐去姓名。[1] 对小团队而言,需要告诉客户的是影响、措施和可执行的下一步。把后台截图和原始日志整张贴出,可能顺带暴露客户信息,却未必帮助任何人作出判断。
恢复后的说明还需要回到用户任务本身。哪些数据已经核对,哪些仍有缺失,客户需要检查什么,遇到异常从哪里联系,都应明确。服务器重新响应,只能证明服务恢复的一部分;它不能替用户确认原来的工作已经完整回来。
GitLab 的公开记录没有抹去丢失的数据,也不能被用来证明一次直播带来了多少信任或生意。这个故事里可以直接带走的工作,是提前验证:最重要的产品暂时不能用时,团队是否仍能可靠地说清发生了什么,以及下一条消息会从哪里出现。
资料与日期:
- [1] GitLab,Postmortem of database outage of January 31,2017 年 2 月 10 日:官方完整复盘。影响范围、独立实例、公告方式和监控负载均按当时记录转述,不作为今天系统状态。
- [2] GitLab,GitLab.com database incident,2017 年 2 月 1 日:事故初报。初报与最终复盘的丢失时段端点表述不同,本文不拼接成精确到分钟的统一结论;关于数据类型,以最终复盘为主要依据。
- 两篇均于 2026 年 11 月 6 日阅读全文。没有复制公开事件文档里的人员姓名或日志;文件转码场景、公告文字和演练步骤均为本文建议与假设。