数据库,逻辑删还是物理删?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 数据库,逻辑删还是物理删?

相信很多人都听过删库跑路这个词,用搜索引擎检索删库跑路,可以看到很多程序员删库跑路的讨论和新闻。

image.png

但是,严格来讲,大部分程序员想删库跑路也做不到。为什么呢?因为没有数据库的删除权限。——真正能删库跑路的是运维,再准确点DBA。

image.png

那么平时业务中的删除是怎么做的呢?答案是逻辑删除

逻辑删除:又名软删除,与物理删除、硬删除相对应,含义是并没有实际的删除数据,只是将数据标记已删除(例如增加is_deleted字段)。

为什么要用逻辑删除?

物理删除很好理解,就是真的把数据给删了。

以MySQL为例,假如数据删了,应该怎么恢复呢?主要方式有两种。

利用 binlog 日志

binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。

使用binlog恢复数据,本质上就是通过binlog找到所有DML操作,去掉错误的SQL语句,然后执行其它的SQL语句,就可以将数据恢复。

binlog恢复数据示意图如下:

image.png

可以看到,恢复时候不仅需要停掉数据库,假如数据量大的话,去筛选恢复数据sql就😂

数据库延时同步节点

  • 给数据库配置一个同步数据的数据库
  • 同步时间,要延时:比如 1 小时同步一次
  • 当出现问题的时候,只要在这个延时时间内,都还可以恢复出一定的数据

所以,综上,可以认识到,数据删除之后的恢复是要付出很大代价的,而且还存在不可恢复的风险。所以出于安全考虑,生产环境数据库应当尽可能禁止物理删除

逻辑删除会带来什么问题?

数据冗余

这个不用说,数据没有实际删除,自然会产生大量的对业务无用的冗余数据。

增加开发复杂度

写sql进行数据处理时需要排除那些已经逻辑删除的数据,这就会导致sql复杂,容易出错,特别是涉及多表查询时。

例如:

  select t1.name,t2.category from product t1
     left join category t2 on t1.category_id=t2.id
   where
    t1.is_deleted=1
    and t2.is_deleted=1

影响惟一性约束

如果数据表的某个字段要求唯一,并强制约束,比如用户表中的登录用户名字段,设计为逻辑删除的话,一旦有新的同用户名记录就无法插入。但如果不将该字段设置为唯一性约束的,那么在每次插入数据的时候,都需先进行一次查询,看看有无未(逻辑)删除的同名记录存在。

image.png

如何设计逻辑删除?

首先需要在表里设计一个删除的标志字段is_deleted

插入数据数据时,这个值默认为0。删除数据时将这个值设置为1。查询和更新数据时都将‘deleted=0’这个条件带上,只查询和更新没有删除的数据。

是不是很简单?但别忘了我们上面提到的影响惟一性约束的问题。这个该怎么解决呢?

可以将唯一约束字段和删除相关的字段创建成组合唯一索引:

  • 将删除标记设置默认值(例如0),将唯一字段与删除标记添加唯一键约束。当某一记录需要删除时,将删除标记置为NULL。
    由于NULL不会和其他字段有组合唯一键的效果,所以当记录被删除时(删除标记被置为NULL时),解除了唯一键的约束。此外该方法能很好地解决批量删除的问题(只要置为NULL就完事了),消耗的空间也并不多(1位 + 联合索引)。
  • NULL在某些情况下是存在一些问题的,删除时可以将删除标记更新为主键,这样同样保证了唯一约束字段和删除标记组合索引的唯一性。
  • 还可以用另外一种方案,添加一个删除时间delete_time的字段,设置一个不为NULLl的默认值,和惟一字段组成联合唯一索引,当进行逻辑删除的时候同时要更新delete_time,这样同样可以保证惟一性。

如果是Java语言开发,推荐MyBatis Plus框架,提供了比较好的逻辑删除支持。

应该用逻辑删除吗?

到现在我们认识到,逻辑删除有利好之处,但是也要付出一定的代价。那么应该用逻辑删除吗?

  • 从项目的规模来讲
  • 一般的建议是小型系统可以采用物理删除,因为数据恢复的成本,或者说数据的价值,相比较使用逻辑删除的开发、运维付出要少。但是物理删除!=随意删除,要认识到删除操作的风险,重要数据应该设计历史表,删除之前将删除的数据复制到历史表。
  • 中大型项目应该采用逻辑删除,有一句话“数据是无价的”。必须承认,在很多时候,数据的价值是远远高于人工的成本的。
  • 从数据价值来讲
  • 价值比较高的数据,如电商系统的订单之类的,毫无疑问,一般都是只允许逻辑删除的,及时必须要做物理删除,也要通过备份表、备份日志等方式保证数据可以快速恢复。
  • 价值比较低的数据,比如用户操作日志之类,这种数据价值不高,而且数据量很大,在资源有限的情况下,可以考虑物理删除,但是这种危险操作尽量也不要由系统功能去做,而应该由专业的DBA去完成——至于怎么降低DBA操作的风险,大概就得靠制度了。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
数据库
达梦数据库的物理备份和还原简解
达梦数据库的物理备份和还原简解
347 1
达梦数据库的物理备份和还原简解
|
7月前
|
存储 SQL 数据库
关系型数据库物理备份
【5月更文挑战第1天】物理备份是一种快速、直接的数据库备份方式,适用于需要快速恢复的场景。但是,在选择备份方法时,应该根据具体的需求和场景来权衡物理备份和逻辑备份的优缺点。
108 4
关系型数据库物理备份
|
4月前
|
存储 SQL 安全
【数据库高手的秘密武器:深度解析SQL视图与存储过程的魅力——封装复杂逻辑,实现代码高复用性的终极指南】
【8月更文挑战第31天】本文通过具体代码示例介绍 SQL 视图与存储过程的创建及应用优势。视图作为虚拟表,可简化复杂查询并提升代码可维护性;存储过程则预编译 SQL 语句,支持复杂逻辑与事务处理,增强代码复用性和安全性。通过创建视图 `high_earners` 和存储过程 `get_employee_details` 及 `update_salary` 的实例,展示了二者在实际项目中的强大功能。
47 1
|
4月前
|
存储 SQL JSON
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
|
4月前
|
存储 前端开发 中间件
CTO要求把所有逻辑放到数据库:合理性的深度剖析
【8月更文挑战第12天】在软件开发领域,关于系统架构的决策往往能深刻影响项目的成败。当CTO提出将所有逻辑放到数据库中的要求时,这一决策无疑会引发团队内部的广泛讨论。本文将从技术合理性、维护性、性能及可扩展性等多个维度,深入探讨这一要求的合理性与潜在影响,旨在为读者提供全面而深入的技术见解。
63 1
|
4月前
|
JSON 数据格式 Java
化繁为简的魔法:Struts 2 与 JSON 联手打造超流畅数据交换体验,让应用飞起来!
【8月更文挑战第31天】在现代 Web 开发中,JSON 成为数据交换的主流格式,以其轻量、易读和易解析的特点受到青睐。Struts 2 内置对 JSON 的支持,结合 Jackson 库可便捷实现数据传输。本文通过具体示例展示了如何在 Struts 2 中进行 JSON 数据的序列化与反序列化,并结合 AJAX 技术提升 Web 应用的响应速度和用户体验。
140 0
|
5月前
|
SQL 存储 安全
数据库数据恢复—SQL Server数据库出现逻辑错误的数据恢复案例
SQL Server数据库数据恢复环境: 某品牌服务器存储中有两组raid5磁盘阵列。操作系统层面跑着SQL Server数据库,SQL Server数据库存放在D盘分区中。 SQL Server数据库故障: 存放SQL Server数据库的D盘分区容量不足,管理员在E盘中生成了一个.ndf的文件并且将数据库路径指向E盘继续使用。数据库继续运行一段时间后出现故障并报错,连接失效,SqlServer数据库无法附加查询。管理员多次尝试恢复数据库数据但是没有成功。
|
7月前
|
数据库
如何解决逻辑删除is_del与数据库唯一约束冲突
如何解决逻辑删除is_del与数据库唯一约束冲突
156 0
|
6月前
|
存储 关系型数据库 MySQL
MySQL数据库——InnoDB引擎-逻辑存储结构(表空间、段、区、页、行)
MySQL数据库——InnoDB引擎-逻辑存储结构(表空间、段、区、页、行)
142 7
|
7月前
|
API 数据库 Python
Python web框架fastapi数据库操作ORM(二)增删改查逻辑实现方法
Python web框架fastapi数据库操作ORM(二)增删改查逻辑实现方法
370 1