点击↑上方↑蓝色“编了个程”关注我~

这是Yasin的第 53 篇原创文章

Y说

最近几周工作上都有点忙,有点精力不够消耗的感觉。

周末倒是没有太多事情,但只想睡觉。

杭州这两天天气都挺好的,阳光不错,每天都会在饭后去隔壁小区的花园里走一走,晒晒太阳。

感觉日子很平静,又过得很快,尤其是周末,感觉什么都没做,但很快就又到周一了。

于是在周日晚上抓住这个周末的尾巴,写一篇文章出来。这个问题是我前段时间在工作中用到的,相信很多开发者也会遇到这个问题,所以分享出来。

什么是软删除

计算机的世界要比真实世界严谨得多。

我们一般不会把数据真正删除,哪怕是在用户来看,这条数据已经是删除了的。比如你发了一条动态,觉得不合适,在自己的APP上把它删除掉,自己和别人都看不到了。

但在数据库中,这条数据一旦创建后就会一直存在,在用户点“删除”按钮的时候,只是给它设置了一个标识,代表它“已删除”,后续通过应用的正常查询,是会过滤掉这条数据的。

但在我们开发人员排查问题或者做数据分析的时候,这条数据是可见的。

要实现软删除成本不大,也不会浪费很多磁盘空间,但带来的好处是可见的,一方面是方便排查问题,可以知道这条数据情况;另一方面是程序出现了问题,导致数据出现错误时,还有补救的机会。

如何实现软删除

实现软删除有几种方案。

最常见的就是设置一个字段,用来标识这条数据是否被删除。常见的数据类型有布尔类型(在MySQL中一般用tinyint来实现);字符串类型(一般是y/n或者yes/no)。我之前在阿里所在的团队就是使用的字符串y/n的设计。

gorm是一个golang的orm框架,它的设计是一个类型为时间的字段,叫deleted_at。如果为空,代表未删除,如果不为空,代表已删除,其值就是删除的时间。

一般场景下,这两种设计都没有任何问题。但如果遇到了唯一索引,那这两种设计都会出现问题。

软删除遇到唯一索引

唯一索引指的是在数据库层面来约束数据的唯一性。比如:每个人的身份证号是独一无二的,不可重复的。那就可以通过给身份证号添加唯一索引来约束。

但如果我们的表用上述两种方式实现了软删除的功能,那使用唯一索引就会出现问题。

首先,「对于使用了软删除的表,唯一索引上必须要加上软删除的字段」,否则已经被删除的数据可能会和新插入的正常数据引起冲突。比如:如果一个博客系统,标题+作者是唯一的。一个用户发了一篇文章,但对内容不满意,删除了。后来又重新发了一篇标题一样的文章,这个时候如果唯一索引没加软删除字段的话,就会报唯一索引冲突。

如果我们使用布尔值或字符串来实现软删除功能,那被删除两次的相同数据会引起唯一键冲突。比如同样是这个博客系统,我删除了一篇文章,又写了一篇标题一样的文章,结果这篇文章也想删除的时候,就会报唯一索引冲突,删除失败。

如果使用gorm的时间戳设计,由于它的deleted_at字段允许为空,唯一索引加上这个字段后,唯一索引会失效。这个时候同一个用户是可以创建两篇标题一模一样的文章的,违背了产品的设计。

其它设计

那如何解决这个问题呢?

其实顺着这个思路去想,是很好解决这个问题的。

首先,软删除字段不能为空,否则唯一索引就失效了。

其次,已删除的数据要想办法不被唯一索引检测到冲突,但未删除的数据又需要被唯一索引检测到冲突。那代表这个唯一索引不能是简单的布尔值,且需要一个“默认值”。

那就可以想到两种设计了。

第一种是像gorm那样,使用时间戳来标识已删除。不同的是,不使用IS NULL来判断未删除的数据,而使用=0来判断未删除的数据。也就是说,deleted_at是非空的,默认值是0。事实上我今天在翻gorm官方文档的时候,发现它其实也是支持这种设计的:

import "gorm.io/plugin/soft_delete"type User struct {ID        uintName      stringDeletedAt soft_delete.DeletedAt
}// Query
SELECT * FROM users WHERE deleted_at = 0;// Delete
UPDATE users SET deleted_at = /* current unix second */ WHERE ID = 1;

另一种就是使用deleted_id来作为软删除字段。默认值是0(如果主键是字符串类型,默认为空字符串),如果是已删除的数据,那更新deleted_id=id

总结

目前项目上都是深度使用的gorm。之前觉得它的软删除设计有些奇怪,但没有细想到底奇怪在哪里,就正常使用了一段时间,直到前段时间发现唯一索引是不生效的,才觉察到有问题。

之前在阿里那种y/n设计是明确有问题的,但当时也没深究怎么去解决。而且软删除这种功能很多时候都是写死在了orm框架里,有时候是没法改变的。

后续翻资料和文档,与同事讨论,发现也有其它不错的解决方案,看来以后在工作中还是要多问自己几个为什么,多思考和查阅资料,才能把软件设计得更好一点。

关于作者

我是Yasin,一个爱写博客的技术人

微信公众号:编了个程(blgcheng)

个人网站:https://yasinshaw.com

欢迎关注这个公众号

数据源切换的一般步骤

MySQL到底在RR层面解决幻读了吗?

当软删除遇到唯一索引相关推荐

  1. gorm 软删除deleted_at导致索引失效

    如果使用gorm的时间戳设计,由于它的deleted_at字段允许为空,唯一索引加上这个字段后,唯一索引会失效. 第一种是像gorm那样,使用时间戳来标识已删除.不同的是,不使用IS NULL来判断未 ...

  2. MySQL删除全局唯一索引unique

    删除索引(通用) alter table 表名 drop index 索引名: drop index 索引名 on 表名 查看索引 show keys from 表名 show index from ...

  3. 唯一索引和逻辑删除冲突

    一. 场景 在数据表结构设计的时候有同时存在唯一索引和逻辑删除,通常逻辑删除is_deleted是取值范围0.1,当删除同一个唯一索引字段值时,就会失败. 二. 解决方案 2.1 物理删除 不再设置逻 ...

  4. 主键约束、唯一性约束、唯一索引

    1.主键约束(PRIMARY KEY) 1) 主键用于唯一地标识表中的每一条记录,可以定义一列或多列为主键. 2) 是不可能(或很难)更新. 3) 主键列上没有任何两行具有相同值(即重复值),不允许空 ...

  5. ORACLE创建唯一索引

    oracle创建唯一索引 Create UNIQUE Index PK_INSTANCE_ID on TB_DD_APPROVAL_OUT (INSTANCE_ID ) oracle基于多列的唯一性约 ...

  6. mysql删除表中的唯一索引吗_Mysql 使用sql删除同表中重复数据并加唯一索引

    同一张表中,假设以两个字段做唯一业务,这两个字段分别为key1,key2, 则以这两个字段为唯一 DELETE tablename FROM tablename , ( SELECT min(id) ...

  7. 死锁:多线程同时删除唯一索引上的同一行

    1    死锁问题背景    1 1.1    一个不可思议的死锁    1 1.1.1    初步分析    3 1.2    如何阅读死锁日志    3 2    死锁原因深入剖析    4 2. ...

  8. mysql索引 删除和创建_mysql索引和唯一索引的创建和删除

    一.本机环境 二.索引的创建删除 三.唯一索引的创建和删除 一.本机环境 系统环境:linux centos 7.2 mysql版本:mysql-5.7.9 安装目录:/application/mys ...

  9. mysql中怎样查看和删除唯一索引

    mysql中怎样查看和删除唯一索引. 查看唯一索引: show index from mytable;//mytable 是表名 查询结果例如以下: 查询到唯一索引后,怎样删除唯一索引呢,使用例如以下 ...

最新文章

  1. zatree插件优化:优化左侧边栏
  2. WePY框架开发的小程序如何在微信web开发者工具中运行起来
  3. Ueditor 改造, 为每个用户单独创建上传附件目录,用户只能查看自己上传的附件文件
  4. Tomcat处理一个HTTP请求的过程
  5. java创建容器对象的类是什么_spring容器创建bean对象的方式
  6. Linux下使用Netfilter强制清除IPv4 DF标志
  7. Flask集成Markdown文本编辑器
  8. 普中科技51单片机直流电机控制风扇调速
  9. 算法 - 程序的灵魂
  10. 怎么建立局域网_用ZeroTier搭建属于自己的虚拟局域网(VLAN)
  11. vs中css样式转换_在现实世界中使用CSS转换
  12. HashMap碰撞问题解析
  13. 产品助理入门攻略(一枚入行3年的PM内心独白)
  14. 机器学习入门好文,强烈推荐(转载)
  15. Nacos入门之服务注册中心以及命名空间分组和DataID三者关系
  16. 阿里云域名注册优惠口令和续费优惠口令(更新)
  17. MySQL 修改frm文件_mysql 之 frm+ibd文件还原data
  18. Android安装教程
  19. Css Gird网格布局详细介绍
  20. 杭电ACM 2014:青年歌手大奖赛_评委会打分

热门文章

  1. 基于FPGA的永磁同步伺服控制系统的设计,在FPGA实现了伺服电机的矢量控制
  2. 发送验证码倒计时效果实现
  3. mac使用在终端登录mysql
  4. 遇到用vnc-viewer连接,键盘Caps Lock不好使和小键盘错位的问题
  5. Echoin -- 能源公链生态正式路演 - 北京,上海...
  6. nodejs微信小程序 vue网络在线考试系统
  7. 年前无情被裁,我面试大厂的这3个月....
  8. MQTT 服务端搭建以及详解
  9. tf生成一定范围的均匀分布的随机矩阵
  10. 黄淮学院CSDN高校俱乐部参加2013年中国移动开发者大会