不小心删了公司数据库,停机45分钟来得及跑路吗……

Anton Zaides 2024-02-25 11:04:00
这本该是一个安静的周六。
 
我收到来自支持团队的消息,说我们的一个客户遇到问题。我判断这个问题的重要程度很高,需要立即解决。15分钟之后,我明确了问题来源——应该删除数据库中的一些损坏订单。
 
这一操作听起来小菜一碟,然而……

 

一、事故还原

 

如果你不在创业公司工作,请不要嘲笑我。
 
由于需要删除的订单有几百个,所以我决定编写一个简单的 SQL 查询语句,而不是手动操作(警告!)。
 
实际语句稍显复杂,在此简化为:

 

  •  
  •  
  •  
  •  
UPDATE ordersSET is_deleted = true
WHERE id in (1, 2, 3)

 

也许你已经猜到这场灾难的影响范围……
 
我按下 CTRL + Enter 并运行这条命令。耗时超过1秒时,我才醒悟过来,客户端 DBeaver 看到空的第三行,同时忽略了第四行
 
没错,我删除了数据库里的全部订单。
 
我感觉整个人都不好了。

 

二、恢复过程

 
深吸一口气后,我意识到得快速行动起来,不能再犯错误浪费时间了。
 
好在恢复工作执行得很好。
 
  • 停止系统——约 5 分钟
  • 创建变更前数据库(幸运的是我们有 PITR)的克隆——约 20 分钟
  • 在等待期间给老板打电话
  • 根据克隆更新生产数据库的信息*—— 15 分钟
  • 启动系统——约 5 分钟
 
*因为公司具备多个独立系统,无法停止所有系统,所以我决定不还原整个数据库,避免在恢复过程中丢失已完成的更改。公司使用 GCP(Google Cloud Platform,谷歌云平台) 提供的托管 PostgreSQL,所以我在更新前创建了新的克隆,导出克隆中的 id 和 is_deleted 列,然后将结果导入到生产数据库中。随后,使用简单的 update + select 语句。
 
显然,我本可以轻易避免这长达 45 分钟的停机时间……
 

三、究竟发生了什么?

 
整个事件听起来是一个你永远不会犯、愚不可及(甚至在大公司根本不允许犯)的错误。
 
没错,问题根本不在于错误的 SQL 语句,人为的小过失从来都不是真正的问题。我运行那条命令这一动作,只是整个事故链条的最后一环。
 
  • 为什么在周末处理生产环境?当时问题并不紧急,也没有人要求我立刻修复故障,我本可以等到周一再处理。
  • 谁会不先在 QA 环境上运行就贸然在生产数据库中更改呢?
  • 为什么我不调用 API而选择手动编辑?
  • 如果没有 API,为什么我没及时与同事沟通,对这一敏感操作双重检查?
  • 最糟糕的是,为什么我没使用事务?其实只要用了 Begin语句,一旦出错,使用 Rollback命令(回滚操作) 就能解决。
 
错误环环相扣,但凡避免任何一个错误,都不可能发生事故。这些失误都可以归因于:我太自信了。
 
不过好在有序的恢复程序阻止了事故连锁反应,如果无法将数据库恢复到正常状态,我都不敢想象后果如何……
 

四、与切尔诺贝利事故有什么关系?

 

几个月前,我阅读了《切尔诺贝利:一部悲剧史》,切尔诺贝利核电站发生的一系列错误使我联想起了那个被诅咒的周末事故(无意低估或与切尔诺贝利核电站事故比较)。

 

  • RBMK 反应堆存在根本技术问题。

  • 以上技术问题并未有效传达。此前发生过涉及该技术问题的事故,但切尔诺贝利团队并不熟悉。

  • 安全检查期间,团队没有按照规范程序操作。

  • 切尔诺贝利核电站爆炸后,苏联政府试图掩盖事实,加剧了损害程度。

 

谁应该负责?

 

反应堆设计师?其他电厂团队未准确传达所遇到的问题?切尔诺贝利团队?苏联政府?

 

所有人都难逃其咎。灾难从来都不是由单一错误导致,而是因一系列错误发生。我们的工作就是尽早打断这一错误链条,并尽力做到最好。

 

五、后续

 

我对与老板的周一谈话没有太多期待。
 
但老板的态度让我惊讶:“(你要)确保不再出现这种情况。但我更欣赏这样——你犯错是因为专注并快速行动,以至于做得越多,搞砸得越多。”
 
这就是我所需要听到的。如果以过于“亲切”的态度说:“没事别担心,谢谢你修复这个问题!”我反而会感觉虚伪。同时,我已经感觉很糟糕了,所以继续吐槽我无济于事。
 
事故后的改进:
 
  • 减少对数据库直接访问的需求,并创建相关的 API
  • 我总是先在 QA 上运行查询(显然,没有什么比灾难更能给人教训)
  • 我与产品经理商量,了解真正紧急和可以等待的事项
  • 任何对生产环境进行更删改操作都需要两个人来完成,这实际上防止了其他错误!
  • 我开始使用事务处理机制

 

六、可供参考的经验教训

 

事故发生后,我向团队同事们讲述了详细过程,没有隐瞒任何细节,也没有淡化我的过错。

 

责备他人还是不追责,是一个相当微妙的选择。当你犯错时,就是一个传递正确信息的好机会。

 

如果你为此道歉 1000 次,同事会认为,当事情发生在他们身上时,你期待他们也要给出相同反应。

 

如果你一笑了之,完全忽视事故影响,同事会认为这程度的错误是可以接受的。

 

如果你承担责任、学习并予以改进——同事也会用这种态度行事。

 

图片

 

七、总结

 
  • 鼓励行动派,关心客户,并积极解决问题。这就是初创企业成功的方式。
  • 犯错要追究责任,寻找避免事故再次发生的方法。
  • 无需落井下石。有些人需要更多责任感鞭策,而有些人则需要更多的鼓励,我更倾向于以鼓励为主。
 
作者丨Anton Zaides  编译丨onehunnit
来源丨zaidesanton.substack.com/p/how-i-destroyed-the-companys-db
 
*本文为dbaplus社群编译整理,如需转载请取得授权并标明出处!欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn
最新评论
访客 2023年08月20日

230721

访客 2023年08月16日

1、导入Mongo Monitor监控工具表结构(mongo_monitor…

访客 2023年08月04日

上面提到: 在问题描述的架构图中我们可以看到,Click…

访客 2023年07月19日

PMM不香吗?

访客 2023年06月20日

如今看都很棒

活动预告