保持 Unique Key 的逻辑删除方案

·

1 min read

前言

实际开发中,重要的业务数据一般不回使用物理删除,都是使用一个状态标记 deleted 实现逻辑删除,但这种情况下会破坏唯一索引。

再往唯一约束列插入相同的值时,会报 Duplicate Entry,但在业务上该值是必须要插入的。

下面我们聊聊如何保持唯一索引

解决方案

方案一:使用物理删除

方案二: 新建历史/备份表

每次删除时,主表进行物理删除,同时将删除的记录保存到历史/备份表中

方案三: 多 deleted 值

  1. deleted0 代表未删除,其他值代表删除
iduser_idnamedeleted
11Edward0
21Edward1
31Edward2

这种方式可以保持 Unique Key,但在 deleted 冲突比较多,需要保证 deleted 累加。

  1. deleted: 0 代表未删除,删除时把 deleted 赋值为时间戳 UNIX_TIMESTAMP(NOW())。将删除状态和之前的唯一约束 A 重新组成唯一联合索引 index(A、deleted)

这种方式的好处除了可以保证唯一索引还可以知道删除的时间,但是对于历史数据涉及到修改业务。

方案四:取消表的唯一约束,同时引入 redis 来保证唯一约束

取消表的唯一性约束,项目中引入 redis ,通过 redis 来判重,新增时向 redis 中 set 记录,删除时,删除 redis 记录。

缺点:增加了系统复杂度,同时需要保证 reids 和数据库的一致性。

方案五:保留删除标记,同时新建一个字段 del_unique_key

保留删除状态位,再新增一个字段 del_unique_key默认值为0,字段的类型和大小与主键 id 保持一致,同时与原先的唯一约束重新组成联合唯一约束 index(A,del_unique_key)。进行逻辑删除时,将 del_unique_key 值改为 该删除行的主键Id

方案取舍

方案一需要从实际业务上考虑,如果物理删除队业务无损,那就无所谓了。

方案二需要额外新增一张记录表,如果只是用来实现记录删除,有点大材小用了。

方案四引入redis,可以解决问题,但增加了系统复杂度,同时需要保证 reids 和数据库的一致性。

方案三和方案五四路其实是一样的,如果是对已经上线的项目进行调整,推荐第五种方案,因为新增字段对已有业务的影响最小。如果新增业务的话,方案三和方案五比较推荐。