业务伪删除该这么设计?

main
  • 9

业务伪删除该这么设计?

现在大数据时代,数据是很重要的,所以对于一些数据系统一般不会做物理删除,删除也会有备份,所以需要设计一套伪删除的逻辑,但在下才疏学浅,对这一套逻辑了解不深,想向各位请教请教!

下面是鄙人搜索得来的两种方法,但个人觉得两种方法都不是特别好,想问下各位有什么更好的方法没?

1.一般系统采用记录加DeleteAt字段来判断数据是否删除,但这样每次查询(单表,多表联查)都需要加上DeleteAt判断,系统上复杂了一个维度。而且如果数据又有唯一索引时,就需要加上DeleteAt字段一起做唯一索引,这样随着数据量增加,索引就会消耗很多的空间。

2.还有一种做法是加一张表做删除归档表,删除的记录从表中删除然后迁移到删除归档表中,这样伪删除也完成了,但如果做数据恢复的时候就比较麻烦了,(删除归档表怎么设计暂不清楚,想请教请教)。

回复一下回答里只用一个status字段标记数据状态的不好之处

只用一个status字段标记,当有唯一键存在时有缺陷,这种唯一键的场景还比较多。
讲下场景:
系统要求一个用户只能创建一个项目,当然项目我可以删除重建。
只有一个status字段标记项目状态, 1 启用 2 删除

project表 user_id project_id status 三个字段,组成唯一键

user_id project_id status
u1 p1 2
u1 p2 1

好上面就是用户u1创建一个项目p1后,删除重新建立了项目p2,然后现在来看,如果用户把p2也删除,就会出现删除异常情况,违反了表唯一键约束,所以只用一个status字段标记的缺点就暴露出来了。

之前在本人的项目中也是采用status字段标记的方式,如果删除后又重建就会先去找已经删除的记录重新启用,但这种做法是不对的,因为之前删除的项目关联了其他记录,或者存在一些之前id标记的数据统计记录,如果启用之前的删除的项目记录,在需求上就不对了。

回复
阅读 5.8k
10 个回答

两种方法都挺好的。

删除归档表就是。比如你有一个content表,新建一个content_deleted表。每当在content表中删数据的时候就同时把该数据新增到content_deleted表里面.

我没有更好的方法,伪删除本身就是一个需求,一个需求会让程序的复杂度增加我认为是一个正常的操作

两种方式都在用

说下第一种,我用status字段表示,删除时就更新该记录的字段值值为-1。这么做还有几个好处,比如-1代表删除,0代表停用,1代表启用....还可以扩展更多用法。

业务数据一般不会用类似 “delete from” 的sql去删除数据,通过设置数据的状态字段为不可用状态即可。

当然如果一开始设计即用了删除方式,那么可能遇到一些问题,需要DB进行一些恢复操作,一般而言建议用置状态位的方式,当然会有一些数据冗余的问题(无用的数据还留在表里)。

用删除归档表,同意楼上,加事务操作即可。但是从删除归档表恢复数据,不建议使用,业务设计比较复杂,很难通过简单的逻辑表述清楚,如果需要恢复数据更建议用数据库的自带的一些手段。

我们用第一种 3个项目了

一般如果数据量不是很大的时候基本都是用一个字段来表示,比如 is_delete 表示是否回收站 0 否 1 是 1代表是删除了的数据。这样比较方便处理, 当然,如果有需要你也可以写到另外一个表

第二种方法实现起来比较容易,删除,排除不用考虑字段,可以在删除之前将数据的列以及对应数据以json的格式保存到删除归档表中,恢复起来只要根据json的表名及列名进行更新即可,这块可以封装成方法。
优化的话,删除数据量大,可以在结合第一种方法标记的方式,定时批量处理,少就用封装的方法

伪删除就是,需的时候能恢复过来,可以加个字段del 默认为0 ,添加的商品都为0,如果删除就改为1,(并不是真的删除)。当然只显示del 为0的是数据。就是伪删除

实际上我看了两种各有利弊
第一种的问题在于 所有查询 都会需要改动,空间消耗就不说了
第二种的问题在于要为该数据额外增加一部分恢复的记录,比如说 origin_table 之类的,而且怎么去对各种类型 解析再生成语句恢复 是比较麻烦的.

所以我刚才灵光一闪,有一个方式我认为很"完美" 希望大家一起来讨论一下

譬如说我们有一个 item 表
每一次进行伪删除的时候,原表直接删除,同时 我们对于这个表做一个 item_rmd 反表(自增项不要自增,这个很重要) 把被删除的数据 原封不动的 (移动) 到 item_rmd中 ,而此时 两张表的 ID(自增项) 加起来 刚好就是原表
如果我们需要进行恢复,也特别简单 可以根据对于原表的任何方式进行查询 不需要任何额外的逻辑来支持

相当于一张披萨 你随意切出来一块 还可以原封不动的插回去,同时也不会影响现有的所有业务逻辑 不需要做任何SQL改动

1.增加一个字段is_del 如果是1则为删除
2.定时删除is_del=1 的数据避免查询数据时 is_del=1的数据占用索引
3.创建被删除数据备份表,is_del=1的行包含主键整体迁移至备份表
?

一般情况第一种就行了。至于你说系统增加了复杂,这本来就是正常的业务逻辑,你可以增加一个字段叫delete_at默认null,删的时候写时间进去就行了,查的时候where delete_at is null,如果框架没自动处理,你在模型类里面封装就可以了。

你知道吗?

宣传栏