软删除是个好主意还是坏主意?
与其在数据库中真正删除一条记录,你可以将其标记为IsDeleted = true
,当恢复该记录时,只需将其标记为False
。
这是个好主意吗?
是否更好的做法是物理删除记录,然后将其移到归档数据库中,如果用户需要该记录,则软件会在归档中查找记录并重新创建它?
软删除是个好主意还是坏主意?
与其在数据库中真正删除一条记录,你可以将其标记为IsDeleted = true
,当恢复该记录时,只需将其标记为False
。
这是个好主意吗?
是否更好的做法是物理删除记录,然后将其移到归档数据库中,如果用户需要该记录,则软件会在归档中查找记录并重新创建它?
我认为通常来说这是个不好的想法(也许有一些例外)。
首先,你的数据库应该定期备份,因此您永远不应该因为一次DELETE操作而永久性地丢失数据(当然,如果只是删除刚添加的数据,则除外)。
其次,像这样进行软删除意味着您现在必须在该表上的每个查询中包含一个WHERE IsDeleted = false
子句(如果您正在连接这些表,则情况会更糟)。 错误出现时,只有当用户或测试人员注意到已删除的记录再次显示时才会被捕获,这可能需要一些时间。此外,开发人员很容易忘记将WHERE子句从COUNT(*)查询中省略,这可能需要更长时间才能发现(我曾经参与过一个这样的项目,在此项目中,这种情况发生了多年;由于没有太多记录被“删除”,因此总数接近预期,但没有人注意到)。
最后,软删除将适用于具有人工主键的表,但可能无法适用于具有自然主键的表(例如,您从以社会保障号为关键字的表中“删除”某人-当您需要再次添加他时,该怎么办?请不要说“在复合主键中包含IsDeleted”)。
在设计审查中,我希望开发人员能够展示出对成本和收益的认识,并提出执行软删除的一个极好理由。 “为什么不这样做?”不是一个优秀的理由。
UNIQUE
索引可能会导致混乱。例如,尝试注册一个已被软删除的用户名将会失败,即使它目前并未被使用。 - Danny Beckett避免潜在的数据丢失从来都不是一个坏主意。
我通常采用软删除的方式。在需要清除一个或多个记录的数据库中,我通常采用两步法,首先进行软删除,然后清空"回收站"中的记录,或者采用文档管理风格方法,其中文档记录可以被归档,然后在硬删除之前经过审批流程。
这取决于具体情况。我可以看到有些情况你需要合法地永久删除某些信息。比如说,有人要求从你的系统中永久删除他们的社保号码,或者你想将重复的记录整合成一条记录。保留一个带有已删除标记的副本可能并不是一个好主意。
同时还存在一个技术上的缺点:你无法进行级联删除,即自动清除任何对已删除数据的引用,以防止外键违规。虽然这不一定是个大问题,但需要谨记在心。
总的来说,我认为这是个不错的想法。
如果您要使用软删除,建议使用 deleted_date 字段,而不是 is_deleted 字段。这样可以得到一个更有用的额外数据,而不仅仅是一个位字段。
first_name
列和一个last_name
列,你是否也会有一个full_name
列,只是因为应用程序想要一个full_name
属性,还是你会在应用程序中计算它?顺便说一下,deleteDate < Getdate()
应该是多余的。此外,如果不知道你的后端情况,也许你可以实现一个计算列,这样你就不必自己维护两个单独的列的完整性了。http://technet.microsoft.com/en-us/library/ms191250(v=sql.105).aspx - Josh Smeaton软删除的主要问题之一是这些不需要的数据可能会对数据库性能产生影响。几年前,我的一个客户要求我对所有数据库项进行软删除,我的解决方案是将所有“已删除”项目移动到备份表中,而不是留在当前正在运行的表中。
如果无效删除会导致严重后果,而恢复操作应该很简单,则采用此方法是一个好主意。此外,如果你想跟踪所有曾经存在的内容,并且“删除”实际上只是“隐藏”,那么采用此方法也是一个不错的选择。这意味着,是否使用此方法取决于具体情况。
我不会试图在这方面“政治正确”。如果你支持软删除,那么你需要去做一次大脑检查。
1)首先,通过不删除表中的行,您到底实现了什么?只是因为有时将来可以访问这些行,对吧?那为什么不创建存档表并将行移动到那里呢?有什么问题吗?
2)使用软删除会在 is_active 或某个时间戳列上创建不必要的查询。这只是浪费,当您编写更简单的查询时就会遇到困难。是的,它可以在视图中工作,但视图不是额外的附属品吗?每个视图都是额外的 SQL,额外的性能成本,在任何商业 RDBMS 中,所有内容都是表。除了您不知道如何在表之上编写查询之外,没有任何神奇之处。
3) 是的,它可以在视图或 MV 中工作。但是,我已经在生产中看到了执行 FTS 的查询,并且一切仍然正常!现代硬件和可靠的软件的奇迹。但是,这也不意味着它是正确的。所以按照同样的逻辑,仅仅因为它有效并不意味着它是正确的。
4) 软删除的复杂性永远不会停留在简单的选择上。
A) 假设您有一个唯一约束条件。现在您软删除了一行,但具有唯一约束条件的列仍然存在。当您想要重新添加相同的数据时,您无法这样做而不使用其他“技巧”。
B) 您可能拥有从表 A 到表 B 的关联,当您从表 A 中软删除某些内容时,您需要确保对表 B 上的独立查询考虑到了这一事实。假设典型的详细页面正在处理某个详细 ID。现在,master_id 已经被软删除,但是您仍然可以在各个地方看到带有该 master_id 的 detail_id 的永久链接。当您在 master_id 上进行硬删除时,这些详细信息将不再存在。现在,通过软删除,它们仍然存在,并且必须意识到其 master_id 处于软删除模式。
它不会停留在 Table_A.is_active = 0 或 1 阶段。
5) 进行硬删除是简单且正确的。
A) 没有人需要在任何地方添加任何额外的东西或担心任何问题。
只需存档数据和相关部分,您就可以做到这一点。
这取决于数据。由于法律/审计要求,有些数据无法删除。
另一方面,社交网络网站应该提供一个选项来删除帐户及其所有相关数据,包括联系信息、照片、消息等。如果他们不提供,例如 Facebook,这将是一个真正的麻烦。
IsDeleted
属性。结果频繁出现错误。问题很明显:每个普通用户想要针对该表运行的查询都涉及到“未删除”的数据,这意味着几乎99.9%的查询涉及到该表都必须在它的WHERE
子句中添加...AND IsDeleted = 'N'
。自然而然,这常常被省略:不论是编写代码的人忘记了添加它,还是根本不知道他们必须首先添加它。当然,在原始规范中没有这个要求,编写代码的人是在使用他们的主观判断力… - onedaywhen