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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 聊一聊 MYSQL 数据的真删和假删

前言



简单做个小白文描述。


真删 :


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


假删:


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


正文



真删, 我们就不展开了。


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


1. 假删的 查询条件问题


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


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


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


为什么说 存在问题?


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


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


enterprise表


image.png保证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表 :


image.png


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


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


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


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


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


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


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


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


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


然而并不然!


 image.png


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


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


直接看 enterprise表 的模拟数据 :


image.png


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


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


image.png


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


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


会出现什么情况?


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


那这时候,死局了。  


破局思考&方案:


想法一:        


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


带来的不好影响:


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


想法二:  


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


那么表结构将会变成:


image.png


怎么使用呢, 可以看到 现在的组合唯一索引是 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 字段 唯一索引的校验即可。  


带来的不好影响:


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


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


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


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


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


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

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
5月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
3月前
|
SQL 人工智能 关系型数据库
如何实现MySQL百万级数据的查询?
本文探讨了在MySQL中对百万级数据进行排序分页查询的优化策略。面对五百万条数据,传统的浅分页和深分页查询效率较低,尤其深分页因偏移量大导致性能显著下降。通过为排序字段添加索引、使用联合索引、手动回表等方法,有效提升了查询速度。最终建议根据业务需求选择合适方案:浅分页可加单列索引,深分页推荐联合索引或子查询优化,同时结合前端传递最后一条数据ID的方式实现高效翻页。
160 0
|
2月前
|
存储 关系型数据库 MySQL
在CentOS 8.x上安装Percona Xtrabackup工具备份MySQL数据步骤。
以上就是在CentOS8.x上通过Perconaxtabbackup工具对Mysql进行高效率、高可靠性、无锁定影响地实现在线快速全量及增加式数据库资料保存与恢复流程。通过以上流程可以有效地将Mysql相关资料按需求完成定期或不定期地保存与灾难恢复需求。
170 10
|
3月前
|
SQL 存储 缓存
MySQL 如何高效可靠处理持久化数据
本文详细解析了 MySQL 的 SQL 执行流程、crash-safe 机制及性能优化策略。内容涵盖连接器、分析器、优化器、执行器与存储引擎的工作原理,深入探讨 redolog 与 binlog 的两阶段提交机制,并分析日志策略、组提交、脏页刷盘等关键性能优化手段,帮助提升数据库稳定性与执行效率。
|
6月前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
285 28
|
5月前
|
存储 SQL 缓存
mysql数据引擎有哪些
MySQL 提供了多种存储引擎,每种引擎都有其独特的特点和适用场景。以下是一些常见的 MySQL 存储引擎及其特点:
142 0
|
7月前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
8月前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
1849 45
|
7月前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
本文探讨了在使用YMP 23.2.1.3迁移MySQL Server字符集为latin1的中文数据至YashanDB时出现乱码的问题。问题根源在于MySQL latin1字符集存放的是实际utf8编码的数据,而YMP尚未支持此类场景。文章提供了两种解决方法:一是通过DBeaver直接迁移表数据;二是将MySQL表数据转换为Insert语句后手动插入YashanDB。同时指出,这两种方法适合单张表迁移,多表迁移可能存在兼容性问题,建议对问题表单独处理。
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
|
7月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,

推荐镜像

更多