软删除是个好主意吗? [重复]

    这个问题在这里已有答案:                           数据库记录的物理与逻辑/软删除?                                      23个答案                                    
已邀请:
我说这是一个坏主意,一般情况下(也许有一些例外)。 首先,应该定期备份您的数据库,因此您永远不会因为DELETE而永久丢失数据(当然,除非是删除刚添加的数据)。 其次,像这样的软删除意味着你现在必须在这个表的每个查询中包含一个
WHERE IsDeleted = false
子句(如果你正在加入这些表,那就更糟了)。一旦用户或测试人员发现删除的记录再次出现,就会发现这里的错误,这可能需要一些时间。此外,开发人员很容易从COUNT(*)查询中省略WHERE子句,这可能需要更长的时间才能发现(我在一个已经发生多年的项目上工作过;没有多少记录被“删除” ,所以总数接近预期,没有人注意到)。 最后,软删除将在带有人工键的表上工作,但可能无法在具有自然主键的表上工作(例如,您从社会安全号码键入的表中“删除”某人 - 当您执行时,您会怎么做需要添加他吗?请不要说“在复合主键中包含IsDeleted”。)。 在设计评审中,我希望开发人员能够展示成本和收益的意识,并以这种方式提出进行软删除的绝佳理由。 “为什么不这样做?”不是一个很好的理由。     
避免潜在的数据丢失绝不是一个坏主意。 我总是软删除。在需要擦除一个或多个记录的数据库的情况下,我通常采用两步软删除过程,然后清空记录的“回收站”,或文档管理式方法,其中文档记录可以老去,然后在硬删除之前经过批准程序。     
这取决于具体情况。我可以看到法律要求您真正删除某些内容的情况。也许有人要求永久删除您的社会安全号码。或者您可能有一个重复记录要合并到一个记录中。使用已删除的标志保持副本可能没有用处。 还有一个技术缺点:您无法执行级联删除操作,这会自动清除对已删除数据的任何引用以防止外键冲突。这不一定是一个大问题,但要记住这一点。 否则,我认为这是个好主意。     
如果您要使用软删除,最好使用deleted_date字段,而不是is_deleted字段。你得到一个很好的额外数据而不仅仅是位字段。     
软删除的主要问题之一是那些不需要的数据可能会影响db性能。几年前,我的一个客户端要求我对所有数据库项进行软删除,我的解决方法是将所有“已删除”项目移动到备份表,而不是将其留给当前运行的表。     
如果无效删除绝对是灾难性的,恢复应该很简单,这是一个好主意。如果你想跟踪曾经的所有事情也是一个好主意,“删除”实际上只意味着“隐藏”。意思是,这取决于具体情况。     
软删除还允许您从应用程序使用的数据库帐户撤消
DELETE
权限。     
我不会试图“在政治上正确”。如果你提倡软删除,那么你需要进行大脑检查。 1) 首先,通过不删除表中的行,您究竟达到了什么目的?事实上,将来某个时候你可以访问这些行,对吧?那么为什么不创建一个存档表并在那里移动行呢?这有什么问题? 2) 使用软删除,您将在is_active上创建不必要的查询或在某个时间戳列上创建查询。当你编写更简单的查询时,这只是浪费。是的,它可以用于视图,但是视图不是额外的附属物吗?每个视图都是一个额外的SQL,额外的性能成本,在任何商业RDBMS下,一切都只是一个表。除了你不知道如何在表格之上编写查询这一事实之外,没有任何神奇的观点。 3)是的,它可以使用View或MV。但后来我看到生产中的查询做FTS,一切仍然有效!现代硬件和固体软件的奇迹。但那也不是正确的。因此,通过相同的逻辑,仅仅因为它起作用并不意味着它是正确的 4)软删除的复杂性永远不会停留在一个简单的选择。 A)假设您有一个UNIQUE约束。现在您软删除一行,但具有UNIQUE约束的列仍然存在。当你想要重新添加相同的数据时,如果没有额外的“技巧”,你就无法做到这一点。 B)您可能有从表A到表B的关联,当您从表A中软删除某些内容时,您需要确保表B上的独立查询处理该事实。假设一个典型的详细信息页面正在处理一些detail_id。 现在,master_id被软删除,但你仍然可以在任何地方使用master_id的detail_id永久链接。在master_id上进行硬删除时,这些细节根本不存在。现在使用软删除它们仍然存在,并且它们必须知道它们的master_id处于软删除模式的事实。 它不会停留在简单的Table_A.is_active = 0或1阶段。 5)做一些简单而正确的删除操作。 A)没有人必须在任何地方添加任何额外的东西或担心任何事情。 您的应用程序逻辑更简单 您的数据库较小 您的查询更快 只需归档数据+相关部分,你应该很好。     
有时软删除是必要的。例如,假设您有一个引用Products表的Invoice表。一旦您创建了具有特定产品的发票,您就可以永远不会删除该产品(如果您的RI设置正确,它将不会让您)。 此特定方案假定您永远不想删除发票,在真实公司中您可能不想删除历史财务数据。 虽然还有许多其他情况下您无法删除某些数据作为依赖关系的副作用,但由于业务或其他原因导致链条无法删除。     
这取决于数据。由于法律/审计要求,某些数据无法删除。 另一方面,社交网站应该提供删除具有所有相关数据的帐户的选项,包括联系信息,照片,消息等。如果他们不这样做,那将是一个真正的烦恼,例如, Facebook的。     
在oracle中,如果将主键添加到您组成的recycle_bin表中,然后添加行级安全策略,则可以在行位于回收站中时禁止所有查询中的值,从回收站中删除pk将自动恢复所有数据。无需更改其他查询以适应逻辑。     
但是,它带来了成本,因为您需要更新查询和索引才能排除已删除的行。 也许不是切换标志,而是将其移动到另一个“垃圾桶”表。 此外,可以说这只是一个部分解决方案,因为它仅涵盖删除,但是当您更新行时,您仍然会覆盖旧值。 一般来说,除非你真的需要,否则我永远不会删除任何东西。这些天磁盘空间很便宜。当然,有限制,有法律命令要删除的数据,有些数据实际上并不是那么重要,也许你不需要将旧数据保存在同一个表中(在某个地方存档)也会工作)。     
只需加一分钱。我总是软删除;虽然它确实耗费了性能,但非常轻微。想想成本,当您的客户抱怨您的软件在执行某些甚至无法记住的操作后停止运行时。嗯,这可能是一个很好的例子,但你永远不会知道出了什么问题,谁做了什么,之前是什么以及之后插入了什么。在这种情况下,这将派上用场。此功能可用于审计目的,许多客户要求审计此类报告。 此外,在大多数基于工作流程的应用程序中,它作为软件功能/要求,客户对在工作项上执行的“操作”感兴趣;分配了什么值以及谁处理了它等等。     
我是软删除的粉丝。主要是为了防止级联删除。但是,它需要额外的代码,因此如果您正在选择子对象,它将连接到父对象(和所有父对象!),以确保它们都不会被删除。或者,您可以级联软删除,但如果您想稍后恢复它们,您可能不知道哪些子项已被删除以及哪些子项由于级联而被删除。 另外,我在每个对象上保留修订日期时间和修订版用户名,以便我知道最后修改(或软删除)了谁。然后,对于审计跟踪,我创建一个*历史(如CustomerHistory)表,在每个UPDATE到原始表之后插入。这样,在修改或软删除对象后,我会记录谁执行了操作以及对象的最后已知状态。     
我遇到了以下广泛情况的软删除: 情况1:从用户/代码中删除记录,但记录在数据库级别,因为业务有兴趣知道它有该记录。 这些要求主要由业务和业务驱动。通常在核心可能是一个法律要求(如@joshperry& @armandino情景),以获得数据库中的先前记录&为每个更改创建一个新记录。在这一点上,我会看看案例2&评估它是否在具有IsDeleted标志之前满足要求 案例2:跟踪记录演变的审计跟踪 - 在线有大量体面的文章用于保存数据库中记录的审计跟踪 HTH。     

要回复问题请先登录注册