软删除是一个好主意吗?

软删除是好主意还是坏主意?

与其实际删除数据库中的一条记录,不如将其标记为 IsDeleted = true,在恢复记录时,可以将其标记为 False

这是个好主意吗?

实际删除记录,然后将其移动到存档数据库,如果用户想要回记录,那么软件将在存档中查找记录并重新创建它,这样做是否更好?

116035 次浏览

避免潜在的数据丢失从来都不是一个坏主意。

我总是软删除。在数据库需要清除一个或多个记录的情况下,我通常采用软删除的两步过程,然后清空记录的“回收箱”,或文件管理风格的方法,文件记录可以老化,然后通过审批过程之前,硬删除。

如果无效的删除是绝对灾难性的,并且恢复应该很简单,那么这是一个好主意。这也是一个好主意,如果你想保持跟踪的一切曾经和“删除”真的只意味着“隐藏”意思是,这取决于情况。

软删除还允许您从应用程序使用的数据库帐户中获得 撤销DELETE特权。

这取决于具体情况。我可以看到法律要求你真正删除某些东西的情况。也许有人要求将他们的社保号从你的系统中永久删除。或者您有一个重复的记录,您想要合并到一个单一的记录中。使用已删除的标志将重复内容挂起可能并不有利。

还有一个技术上的缺点: 不能进行级联删除,这会自动清除对已删除数据的任何引用,以防止外键违规。这不一定是一个大问题,但是需要牢记在心。

否则,我觉得这是个好主意。

但是,这样做是有代价的,因为您需要更新查询和索引,以便能够排除已删除的行。

也许与其切换一个标志,不如把它移到另一个“垃圾桶”桌子上。

另外,可以说这只是部分解决方案,因为它只包含删除操作,但是在更新行时,仍然会覆盖旧值。

一般来说,不到万不得已不要删除任何东西。现在磁盘空间很便宜。当然,有些数据是有限制的,有些数据是你必须合法删除的,有些数据其实并不那么重要,也许你不需要把旧数据保存在网上和同一个表中(在某个地方存档也可以)。

软删除的主要问题之一是那些不需要的数据可能会影响数据库的性能。几年前,我的一个客户要求我对所有数据库项进行软删除,我的解决方案是将所有“已删除”项移动到一个备份表中,而不是将其留给当前运行的表。

这取决于数据。由于法律/审计要求,有些数据无法删除。

另一方面,社交网站 应该提供了一个选项,删除帐户与所有相关的数据,包括联系信息,照片,信息等。如果他们不这样做,那将是一个真正的烦恼,例如 Facebook。

有时软删除是必要的。例如,假设您有一个引用 Products 表的 Invoice 表。一旦您创建了一个具有特定 Product 的 Invoice,您就永远不能删除该 Product (如果您的 RI 设置正确,它将不允许您删除该 Product)。

这个特定的场景假设您永远不想删除发票,而在真实的公司中,您可能不想删除历史财务数据。

虽然有许多其他的情况下,你不能删除一些数据,作为一个依赖的副作用链不能删除的原因业务或其他。

我说这通常是个坏主意(也许有些例外)。

首先,应该定期备份数据库,这样就不会出现因为 DELETE 而永久丢失数据的情况(当然,除非删除刚添加的数据)。

其次,像这样的软删除意味着您现在必须在这个表上的每个查询中包含一个 WHERE IsDeleted = false子句(如果您正在连接这些表,情况会更糟)。一旦用户或测试人员注意到被删除的记录再次出现,就会发现这里的错误,这可能需要一些时间。此外,开发人员很容易在 COUNT (*)查询中忽略 WHERE 子句,这可能需要更长的时间才能发现(我在一个项目中工作,这种情况已经发生了多年; 没有多少记录被“删除”,所以总数接近预期,没有人注意到)。

最后,软删除在使用人工密钥的表上可以工作,但在使用自然主键的表上可能无法工作(例如,你从一个使用社会安全号码键入的表中“删除”某人——当你需要将他重新添加回来时,你会怎么做?请不要说“在复合主键中包含 IsDelete”。).

在设计评审中,我希望开发人员能够展示出对成本和收益的认识,并提出以这种方式进行软删除的 好极了理由。“为什么 没有要这么做?”不是一个很好的理由。

我是软删除的粉丝。主要是为了防止级联删除。但是,它需要额外的代码,以便如果您选择一个子对象,它加入到父对象(和所有父对象!) 对象,以确保它们都不会被删除。或者你可以级联软删除,但如果你想恢复他们以后你可能不知道哪些孩子已经被删除了,哪些已经被删除由于级联。

此外,我在每个对象上保留修订日期时间和修订用户名,这样我就知道谁最后修改(或软删除)了它。然后,对于审计跟踪,我创建了一个 * History (如 CustomerHistory)表,它在每个 UPDATE 之后插入到原始表中。这样,在对象被修改或软删除之后,我就有了执行操作的人的记录以及对象的最后已知状态。

我遇到了以下大致情况下的软删除:

案例1: 将记录从可见的用户/代码中删除,但是在 DB 级别保留记录,因为企业希望知道它拥有这些记录。
这些需求主要是由业务驱动的,通常核心是一个法律要求(如@joshperry &@armandino 场景) ,要求在数据库中保存以前的记录,并为每次更改创建一个新记录。此时,我将查看 CASE 2并评估它是否满足要求,然后再使用 IsDelete 标志

案例2: 跟踪记录的审计跟踪——网上有大量像样的文章用于保存数据库中记录的审计跟踪

高温。

只是为了增加一分钱。我总是软删除; 虽然它确实花费了性能,但是非常小。想想成本,当你的客户抱怨你的软件停止工作后,她执行某些动作,甚至她不记得。好吧,这可能是一个很大的例子,但是你永远不会知道哪里出错了,谁做了什么,之前是什么,以及之后插入了什么。这样的话,这个就派上用场了。这个功能对于审计目的很方便,许多客户要求审计这类报告。

此外,在大多数基于工作流的应用程序中,它作为一个软件特性/需求出现,客户对在工作项上执行的“操作”感兴趣; 分配了什么值以及谁处理了它,等等。

如果要使用软删除,最好使用 delete _ date 字段,而不是 is _ delete 字段。您将获得一个很好的额外数据,而不仅仅是位字段。

在 Oracle 中,如果您将主键添加到您创建的循环 _ bin 表中,然后添加一个行级安全策略,那么当该行位于循环回收桶中时,您可以禁止所有查询的值,从循环回收桶中删除 pk 将自动恢复所有数据。不需要更改其他查询以适应逻辑。

我不会试图“在这件事上保持政治正确”。如果你提倡软删除,那么你需要做一个大脑检查。

1) 首先,不删除表中的行到底能达到什么目的?事实上在将来的某个时候你可以访问这些行,对吗?那么为什么不创建一个归档表并将行移动到那里呢?这有什么不对吗?

2) 通过软删除,您将创建不必要的关于 is _ active 的查询或关于某个时间戳列的查询。当您编写更简单的查询时,这只是浪费。是的,它将与视图一起工作,但视图不是一个额外的附件吗?每一个视图都是一个额外的 SQL,额外的性能成本,在任何商业 RDBMS 下面的一切都只是一个表。视图没有什么神奇之处,除了您不知道如何在表顶部编写查询这一事实。

3)是的,它将与视图或 MV 一起工作。但后来我看到在生产中的查询做 FTS 和一切仍然工作!现代硬件和可靠软件的奇迹。但那也不代表这是对的。所以按照同样的逻辑,仅仅因为它工作并不意味着它是 好吧

4)软删除的复杂性从来没有停止在一个简单的选择。

A)假设您有一个 UNIQUE 约束。现在您可以软删除一行,但是具有 UNIQUE 约束的列仍然存在。当您想要将相同的数据添加回来时,如果没有额外的“技巧”,就无法做到这一点。

B)可能有从表 A 到表 B 的关联,当从表 A 中软删除某些内容时,需要确保对表 B 的独立查询处理这一事实。假设一个典型的详细信息页面正在处理某个 Details _ id。

现在一个 master _ id 被软删除了,但是仍然有包含 master _ id 的 Details _ id 的永久链接。当您对 master _ id 进行硬删除时,这些细节根本不存在。现在使用软删除,它们仍然存在,并且它们必须意识到它们的 master _ id 处于软删除模式。

它不会在简单的 Table _ A. is _ active = 0或1阶段停止。

5)执行硬删除操作简单而正确。

A)没有人必须添加任何额外的东西或担心任何地方的任何东西。

  1. 您的应用程序逻辑更简单
  2. 你的数据库更小
  3. 您的查询速度更快

只要存档数据 + 相关的片段,你应该是好的。