警示:软删除引发泼天大祸!
所谓软删除,是一种在不真正执行删除操作的情况下保留数据的简便方法,仅通过标记一个「DELETE」标志来实现。
你在表格中增加了一个新的列,这样在进行「删除」操作时,实际上是更新了这条数据的状态,并在进行数据查询时自动排除那些标记为已删除的数据。
尽管这种做法初看起来简单易行,但它隐藏着潜在的风险 —— 如果不小心让一些本不应该被展示的数据泄露出去,后果可能非常严重。
重大事件警示
我在一家活动票务公司工作时,创建了一个与此类似的拉取请求:
问题就出在了一行代码上:
诚然,软删除机制并非唯一的问题所在。对于这次改动,我本应采取更多的预防措施,比如分步骤进行。CI/CD 流程中的自动化测试本应该能够发现这个错误,但它却还是漏了。万幸的是,这个领域的监控做得很好,问题几乎立刻就被发现并解决了。但是,由此造成的影响和后果还是非常严重的,包括数百个需要退款的重复预订、取消的订单、发送给受影响顾客的道歉邮件,还有一份深夜编写的事故总结报告。
不要使用软删除!
即便在像 GDPR 这样的法规监管下,我们想要保留被删除数据的倾向是可以理解的。开发者可能出于合规、报告、分析的需要,或者仅仅是希望有一个后备方案 —— 以防万一误删数据或需要排查已删除记录的错误。想象这样的场景:一个顾客不慎删除了一张至关重要的发票,或者一个社交媒体用户删去了一条违反规则的评论。在某个宽限期内保留这些被删除的数据看似有其价值。然而,软删除策略实际上带来的问题要比它解决的更多。
复杂性增加
为 active users 的 email 字段创建唯一索引
数据完整性
ERROR: delete on table "users" violates foreign key constraint "orders_user_id_fkey" on table "orders"
DETAIL: Key (id)=(456) is still referenced from table "orders".
自行执行参照完整性可能容易出错,并会增加大量的开发和维护开销。
软删除的替代方案
如果不想在整个代码库中手动归档数据,最好的办法就是在数据库层建立审计跟踪。《PostgreSQL 数据更改跟踪终极指南》(https://blog.bemi.io/the-ultimate-guide-to-postgresql-data-change-tracking/) 概述了 PostgreSQL 的不同策略。我还推荐大家查看我参与的一个名为 Bemi 的开源项目 (https://github.com/BemiHQ/bemi?ref=blog.bemi.io),该项目旨在通过插入数据库和应用程序(支持大量不同的 ORM,如 Bemi-rails )来简化这一过程,从而自动提供上下文数据变更记录。
底线
远离软删除。虽然它们看上去似乎是处理已删除数据的便捷方法,但实际上,它们就像一个即将爆炸的定时炸弹。这是我几年前吃过的苦头,绝对是你不愿意重蹈覆辙的教训。相比之下,使用历史记录或审计表是一个更为明智的选择。这种做法不仅更整洁、更安全,而且长远来看能够避免无数的麻烦。
地址 https://blog.bemi.io/soft-deleting-chaos/