数据库逻辑删除搭配唯一索引问题及解决方案

问题背景

项目中为了方便数据恢复和保护数据本身价值,经常会用到逻辑删除这种解决方案,一般都是表中加del_flag字段 0:未删除;1:已删除 用来标识这条数据的有效性,

在这里插入图片描述
但是这种方案也引出了很多问题,其中一个问题就是数据库唯一索引重复问题。
例如:用户表中有个用户编码code字段,业务上这个字段是唯一标识这个用户的,并给用户编码字段建立了唯一索引。假如这个时候删除了张三这个用户即:

在这里插入图片描述
现在想再新增一个编码为001的用户,因为这个字段建了唯一索引,在新增的时候会报唯一索引重复错误,

数据库逻辑删除搭配唯一索引问题及解决方案_第1张图片
这样就出现了问题。
你想了下可能会说可以把code和del_flag字段作为联合唯一索引,这样确实保存进去了

数据库逻辑删除搭配唯一索引问题及解决方案_第2张图片
假如现在我想把001的王五删除del_flag置为1的时候就又会报唯一索引重复

数据库逻辑删除搭配唯一索引问题及解决方案_第3张图片
显然这样不合理。

解决方案

1、编码字段唯一索引变为普通索引

这种是最简单的方式,但是code唯一标识用户的有效性数据库就失去了控制,只能从程序中判断去限制,如果只是为了满足业务需求还要提高查询速度这个是完全可以的,下面是普通索引和唯一索引的区别
数据库逻辑删除搭配唯一索引问题及解决方案_第4张图片
如果你看了普通索引和唯一索引的区别还想使用唯一索引做严格限制的话继续往下看

2、记录删除版本号

del_flag不存0或者1,存的是删除版本号,这样del_flag字段为0代表未删除,大于0的都是删除了的

数据库逻辑删除搭配唯一索引问题及解决方案_第5张图片

这样固是可以的,但是实现这个方案复杂度不小,比如你删除马六,del_flag要置为3就要查询现在的001这个编码的最大del_flag值是多少才可以,所以这个方法成本高,所以继续往下看

3、删除标识字段自定义值

走到现在来说你可能就有很多方案了,对于已删除的数据只需要把del_flag存的是唯一的值就可以了同样方式很多:
已删除的数据del_flag存id值

这样del_flag为0代表未删除反之代表已删除,因为id是主键肯定唯一,满足需求足够了,但是这个del_flag字段的值没有实际意义

已删除的数据del_flag存当前删除时间(推荐)

数据库逻辑删除搭配唯一索引问题及解决方案_第6张图片

为了不浪费del_flag这个字段值的意义,可以采取这个方法,del_flag为null是未删除,反之是已删除,这样确实没浪费很直观,但是这里最多精确到秒对于并发请求下这里还是会报唯一索引重复,所以对于删除并发不高的普通系统可以了,结合mybatis-plus的@TableLogic注解或者全局配置轻松解决

在这里插入图片描述

已删除的数据del_flag存当前删除毫秒级时间戳(推荐)

这时del_flag为0代表未删除反之为未删除,这种可以解决②中并发问题,毫秒级的维度,很少有一毫秒里的并发删除吧,出错几率极小,如果有那你就存id吧还是。这种同样也可以结合mybatis-plus轻松解决

在这里插入图片描述
这种数据里有个点

数据库逻辑删除搭配唯一索引问题及解决方案_第7张图片

好看点就 REPLACE(unix_timestamp(current_timestamp(3)),‘.’,‘’)

在这里插入图片描述

如有不足望指正。

你可能感兴趣的:(数据库,sql)