聊一聊 MYSQL 数据的真删和假删

前言

简单做个小白文描述。

 真删 :

 指的就是 彻底地删除, 从数据库表内将数据 进行 移除  delete

假删:

指的就是 逻辑上的删除 , 数据库表内, 数据会包含一个标识flag字段 , 例如: status(删除标识,0代表未删除,1代表删除,默认为0) ,执行假删时,只是将数据的 删除标识 status从 0 改 1,update

正文

真删, 我们就不展开了。

该篇文章其实主要是想聊聊 这个 假删 - 逻辑删除 。

1. 假删的 查询条件问题

既然是对某张表做了假删, 使用  status , 那么在一些业务 查询里面 , 切记切记一定不能忘了,只要使用到 ‘ 假删 ’的数据表, 那么需要带上  status=0 .

2.假删 的验重,数据唯一 问题

验重, 字面意思就是说数据唯一, 而这个数据的唯一保证 ,我们常规地首先是在代码层面做唯一校验,然后在数据库层面也做唯一设置。

为什么说 存在问题?

按照咱们的风格,举个例子来看看:

首先我们现在有一张用于保存企业enterprise信息的表 , 业务上简单理解,需要保证企业唯一,也就是企业名 name唯一(简单举个例子,具体看项目业务需求) 。

enterprise表

idnameaddressstatus    (删除标识,0未删除 ,1 已删除)
1小目标JCccc公司象牙塔0
2test公司梦想国度

保证name的唯一,那么在 企业数据新增时, 按照常规来说我们需要做验重处理。

select  id  from enterprise where name= ' xxxx' ;

看到这里, 可能已经有小伙伴有不一样的看法了, 这个查询的sql是否要带上删除标识?

select  id  from enterprise where name= ' xxxx'  and status = 0 ;

这里也就是指的是, 被执行了假删的数据,是否还需要加入 验重的校验逻辑里?

其实,不同的业务场景,规则肯定不同。 例如上面例子里面介绍的企业信息表, 那么如果企业信息进行假删后, 后面再一次进行企业信息录入时, 企业的名字肯定还是不会变化的。

那么这时候,如果对所谓的 假删数据 stauts=1 还挂钩上,那么就有些不符合常理了,

也就是说,这里的假删不能影响业务,在业务上其实就是已经真正删除掉了。

所以我们需要带上 status= 0 ,保证现在 表内 有效的 企业信息数据中, 不能包含重复数据!

select  id  from enterprise where name= ' xxxx'  and status = 0 ;

ok,这么一看,假删的验重问题似乎已经考虑齐全了,就这么操作。

但是,目前来说也仅仅是代码层面,调用sql时做的处理。  那往往很多时候, 在数据库表创建的时候也需要对数据唯一字段进行唯一索引的创建

于是乎我们其实还需要考虑一下以下这个引申出来的问题:

假删 数据表 的 唯一索引的创建 问题

回到刚刚例子中的  enterprise表 :

idnameaddressstatus  (删除标识,0未删除 ,1 已删除)
1小目标JCccc公司象牙塔0
2test公司梦想国度1

上边说了下,我们需要保证企业信息唯一,保证企业名 name 的唯一。

那么,按照常规,name字段的 唯一索引(name_index )不可或缺 ,需要创建

但是,此时这张表其实在验重的时候,进行的逻辑判断 是需要 带上条件 status的。

那么问题就出现了, 对于数据表的真正唯一来说,

其实是 name + status  这两个字段同时保证唯一时, 数据才算是唯一。

也就是说 唯一索引需要升级为唯一组合索引  name字段 & status字段  (name_status_index) .

到这里, 好像是这么一个意思。 

这样的唯一组合索引, 跟代码层面的校验规则似乎保持了一致的验重逻辑处理。

保证了吗? 能这样创建吗?

然而并不然! 

是的, 这个问题的介绍描述 转折确实有点多了。 不过我就是想这么地表达出 一个 针对一个问题的处理、设计解决方案, 需要一步步每个环节都进行把控。

回到正文,为什么说这样 还不行??  唯一组合索引 还不行?

直接看 enterprise表 的模拟数据 :

idnameaddressstatus  (删除标识,0未删除 ,1 已删除)
1小目标JCccc公司象牙塔0
2test公司梦想国度1

可以看到 test公司 这条数据的status是 1 , 那么也就是进行了 所谓的假删 ,逻辑删除。

那么再次创建时, 我们允许创建, 因为在有效数据内 (status=0) ,数据唯一即可,所以表内数据出现:
 

idnameaddressstatus  (删除标识,0未删除 ,1 已删除)
1小目标JCccc公司象牙塔0
2test公司梦想国度1
3test公司梦想国度0

这么一看,id为3 的数据 在表内 存在合情合理, 跟id为2 的 被假删数据 ,隔离得很好,没有什么问题。

 但是, 再想想,这时候,管理员又把id为 3的数据 进行了 假删。

会出现什么情况?

没错如果我们做了 唯一组合索引 ,那么 再次进行逻辑删除时, 问题出现,  唯一组合索引 不允许 再次 存入   name 为 test公司、status 为 1 的数据,因为之前存在过了

那这时候,死局了。   

破局思考&方案:

想法一:         

   不设置索引了。 仅仅在代码层面做 stauts=0 的有效数据 验重算了。

带来的不好影响: 

   数据库层面不做唯一拦截,那就会允许存在有误数据。

想法二:   

  引入一个新的字段 delete_uuid , 这个字段 作为 唯一组合索引 的成员  ,name_deleteuuid_index. 

那么表结构将会变成:

idnameaddressstatus  (删除标识,0未删除 ,1 已删除)delete_uuid
1小目标JCccc公司象牙塔0z2831a82-de87-c078-94bf-3dfd909292b00
2test公司梦想国度1NULL
3test公司梦想国度0e6831a82-de87-4078-94bf-4ed909292b00

怎么使用呢, 可以看到 现在的组合唯一索引是 name & delete_uuid ,。

新增数据验重时, 查询加上条件 status =0 and delete_uuid !=NULL   保证有效数据内的唯一性。

然后是针对删除操作, 进行逻辑假删时, 把status改为1 ,并 设置 delete_uuid 为NULL。

(估计有些看官,看到这里会有疑惑, 如果数据 name为test公司 ,删除创建再删除,那么产生了两条 name一样且 delete_uuid 也都是NULL 的数据,数据库允许么? 这就需要给有疑惑的看官科普一下NULL 这个东西的知识了,可以看下下面这篇:

Mysql 唯一索引的字段值 允许多个NULL值存在吗 ?   Mysql 唯一索引的字段值 允许多个NULL值存在吗_默默不代表沉默-CSDN博客

回归话题内容,

这么一来,即使出现id 为3 和id为2 这种数据场景,需要进行删除时,也不会因为组合索引的唯一性无法进行删除。

带来的不好影响: 


复杂度提高了;

多了一个字段,那么一些查询、删除时,就需要考虑到这个字段的使用;

想法三:

逻辑删除的实现上做改变。  本来常规的是 把status从 0 改为 1 ;

那么改为 从 原表 把执行逻辑删除的数据, 迁移插入到历史表 ,

这样原表可以一直保证 name 字段 唯一索引的校验即可。  

带来的不好影响: 

既然出现了历史表用于单独存储 假删除的数据, 那么意味着 存储 同个业务数据表其实 一共有两张表 。

我们再回到逻辑删除这个东西的出现, 既然要进行逻辑删除,那么意思就是说,这个数据在一定的情况下,是不允许直接删除,会存在 '恢复' 的情况。

就好比如微信的聊天记录, 删除了,但是微信还是提供了一定条件下做聊天记录的恢复。 

那么也就是说,如果有这种恢复的场景 就需要 考虑到两张表的使用操作了。

额外,如果就比如本文中 企业表, 假如 进行逻辑删除的数据需要加入一些数据统计分析业务, 那么 两张表的数据都需要使用到,随之很多业务的实现也会因此而变得不那么直接。

好吧,啰里啰唆地也说了这么多,那就先聊到这了。 大家有什么想法,可以直接评论,都聊一聊假删 这个话题。

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小目标青年

对你有帮助的话,谢谢你的打赏。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值