数据库:删除或不删除记录

Posted

技术标签:

【中文标题】数据库:删除或不删除记录【英文标题】:Database: To delete or not to delete records 【发布时间】:2010-10-04 21:19:23 【问题描述】:

我不认为我是唯一对此感到疑惑的人。您通常对数据库行为进行哪些练习?您更喜欢从数据库中物理删除记录吗?还是只用“已删除”标志或布尔列标记记录以表示记录是活动的还是非活动的更好?

【问题讨论】:

...无论是在数据库中承受标志的膨胀和冗余,还是将 DELETE 带到记录表中,然后通过删除,结束它们。删除,睡觉; Physical or Logical Delete of Database Record 的可能重复项 【参考方案1】:

这绝对取决于您数据库的实际内容。如果您使用它来存储会话信息,那么当会话到期(或关闭)时,请务必立即擦除它,您不希望那些垃圾到处都是。因为它不能真正再次用于任何实际目的。

基本上,您需要问自己,我是否需要恢复这些信息?就像 SO 上的已删除问题一样,它们绝对应该被标记为“已删除”,因为我们正在积极允许取消删除。我们还可以选择将其显示给选择的用户,而无需做太多额外的工作。

如果您没有积极寻求完全恢复数据,但仍希望将其保留用于监控(或类似)目的。我建议您(当然在可能的范围内)找出一个聚合方案,然后将其推到另一个表中。这将使您的主表保持干净的“已删除”数据,并保持您的辅助表为监控目的(或任何您想到的)而优化。

有关时间数据,请参阅:http://talentedmonkeys.wordpress.com/2010/05/15/temporal-data-in-a-relational-database/

【讨论】:

【参考方案2】:

使用删除标志的优点:

    如果需要,您可以稍后取回数据, 删除操作(更新标志)可能比真正删除要快

使用删除标志的缺点:

    很容易在 SQL 中的某处遗漏AND DeletedFlag = 'N' 数据库在所有垃圾中查找您感兴趣的行会变慢 最终,您可能还是想真正删除它(假设您的系统是成功的。如果该记录已有 10 年历史,并且在最初创建 4 分钟后被“删除”) 它可能会导致无法使用自然键。您可能有一个或多个已删除的行使用自然键,而真实行想要使用相同的自然键。 您可能出于法律/合规原因实际删除数据。

【讨论】:

【参考方案3】:

作为对所有帖子的补充...

但是,如果您打算标记记录,最好考虑为活动记录创建视图。这将使您免于编写或忘记 SQL 查询中的标志。如果您认为这也有目的,您也可以考虑查看非活动记录。

【讨论】:

【参考方案4】:

我很高兴找到这个帖子。我也想知道人们对这个问题的看法。我已经在许多系统上实施了大约 15 年的“标记为已删除”。每当用户打电话说某些内容被意外删除时,将其标记为未删除肯定比重新创建它或从备份中恢复要容易得多。

我们在 Rails 上使用 postgresql 和 Ruby,看起来我们可以通过以下两种方式之一来做到这一点,修改 rails 或添加 ondelete 触发器,然后使用 pl/pgsql 函数将其标记为已删除。我倾向于后者。

至于性能命中,看看 EXPLAIN-ANALYZE 在大表上对少数已删除项目和许多已删除项目的结果会很有趣。

我发现在长期使用的系统中,新用户往往会做一些愚蠢的事情,比如意外删除内容。因此,当人们是新职位时,除了零经验外,他们拥有之前担任该职位的人的所有访问权限。意外删除某些内容并能够快速恢复让每个人都能快速恢复工作。

但正如有人所说,有时您可能出于某种原因需要恢复该特定密钥,此时您需要真正删除它,然后重新创建记录(取消删除并修改记录)。

【讨论】:

【参考方案5】:

我将它们标记为已删除,并没有真正删除。但是,我每隔一段时间就会清除所有垃圾并将其存档,因此不会影响性能。

【讨论】:

【参考方案6】:

如果涉及个人数据,无论哪种方式都存在法律问题。我认为这很大程度上取决于您在哪里(或数据库在哪里),以及使用条款是什么。

在某些情况下,人们可能会要求从您的系统中删除,在这种情况下需要硬删除(或至少清除所有个人信息)。

如果涉及个人信息,我会在您采取任何一种策略之前咨询您的法律部门。

【讨论】:

【参考方案7】:

如果您担心“休眠”记录会减慢您的数据库访问速度,您可能希望将这些行移动到另一个充当“归档”表的表中。

【讨论】:

【参考方案8】:

对于用户输入/管理的数据,我使用了您描述的标志方法,并为用户提供了一个“清空垃圾箱”界面,以便在他们选择时实际删除项目。

【讨论】:

【参考方案9】:

我有一个包含很多依赖项的数据库。因此,我无法删除一些记录,因为其他记录仍然依赖于数据。这是我通常做的;我尝试删除数据,如果它有效,我知道它没有任何依赖关系并且没关系。如果没有,我会捕获错误并将其标记为不活动:

try

    _context.SomeTable.Remove(someEntity);
    await _context.SaveChangesAsync();

catch (DbUpdateException ex) when (ex.InnerException is SqlException && (ex.InnerException as SqlException).Number == 547)

    // Mark as inactive
    someEntity.Active = false;
    await _context.SaveChangesAsync();

【讨论】:

以上是关于数据库:删除或不删除记录的主要内容,如果未能解决你的问题,请参考以下文章

查询及删除重复记录

怎样删除SAP的历史记录

为啥CKModifyRecordsOperation批量删除CloudKit中的记录不删除记录?

如何批量删除数据库里某个表里的多条记录

linux小常识

数据库:表的插入,更新表中的数据记录,删除表中的数据记录