数据库设计问题记录
唯一性约束和逻辑删除的冲突
问题描述
如果一张表中,存在唯一性约束,比如一些数据中的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字段的操作,建议封装成公共方法。
尽量不使用外键
虽然在学习的过程中,为了理想中的保持数据一致性,外键会经常被提及。但在实际业务开发过程中,非必要不使用外键约束。原因在于外键的使用可能引发一系列数据一致性的问题。比如在表中做增删改操作时,如果表字段使用了外键,要同时考虑外键所在表的数据一致性问题。这些问题会非常频繁地出现,而且解决起来会大大增加业务代码的复杂度,增加了维护成本和风险。
不使用外键,但又有相关需求,需要在一张表中存入另一张表的主键,如何实现?这种情况可直接通过业务代码控制,在插入数据时,先查询到相应的数据再插入。当然这不可避免难以保持数据一致性,但比起要保持数据一致性付出的代价,在业务层处理的成本要低得多。
总结
在数据库中建立的数据约束,都应该在业务层的时候做好相关校验,让错误在业务层被拦截并抛出,这样做有助于数据被定位和友好提示。数据库约束,是最后一道防线。
相关文章:
数据库设计问题记录
唯一性约束和逻辑删除的冲突 问题描述 如果一张表中,存在唯一性约束,比如一些数据中的code,且数据表使用逻辑删除。当删除某行数据的时候,以后再次插入相同code的数据,数据库会报错。 问题分析 在逻辑删除中&#…...
mac_录屏
参考: mac m1上系统内录方法BlackHole代替soundflower录音(附安装包) https://blog.csdn.net/boildoctor/article/details/122765119录屏后没声音?这应该是 Mac(苹果电脑) 内录声音最优雅的解决方案了 https://www.bilibili.com/…...
【Java-tesseract】OCR图片文本识别
文章目录 一、需求二、概述三、部署安装四、技术细节五、总结 一、需求 场景需求:是对识别常见的PNG,JPEG,TIFF,GIF图片识别,环境为离线内网。组件要求开源免费,并且可以集成Java生成接口服务。 二、概述 我不做选型对比了,我筛选测试了下Tesseract(v…...
redis cluster集群
华子目录 什么是redis集群redis cluster的体系架构什么是数据sharding?什么是hash tag集群中删除或新增节点,数据如何迁移?redis集群如何使用gossip通信?定义meet信息ping消息pong消息fail消息(不是用gossip协议实现的࿰…...
解锁高效密码:适当休息,让学习状态满格
一、“肝帝” 的困境 在当今竞争激烈的职场中,“肝帝” 现象屡见不鲜。超长工时仿佛成为了许多行业的 “标配”,从互联网企业的 “996”“007”,到传统制造业的轮班倒、无休无止的加班,员工们的工作时间被不断拉长。清晨ÿ…...
代码随想录算法训练营第十一天-150.逆波兰表达式求值
队列栈 #include <iostream> #include <vector> #include <stack>class Solution { public:int evalRPN(std::vector<std::string>& tokens) {std::stack<long long> stack_number;for (auto it tokens.begin(); it ! tokens.end(); it) {…...
C++ 泛编程 —— 嵌套使用模板类
嵌套使用模板类 嵌套使用模板类最常见的场景数组容器中有栈容器栈容器中有数组容器递归使用模板类 嵌套使用模板类最常见的场景 容器中有容器 数组的元素可以是栈,栈中的元素可以是数组。先来看一下Stack和Vector的基本代码,定长数组Array的代码也给出来…...
【WebGIS】Cesium:GLTF数据加载
在3D Web GIS开发中,使用GLTF格式的模型可以提高应用的加载速度并提升用户体验。Cesium.js是一个强大的3D地理空间引擎,支持GLTF格式的3D模型,并且提供丰富的API来处理和优化模型的加载和渲染。本文将系统地介绍如何加载GLTF模型,…...
【面经】25届 双非本科 字节跳动 北京 四年的总结
点击“硬核王同学”,选择“关注” 福利干货第一时间送达 大家好,我是硬核王同学,最近在做免费的嵌入式知识分享,帮助对嵌入式感兴趣的同学学习嵌入式、做项目、找工作! 给大家分享一个25届本科大佬的面经,…...
抖去推碰一碰系统技术源码/open SDK转发技术开发
抖去推碰一碰系统技术源码/open SDK转发技术开发 碰一碰智能系统#碰碰卡系统#碰一碰系统#碰一碰系统技术源头开发 碰碰卡智能营销系统开发是一种集成了人工智能和NFC技术的工具,碰碰卡智能营销系统通过整合数据分析、客户关系管理、自动化营销活动、多渠道整合和个…...
goview——vue3+vite——数据大屏配置系统
低代码数据大屏配置系统: 数据来源是可以动态api配置的: 配置上面的api接口后,在数据过滤中进行数据格式的转化。 以上内容,来源于https://gitee.com/dromara/go-view/tree/master-fetch/ 后端代码如下,需要更改…...
中间件xxl-job安装
拉取镜像 docker pull xuxueli/xxl-job-admin:2.4.2 创建xxl-job-admin容器 docker create --name xxl-job-admin -p 9099:8080 -e PARAMS"--spring.datasource.urljdbc:mysql://192.168.96.57:3306/xxl_job2Unicodetrue&characterEncodingUTF-8 --spring.dataso…...
【第2篇】 Python与数据库基础
1. 数据库的基本概念 1.1 表(Table) 表是数据库中存储数据的基本单位,由行和列组成。例如:users 表可以存储用户信息,每一行代表一个用户,每一列代表用户的属性(如姓名、年龄)。 …...
CTFHUB-web进阶-php
我们用蚁剑中的这个插件来做这些关卡 一.LD_PRELOAD 发现这里有一句话木马,并且把ant给了我们,我们直接连接蚁剑 右键 选择模式,都可以试一下,这里第一个就可以 点击开始 我们进入到目录,刷新一下,会有一个…...
深度学习使用Anaconda打开Jupyter Notebook编码
新手入门深度学习使用Anaconda打开Jupyter Notebook编码 1. 安装Anaconda 第一种是Anaconda官网下载安装包,但是很慢,不太建议 第二种使用国内清华大学镜像源下载 选择适合自己电脑的版本,支持windows,linux系统 下载完之后自行…...
金蝶V10中间件的使用
目录 环境准备搭建过程配置修改应用部署 环境准备 Linux内核服务器JDK1.8安装包:AAS-V10.zip程序包:***.war 搭建过程 将安装包上传至服务器opt目录下,官方给定的默认服务主目录为“/opt/AAS-V10/ApusicAS/aas/”;解压安装包(解…...
Firewalld 防火墙详解:深入理解与实践指南
在现代网络环境中,防火墙是保护系统和网络不受未授权访问的关键工具。firewalld是Linux系统中广泛使用的动态防火墙管理工具,它提供了强大的功能和灵活的配置选项。本文将深入探讨firewalld防火墙的工作原理、配置和管理,以及如何在实际环境中…...
linux系统编程(五)
1、信号 信号是事件发生时对进程的通知机制,针对每个信号都定义了一个唯一的整数,这些整数定义在signal.h中。 常见信号如下: SIGABRT:进程调用abort函数,系统向进程发送此信号,终止进程并产生核心转储文…...
Effective C++ 条款 16:成对使用 `new` 和 `delete` 时要采取相同形式
文章目录 条款 16:成对使用 new 和 delete 时要采取相同形式核心思想示例代码错误用法分析设计建议总结 条款 16:成对使用 new 和 delete 时要采取相同形式 核心思想 一致性要求 当使用 new 分配内存时,必须在相应的 delete 操作中保持一致&a…...
【HarmonyOS NEXT】鸿蒙原生应用“上述”
鸿蒙原生应用“上述”已上架华为应用市场,欢迎升级了鸿蒙NEXT系统的用户下载体验,用原生更流畅。 个人CSDN鸿蒙专栏欢迎订阅:https://blog.csdn.net/weixin_44640245/category_12536933.html?fromshareblogcolumn&sharetypeblogcolumn&a…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
