当前位置: 首页 > news >正文

数据库设计问题记录

唯一性约束和逻辑删除的冲突

问题描述

如果一张表中,存在唯一性约束,比如一些数据中的code,且数据表使用逻辑删除。当删除某行数据的时候,以后再次插入相同code的数据,数据库会报错。

问题分析

在逻辑删除中,数据没有被物理删除,而是用一个deleted字段标记数据已被删除,当查询数据时过滤掉已删除的数据。实际上数据仍保留在数据库中。当插入相同code的数据时,数据库的唯一性约束会限制数据的插入。

PS:如果使用的是mybatis-plus框架,可以通过配置文件开启逻辑删除功能。当查询数据时,会在where条件自动拼接deleted。

解决方案

解决方案是多样的,要基于业务和资源做权衡。由于项目要保持逻辑删除不变(数据是无价的!),解决方案是在有唯一性约束的表中,通过新增一个delete_timestamp字段,组成联合索引。delete_timestamp默认为0,在删除数据时,delete_timestamp赋值。这样,当下次插入的时候,数据库不再单独对code做唯一性校验,而是对code和delete_timestamp组成的联合索引做唯一性校验。由于删除后的delete_timestamp与新增的delete_timestamp必定不同,所以不会再有重复插入数据的报错。如果数据没被删除,新插入相同的code时,由于delete_timestamp都默认是0,所以同样会正常拦截。

PS:对于delete_timestamp字段的操作,建议封装成公共方法。

尽量不使用外键

虽然在学习的过程中,为了理想中的保持数据一致性,外键会经常被提及。但在实际业务开发过程中,非必要不使用外键约束。原因在于外键的使用可能引发一系列数据一致性的问题。比如在表中做增删改操作时,如果表字段使用了外键,要同时考虑外键所在表的数据一致性问题。这些问题会非常频繁地出现,而且解决起来会大大增加业务代码的复杂度,增加了维护成本和风险。

不使用外键,但又有相关需求,需要在一张表中存入另一张表的主键,如何实现?这种情况可直接通过业务代码控制,在插入数据时,先查询到相应的数据再插入。当然这不可避免难以保持数据一致性,但比起要保持数据一致性付出的代价,在业务层处理的成本要低得多。

总结

在数据库中建立的数据约束,都应该在业务层的时候做好相关校验,让错误在业务层被拦截并抛出,这样做有助于数据被定位和友好提示。数据库约束,是最后一道防线。

http://www.lryc.cn/news/510496.html

相关文章:

  • mac_录屏
  • 【Java-tesseract】OCR图片文本识别
  • redis cluster集群
  • 解锁高效密码:适当休息,让学习状态满格
  • 代码随想录算法训练营第十一天-150.逆波兰表达式求值
  • C++ 泛编程 —— 嵌套使用模板类
  • 【WebGIS】Cesium:GLTF数据加载
  • 【面经】25届 双非本科 字节跳动 北京 四年的总结
  • 抖去推碰一碰系统技术源码/open SDK转发技术开发
  • goview——vue3+vite——数据大屏配置系统
  • 中间件xxl-job安装
  • 【第2篇】 Python与数据库基础
  • CTFHUB-web进阶-php
  • 深度学习使用Anaconda打开Jupyter Notebook编码
  • 金蝶V10中间件的使用
  • Firewalld 防火墙详解:深入理解与实践指南
  • linux系统编程(五)
  • Effective C++ 条款 16:成对使用 `new` 和 `delete` 时要采取相同形式
  • 【HarmonyOS NEXT】鸿蒙原生应用“上述”
  • 【人工智能】使用Python构建推荐系统:从协同过滤到深度学习
  • 店铺营业状态设置
  • batchnorm和layernorm的理解
  • 在git commit之前让其自动执行一次git pull命令
  • 【Rust自学】6.3. 控制流运算符-match
  • 大模型应用技术系列(三): 深入理解大模型应用中的Cache:GPTCache
  • 『大模型笔记』评估大型语言模型的指标:ELO评分,BLEU,困惑度和交叉熵介绍以及举例解释
  • 深度解析:Maven 和 Gradle 的使用比较及常见仓库推荐
  • SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
  • 管理面板Ajenti的在Windows10下Ubuntu24.04/Ubuntu22.04里的安装
  • 在Python如何用Type创建类