如何处理数据库中的delete(将删除的实体移动到存档表中)



我们目前正在开发的信息系统有一个postgresql驱动的数据库。由于删除问题是我一直不愿意完全解决的问题,当项目已经开始时,它开始困扰我,数据库正在慢慢被填满,当用户实际上想要删除不相关的数据时,就会出现一个点。

在我们的例子中,被用户删除的是我们为客户做的一些"工作"。一旦任务完成,用户通常不希望它出现在网页上,所以他们会删除它。起初(当系统处于测试阶段,因此不可能造成任何损害时),用户的删除是对数据库的真正删除。因为它被很好地设置为级联到实体图的最底部,所以它确实删除了所有内容。也花了很多时间。现在我们开始真正使用这个系统,我很害怕意外删除,我让用户无法删除任何东西。

我认为最重要的问题是"在我们的业务领域,‘删除’工作到底意味着什么?"在本例中,有两个点:

  • 用户不想再看到作业列表(除非他们明确请求旧作业列表,因此我必须保留该列表)
  • 一些作业的数据将永久删除,只保留作业状态的一些基本概述

我读过很多关于为什么软删除是好的文章,也读过很多关于为什么软删除不好的文章(比如这里)。在我看来,更好的替代方案是将已删除的作业移到某个归档表中。同时,我会删除工作中不再需要的数据。这样做的好处是,我不必调整所有的查询来处理某种"DeletedOn"列,主作业表也不会被非活动作业弄得乱七八糟。

我遇到的问题更多的是一个技术问题:假设我仍然需要从其他实体到已删除的作业保持一些引用,最好的方法是什么?因为我在其他实体中设置了作业表的外键,所以我不能将作业移到另一个表中,DB不允许我这样做。

通常且经过良好测试的方法是什么?

如果我理解正确,那么您在数据库中有某种"作业",不能删除所有相关信息,但需要保留其中的一部分…

在这种情况下,我有两个选择:
  • 添加作业状态字段
    该字段可以有不同的值,如new/in progress/waiting/delivered/deleted…一旦您更改代码以适应这个新字段,您就有了很大的灵活性……你可以在UI中为用户提供基于Job State的过滤器等等。

  • 添加DeleteOn字段并隐藏
    重命名表,添加字段并创建一个与原始表同名的视图,该视图过滤掉所有设置为DeleteOn的记录…视图获得一个触发器(ON DELETE),它只是为各自的作业设置该字段…没有级联删除,没有混乱/改变代码等。如果需要,您可以扩展触发器,将所有或部分已设置DeleteOn的行移动到归档表…

我不能告诉你什么是通常的和经过良好测试的方法,我只能告诉你对我有用的方法。

我们同意任何数据都不应该因为各种原因(审计、历史存档等)而丢失,所以我们看到了两种可能的结果:

  • 移动数据
  • 将数据标记为已删除并在每次查询时进行过滤
现在的问题是哪个对你来说更贵。
  • 移动数据:在这里,您将需要另一个表(或者一个OLAP数据库?)来持久化所有删除。我想到的第一个成本是双重维护。如果向一个表中添加列,则必须将其添加到历史表中(或更新ETL作业和目标表)。你对ERD所做的每一次更改都必须做两次。

  • 标记数据:更新所有当前查询以考虑该标志。这可能会很痛苦,但它是一次性的(在大多数情况下将是WHERE deleted = 0)。一些orm提供了很好的方法来解决这个问题,而不需要您手动更改查询。另一个问题是你也提到的,你的表格会"脏"。这可能是性能问题,也可能不是,这取决于您生成的数据量。

每次我考虑利弊时,我总是选择软删除,所以现在就看你的情况了。

最新更新