火烧眉毛,我是如何在周六删了公司的数据库

原文链接,作者:Anton Zaides。


这本是一个安静的星期六。

我收到了支持团队的一条消息,说我们一个客户遇到了问题。我认为这个问题很重要,值得开始调试。15 分钟后,我明白了问题所在 - 在数据库中有一些损坏的订单需要删除。

听起来小菜一碟。

事故还原

如果你不给创业公司打工,请不要嘲笑我 😅

有几百个订单需要删除,所以我决定不手动操作,而是编写一个简单的 SQL 查询语句(警告 🚩)

实际上比这复杂一些,但这里简化一下:

sql 复制代码
UPDATE orders
SET is_deleted = true

WHERE id in (1, 2, 3)

你大概已经猜到这场灾难的规模了...

我按下了 CTRL + Enter 并运行了命令。当它花费超过一秒钟时,我明白发生了什么。我的客户端 DBeaver 看到空的第三行,并忽略了第四行。

是的,我删除了数据库中所有的订单 😢

我整个人都不好了。

恢复

深吸一口气后,我知道我必须快速行动起来。不能犯更多错误浪费时间了。

恢复工作做得很好。

  1. 停止系统 - 约 5 分钟
  2. 创建变更前数据库(幸运的是我们有 PITR)的克隆 - 约 20 分钟
  3. 在等待期间给我的老板打电话 😨
  4. 根据克隆更新生产数据库的信息* - 约 15 分钟
  5. 启动系统 - 约 5 分钟

*我决定不还原整个数据库,因为无法停止所有系统,因为我们有多个独立的系统。我不想在恢复过程中丢失所做的更改。我们用 GCP 提供的托管 PostgreSQL,所以我从更新之前创建了一个新的克隆。然后,我只导出了克隆中的 idis_deleted 列,并将结果导入到生产数据库中。之后,就是简单的 update + select 语句。

所以显然本可以很容易避免这 45 分钟的停机时间...

发生了什么?

这可能听起来像是一个你永远不会犯的愚蠢错误(甚至在大公司中,根本不能犯)。确实。问题不在于错误的 SQL 语句。**一个小小的人为失误从来都不是真正的问题。**我运行那个命令只是整个失败链条的终点。

  1. 为什么要在周末处理生产环境?在这种情况下,事情并没有那么紧急。没有人要求我立即修复它。我本可以等到星期一再处理。
  2. 谁会在生产数据库上更改而不先在 QA 环境上运行一下呢?
  3. 为什么我手动编辑了数据库而不是通过调用 API?
  4. 如果没有 API,为什么我没打电话给队友,在如此敏感的操作上进行双重检查?
  5. **最糟糕的是,为什么我没使用事务?**其实只要用了 Begin,万一出错时使用 Rollback 就可以了。

错误一层层叠加,其中任何一个被避免了 - 整件事就不会发生。大多数问题答案都很简单:我太自信了。 不过还好通过有章法的恢复程序,阻止了连锁反应。想象一下如果无法将数据库恢复到正确状态会发生什么灾难......

这与切尔诺贝利有什么关系?

几个月前,我阅读了「切尔诺贝利:一部悲剧史」。那里发生的一系列错误使我想起了那个被诅咒的周末(并不是要低估或与切尔诺贝利灾难相比较)。

  1. RBMK 反应堆存在根本技术问题。
  2. 这个问题没有得到恰当传达。之前有涉及该问题的事件,但切尔诺贝利团队对此并不熟悉。
  3. 在安全检查期间,团队没有按程序操作。
  4. 爆炸后,苏联政府试图掩盖事实,从而大大加剧了损害程度。

谁应该负责?

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

所有人都有责任。灾难从来不是由单一错误引起的,而是由一连串错误造成的。我们的工作就是尽早打断这条链条,并做到最好。

后续

我对周一与老板的谈话本没有什么期待。

但他让我惊讶:「确保不再发生这种情况。但是我更喜欢这样 - 你犯了错误是因为你专注并且喜欢快速行动。做得越多,砸得越多。」

那正是我需要听到的。如果以过于「亲切」的方式说:没关系,别担心,谢谢你修复它!我反而会感觉虚伪。另一方面,我已经感觉很糟糕了,所以没有必要进一步吐槽我。

从那时起:

  • 我们减少了对数据库直接访问的需求,并创建相关的 API。
  • 我总是先在 QA 上运行查询(显而易见吧?没有比灾难更能教训人了)。
  • 我与产品经理商量,了解真正紧急和可以等待的事项。
  • 任何对生产环境进行更删改操作都需要两个人来完成。这实际上防止了其他错误!
  • 我开始使用事务处理机制。

可以应用在你的团队中的经验教训

事发后,我和团队详细分享了过程,没有隐瞒任何事情,也没有淡化我的过错。 在责备他人和不追究责任之间有一个微妙的平衡。当你犯错误时,这是一个传递正确信息的好机会。

如果你道歉 1000 次,他们会认为你期望当事情发生在他们身上时,他们也需要给出同样的回应。

如果你一笑了之,并忽视其影响,他们会认为这是可以接受的。

如果你承担责任、学习并改进自己 - 他们也会以同样的方式行事。

总结一下

  • 鼓励行动派,关心客户,并解决问题。这就是初创企业成功的方式。
  • 当犯错时,要追究责任。一起理解如何避免这种情况发生。
  • 没必要落井下石。有些人需要更多的责任感,而有些人则需要更多的鼓励。我倾向于以鼓励为主。

顺便说一句,如果团队采用了 Bytebase 的话,这个事故是大概率可以被避免的,因为 Bytebase 有好几道防线:

  1. 用户不能随意通过使用 DBeaver 这样的本地客户端直连数据库,而必须通过 Bytebase 提交变更工单。
  2. 变更工单的 SQL 会经过自动审查,如果影响范围有异常,会有提示。
  3. 变更工单只有通过人工审核后才能发布。

💡 更多资讯,请关注 Bytebase 公号:Bytebase

相关推荐
程序边界18 分钟前
从 Oracle 到 KingbaseES:企业信创改造的“抄作业”模板,直接套用!
数据库·oracle
funfan051729 分钟前
奇怪的“bug”--数据库的“隐式转换”行为
数据库·bug
Jasonakeke41 分钟前
【重学MySQL】八十八、8.0版本核心新特性全解析
android·数据库·mysql
comeoffbest1 小时前
PostgreSQL 能存万物:从安装到高级功能实战
数据库·postgresql
时序数据说1 小时前
IoTDB如何解决海量数据存储难题?
大数据·数据库·物联网·时序数据库·iotdb
小楓12012 小时前
MySQL數據庫開發教學(二) 核心概念、重要指令
开发语言·数据库·mysql
花果山总钻风3 小时前
MySQL奔溃,InnoDB文件损坏修复记录
数据库·mysql·adb
TDengine (老段)4 小时前
TDengine IDMP 运维指南(管理策略)
大数据·数据库·物联网·ai·时序数据库·tdengine·涛思数据
Full Stack Developme4 小时前
PostgreSQL interval 转换为 int4 (整数)
数据库·postgresql
larance4 小时前
FastAPI + SQLAlchemy 数据库对象转字典
数据库·fastapi