物理与逻辑/软删除数据库logging?

做一个logging的逻辑/软删除(即设置一个标志说明该logging被删除)而不是实际或物理删除该logging的优点是什么?

这是常见的做法吗?

这是安全的吗?

优点是您可以保持历史logging(适合审计),您不必担心通过引用您正在删除的行的数据库中的其他各个表将级联删除。 缺点是你必须编写任何报告/显示方法来考虑这个标志。

至于如果这是一个普遍的做法 – 我会说是的,但与你使用它的任何事情取决于你的业务需求。

编辑:想到另一个不利的地方 – 如果你在表上有独特的索引,被删除的logging将仍然占用“一个”logging,所以你必须围绕这种可能性也编码(例如,一个用户表具有唯一的索引用户名;被删除的logging仍然会阻止已删除的用户名为新logging。解决这个问题,你可以通过一个GUID到被删除的用户名列,但是这是一个非常冒险的解决办法,我不会推荐。可能在这种情况下只要有一个用户名被使用的规则,就不会被取代。

逻辑删除是否通用? 是的,我在很多地方见过这个。 他们安全吗? 那真的取决于他们在数据被删除之前的安全性呢?

当我担任技术主pipe时,我要求我们的团队保存每一个数据,当时我知道我们将使用所有这些数据来构build各种BI应用程序,尽pipe当时我们不知道需求会是什么是。 从审计,故障排除和报告(这是B2B交易的电子商务/工具站点)这一点来看,这是很好的,如果有人使用了工具,即使他们的帐户后来被closures,我们也想logging它,它确实有几个缺点。

缺点包括(不包括已经提到的其他人):

  1. 性能保持所有这些数据的意义,我们制定各种归档策略。 例如,应用程序的一个区域正在接近每周产生大约1Gb的数据。
  2. 保持数据的成本确实随着时间的推移而增长,而磁盘空间便宜,基础设施的数量在线和离线保存和pipe理TB数据量是很多的。 需要大量的磁盘冗余,人们的时间,以确保备份正在迅速移动等。

当决定使用逻辑,物理删除或存档时,我会问自己这些问题:

  1. 这个数据是否需要重新插入到表中。 例如用户帐户适合这个类别,因为你可能激活或停用用户帐户。 如果是这种情况,逻辑删除就是最有意义的。
  2. 存储数据有没有内在价值? 如果有的话,会产生多less数据。 根据这一点,我要么去逻辑删除,要么实施一个归档策略。 请记住,您始终可以存档逻辑删除的logging。

我是一名NoSQL开发人员,在上一份工作中,我使用的是对某个人来说至关重要的数据,如果在创build的同一天被意外删除,我无法在上次备份中find它从昨天! 在这种情况下,软删除总是保存一天。

我做了使用时间戳的软删除,注册文档被删除的date:

 IsDeleted = 20150310 //yyyyMMdd 

每个星期天,一个进程在数据库上走,并检查IsDeleted字段。 如果当前date和时间戳之间的差异大于N天,则文档被硬删除。 考虑到文件仍然可以在一些备份,这是安全的做到这一点。

编辑:这个NoSQL用例是关于在数据库中创build的大文档,每天数十或数百个,但不是数千或数百万。 一般来说,它们是具有工作stream程过程的状态,数据和附件的文件。 这就是为什么有用户删除重要文件的可能性。 此用户可以是具有pipe理员权限的人员,也可以是文档所有者,仅举几例。

TL; DR我的用例不是大数据。 在这种情况下,你将需要一个不同的方法。

这可能有点晚,但我build议大家检查Pinal Dave的博客文章关于逻辑/软删除:

我只是不喜欢这种devise[软删除]。 我坚信只有必要的数据应该放在单个表中而无用的数据应该被移动到存档表的架构。 我不build议使用isDeleted列,而是build议使用两个不同的表格:一个是订单,另一个是删除订单。 在这种情况下,你将不得不同时维护这个表格,但是实际上这很容易维护。 当您将UPDATE语句写入isDeleted列时,将INSERT INTO写入另一个表并从原始表中删除它。 如果情况是回滚,请按相反顺序写入另一个INSERT INTO和DELETE。 如果您担心交易失败,请将此代码包含在TRANSACTION中。

在上述情况下,较小的表格和较大的表格有什么优点?

  • 一张小桌子很容易维护
  • 索引重build操作要快得多
  • 将归档数据移动到另一个文件组将减less主文件组的负载(考虑到所有文件组都在不同的系统上) – 这也将加速备份。
  • 由于规模较小,统计资料将经常更新,这将减less资源密集型。
  • 指数的大小将会变小
  • 表格的性能会随着表格尺寸的缩小而改善。

回复:“这安全吗?” – 这取决于你的意思。

如果你的意思是通过物理删除,你将防止任何人发现删除的数据 ,那么是的,这或多或less是真的; 您在物理上删除需要擦除的敏感数据会更安全,因为这意味着它永久地从数据库中删除。 (但是,要意识到可能存在其他数据副本,如备份,事务日志或传输中的logging版本,例如数据包嗅探器 – 仅仅因为您从数据库中删除了数据保证它没有保存在其他地方。)

如果你的意思是通过逻辑删除,你的数据更安全,因为你永远不会丢失任何数据 ,这也是事实。 这对于审计场景很好。 我倾向于这样devise,因为它承认了一个基本的事实,即一旦生成数据,就永远不会真的消失(特别是如果它有能力被networkingsearch引擎caching)。 当然,一个真实的审计场景要求不仅要删除逻辑,还要logging更新,以及更改的时间和进行更改的angular色。

如果您的意思是数据不会落入任何不应该看到的人的手中,那么这完全取决于您的应用程序和安全结构。 在这方面,逻辑删除不会比数据库中的其他任何东西更安全。

我使用的一种模式是创build一个镜像表,并在主表上附加一个触发器,所以所有的删除操作(如果需要的话)都会被logging在镜像表中。

这允许您“重build”已删除/已更改的logging,并且仍然可以在主表中进行硬删除并保持“清除”状态 – 还允许创build“撤消”function,还可以loggingdate,时间以及在镜像表中执行操作的用户(在寻找巫婆的情况下非常有用)。

另外一个好处是,除非你故意在镜像表中包含logging(你可能希望显示活的和被删除的logging),否则在查询主数据时不会意外地包括被删除的logging。

另一个优点是镜像表可以独立清除,因为它不应该有任何实际的外键引用,与从使用软删除的主表进行清除相比,这是一个相对简单的操作,但仍然具有与其他表的引用连接。

还有什么其他优点 – 如果你有一大堆编程人员在项目上工作,用混合的技巧和对细节层次的关注读取数据库,你不必熬夜,希望其中一个不忘记包括删除logging(大声笑,不包括删除logging=真),这导致像夸大其词的东西说客户可用的现金头寸,然后他们去购买一些股份(即在交易系统中),当你使用交易系统,你将很快发现稳健解决scheme的价值,即使它们可能有一点点的初始“开销”。

例外情况: – 作为指导,对用户,类别等“引用”数据使用软删除,对事实types数据,即事务历史logging,硬删除到镜像表。

我通常使用逻辑删除 – 当您也间歇性地将“已删除”数据归档到归档表(可以根据需要search)时,我发现它们运行良好,因此不会影响应用程序的性能。

它运作良好,因为如果您曾经接受过审核,您仍然有数据。 如果你删除它, 它已经消失了

我是逻辑删除的忠实粉丝,尤其是对于业务线应用程序,或者在用户帐户的情况下。 我的理由很简单:通常我不希望用户能够使用该系统(所以账户被标记为已删除),但是如果我们删除了用户,我们会失去所有的工作。

另一个常见的情况是用户在删除后可能会重新创build一段时间。 将用户的所有数据与删除之前的数据一样存在,而不必重新创build数据,对用户来说是一个更好的体验。

我通常认为删除用户更多的是“无限期地”暂停。 你永远不知道什么时候他们会合法的需要回来。

逻辑删除如果在参照完整性上很难。

在表格数据存在时态方面时,这是正确的想法(有效的FROM_DATE – TO_DATE)。

否则将数据移动到审计表并删除logging。

从积极的一面:

这是更简单的方法(如果可能的话)。

很容易看出特定时间点的状态。

这是相当标准的情况下,你想保持一些东西的历史(例如用户帐户@Jon Dewees提到)。 如果用户请求删除的机会很大,这当然是一个好主意。

如果您担心从查询中删除已删除logging的逻辑变得杂乱,并且使查询复杂化,则可以构build视图,为您进行筛选并针对该查询使用查询。 这将防止在报告解决scheme等这些logging泄漏。

我强烈不同意逻辑删除,因为您遇到很多错误。

首先查询,每个查询必须照顾IsDeleted字段和复杂的查询错误的可能性变得更高。

其次,性能:想象一个只有3个活动的100000个recs的表,现在将这个数字乘以数据库的表; 另一个性能问题是与旧logging(已删除logging)的新logging可能发生冲突。

我所看到的唯一的优点是logging的历史,但也有其他方法来实现这个结果,例如你可以创build一个日志表,你可以保存信息: TableName,OldValues,NewValues,Date,User,[..] where *Values可以是varchar并以这种forms写入详细信息fieldname : value ; […]或将信息存储为xml

所有这一切都可以通过代码或触发器来实现,但是你只有一张表,所有的历史。 另一种select是查看指定的数据库引擎是否支持本地跟踪更改,例如在SQL Server数据库上有SQL跟踪数据更改。

有超出系统devise的需求需要回答。 logging保留的法律或法定要求是什么? 根据行的相关性,可能有一个法律要求,数据在“暂停”之后保持一段时间。

另一方面,要求可能是一旦logging被“删除”,就被真正不可撤销地删除。 在做出决定之前,请与您的利益相关者沟通。

他们不让数据库执行,因为它应该渲染级联function无用的事情。

对于插入等简单的事情,在重新插入的情况下,它后面的代码加倍。

你不能简单地插入,而是你必须检查一个存在,如果它不存在之前插入它,或更新删除标志,如果它同时也更新所有其他列到新值。 这被看作是对数据库事务日志的更新,而不是导致审核日志不准确的新插入。

它们会导致性能问题,因为表格会被冗余数据覆盖。 它与索引,特别是与唯一性的喧闹。

我不是逻辑删除的忠实粉丝。

依靠同步的移动应用程序可能会强制使用逻辑删除而不是物理删除:服务器必须能够向客户端指示logging已被(标记为)已被删除,并且如果logging被物理删除,则这可能是不可能的。

我曾经做过软删除,只是为了保留旧的logging。 我意识到用户不会像我想的那样频繁地查看旧的logging。 如果用户想查看旧的logging,他们可以从档案或审计表查看,对不对? 那么,软删除的优点是什么呢? 这只会导致更复杂的查询语句等

以下是我实施之前,我决定不再软删除:

  1. 实施审计,logging所有活动(添加,编辑,删除)。 确保没有任何外键链接到审计,并确保这个表是安全的,没有人可以删除除pipe理员。

  2. 确定哪些表被认为是“交易表”,这很可能会被长期保存,并且很可能用户可能想要查看过去的logging或报告。 例如; 购买交易。 这个表格不应该只保留主表的id(比如dept-id),而且还要保留其他的信息,比如名字作为参考(比如dept-name)或者其他必要的报告字段。

  3. 实现主表的“主动/非主动”或“启用/禁用”或“隐藏/显示”logging。 因此,用户可以不删除logging,而是禁用/禁用主logging。 这样更安全。

只是我的两分钱的意见。

软删除(Soft Delete)是一种编程实践,当数据更相关时,大多数应用程序都遵循这种编程实践。 考虑一个最终用户的错误删除可能是致命的财务应用案例。 软删除变得相关时就是这种情况。 在软删除中,用户实际上并不是从logging中删除数据,而是将其标记为IsDeleted为true(按照常规惯例)。

在EF 6.x或EF 7中,Softdelete被添加为属性,但是我们现在必须创build一个自定义属性。

我强烈推荐SoftDelete在数据库devise和编程实践中的良好惯例。

好! 大家都说,这取决于情况。

如果您在像UserName或EmailID这样的列上有一个索引,并且您永远不会再指望使用相同的UserName或EmailID; 你可以去软删除。

也就是说,总是检查你的SELECT操作是否使用主键。 如果你的SELECT语句使用一个主键,用WHERE子句添加一个标志不会有太大的区别。 我们举一个例子(伪):

表用户(UserID [主键],EmailID,IsDeleted)

SELECT * FROM UserID = 123456和IsDeleted = 0的用户

由于UserID列有一个主键,所以此查询在性能方面没有任何区别。 最初它会根据PK扫描表格,然后执行下一个条件。

软删除的情况根本无法工作:

主要在所有网站注册EmailID作为您的唯一标识。 我们很清楚,一旦在Facebook,G +等网站上使用了EmailID,就不能被其他人使用。

有一天,当用户想要从网站上删除他/她的个人资料。 现在,如果您进行逻辑删除,则该用户将不能再次注册。 而且,使用相同的EmailID重新注册并不意味着要恢复整个历史logging。 大家都知道,删除意味着删除。 在这种情况下,我们必须做一个物理删除。 但为了保持帐户的整个历史,我们应该始终将这些logging归档到归档表或删除的表中。

是的,在我们有很多外国表的情况下,处理是相当麻烦的。

另外请记住,软/逻辑删除将增加您的表大小,所以索引大小。

回答Tohid的评论,我们遇到了同样的问题,我们想要坚持logging的历史,也不知道我们是否想要is_deleted列。

我正在谈论我们的python实现和我们碰到的一个类似的用例。

我们遇到了https://github.com/kvesteri/sqlalchemy-continuum这是一个简单的方法来获取对应表的版本控制表。; 代码的最小行数和捕获添加,删除和更新的历史logging。

这不仅仅是is_deleted列。 你总是可以反向版本表来检查这个条目发生了什么。 是否进入删除,更新或添加。

这样我们根本就不需要有is_deleted列,而我们的删除函数是非常简单的。 这样我们也不需要记住在我们的任何一个api中标记is_deleted=False

大多数情况下使用softdeleting是因为你不想公开一些数据,但是由于历史的原因你不得不保留它(产品可能会停止使用,所以你不需要任何新的事务,但是你仍然需要销售交易的历史)。 顺便说一下,有些人正在复制销售交易数据中的产品信息价值,而不是参考产品来处理这个问题。

实际上,它看起来更像是一个可见/隐藏或主动/非主动特征的重新说明。 因为这是商业世界中“删除”的意思。 我想说,终结者可能会删除人,但老板只是开除他们。

这种做法是相当普遍的模式,由于很多原因而被大量的应用程序所使用。 因为这不是唯一的办法,所以你会有一千个人说这是好的或废话,都有很好的论据。

从安全angular度来看,SoftDelete不会取代审计工作,也不会取代备份工作。 如果您担心“在两个备份案例之间插入/删除”,则应该阅读“完整或批量恢复模型”。 我承认,SoftDelete可以使恢复过程更微不足道。

由你来知道你的要求。