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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 聊一聊 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 字段 唯一索引的校验即可。  


带来的不好影响:


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


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


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


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


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


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

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
关系型数据库 MySQL 数据库
MySQL 复制A的表结构和数据到表B
在MySQL中复制表A至表B可通过不同方法实现。一种是先用`CREATE TABLE B LIKE A;`复制结构,再用`INSERT INTO B SELECT * FROM A;`填充数据。另一种更简便的方法是直接使用`CREATE TABLE B AS SELECT * FROM A;`一次性完成结构和数据的复制。还有一种高级方法是通过`SHOW CREATE TABLE A;`获取表A的创建语句,手动调整后创建表B,如有需要再用`INSERT INTO ... SELECT`复制数据。注意权限问题、跨数据库复制时需指定数据库名,以及大表复制时可能影响性能。
|
5天前
|
消息中间件 数据采集 关系型数据库
大数据-业务数据采集-FlinkCDC 读取 MySQL 数据存入 Kafka
大数据-业务数据采集-FlinkCDC 读取 MySQL 数据存入 Kafka
19 1
|
5天前
|
数据采集 关系型数据库 MySQL
大数据-业务数据采集-FlinkCDC The MySQL server is not configured to use a ROW binlog_format
大数据-业务数据采集-FlinkCDC The MySQL server is not configured to use a ROW binlog_format
15 1
|
8天前
|
固态存储 关系型数据库 MySQL
"惊!20亿数据秒速入MySQL,揭秘数据库极速插入的黑科技,你不可不知的绝密技巧!"
【8月更文挑战第11天】面对20亿级数据量,高效插入MySQL成为挑战。本文探讨优化策略:合理设计数据库减少不必要的字段和索引;使用批量插入减少网络往返;优化硬件如SSD和内存及调整MySQL配置;并行处理加速插入;附Python示例代码实现分批导入。这些方法将有效提升大规模数据处理能力。
21 2
|
11天前
|
SQL 关系型数据库 MySQL
“震撼揭秘!Flink CDC如何轻松实现SQL Server到MySQL的实时数据同步?一招在手,数据无忧!”
【8月更文挑战第7天】随着大数据技术的发展,实时数据同步变得至关重要。Apache Flink作为高性能流处理框架,在实时数据处理领域扮演着核心角色。Flink CDC(Change Data Capture)组件的加入,使得数据同步更为高效。本文介绍如何使用Flink CDC实现从SQL Server到MySQL的实时数据同步,并提供示例代码。首先确保SQL Server启用了CDC功能,接着在Flink环境中引入相关连接器。通过定义源表与目标表,并执行简单的`INSERT INTO SELECT`语句,即可完成数据同步。
34 1
|
18天前
|
存储 SQL 关系型数据库
(二十三)MySQL分表篇:该如何将月增上亿条数据的单表处理方案优雅落地?
前面《分库分表的正确姿势》、《分库分表的后患问题》两篇中,对数据库的分库分表技术进行了全面阐述,但前两篇大多属于方法论,并不存在具体的实战实操,而只有理论没有实践的技术永远都属纸上谈兵,所以接下来会再开几个单章对分库分表各类方案进行落地。
|
22天前
|
关系型数据库 MySQL 数据库
使用Python读取xlsx表格数据并导入到MySQL数据库中时遇到的问题24
【7月更文挑战第24天】使用Python读取xlsx表格数据并导入到MySQL数据库中
46 7
|
20天前
|
SQL 关系型数据库 MySQL
MySQL删除表数据、清空表命令(truncate、drop、delete 区别)
MySQL删除表数据、清空表命令(truncate、drop、delete区别) 使用原则总结如下: 当你不需要该表时(删除数据和结构),用drop; 当你仍要保留该表、仅删除所有数据表内容时,用truncate; 当你要删除部分记录、且希望能回滚的话,用delete;
|
6天前
|
关系型数据库 MySQL
MySQL——删除重复数据
MySQL——删除重复数据
12 0
|
1月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之从mysql读数据写到hive报错,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。