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

9.深度剖析MySQL约束的工程设计:自增主键的分布式局限、外键约束的权衡,与CHECK的版本适配实践

目录

一、上节课复习:MySQL到底是个啥玩意儿

主键的坑,你踩过吗?

二、外键约束:父表和子表的爱恨情仇

实战场景:电商网站的商品下架

三、check约束


一、上节课复习:MySQL到底是个啥玩意儿

首先,mysql是一个客户端-服务器结构的程序。这意味着我们通过Navicat这样的客户端,通过网络发送SQL请求给MySQL服务器,服务器处理完再通过网络返回结果。客户端和服务器可以在同一台机器,也可以在不同机器。

基本操作就是经典的增删改查

  • insert

  • delete

  • update

  • select

然后重点来了——数据库约束。计算机圈子里流传了一句话:"人是不靠谱的",数据库的数据通常非常重要,必须保证准确性,程序的约束就是其中一种。

常见的约束有这些:

  • NOT NULL非空约束

  • DEFAULT默认约束

  • UNIQUE唯一约束

  • PRIMARY KEY主键约束

  • FOREIGN KEY外键约束

  • CHECK检查

主键的坑,你踩过吗?

一个表中只能有一个主键,通常主键使用整数来表示。最常用的是自增主键

create table student (id int primary key auto_increment, name varchar(20));

但是!这里有个巨坑——自增主键仅限于单节点的MySQL服务器场景使用。如果是多节点的情况,比如大公司数据量级非常庞大,靠一个服务器存储不现实,搞了20个MySQL服务器构成的集群,这时候自增主键就可能会重复!因为各个节点的自增是独立的,AB之间的自增主键是会出现重复的。

业界流传了很多分布式情况下唯一的id生成算法,比如雪花算法。核心思想是把时间戳+主机的标识+随机的数字,然后通过hash算法映射成整数。虽然hash算法存在冲突概率,但工程上选择好的hash算法可以让这个概率变得极低(工程上忽略不计)。

二、外键约束:父表和子表的爱恨情仇

外键约束涉及到两个表的关系。比如学生表(studentId, name, classId)和班级表(classId, name)。班级表是父表,学生表是子表。

设定外键约束时,需要明确当前表的哪个列和另外一个表的哪个列建立关联关系:

create table class (classId int primary key auto_increment, name varchar(20)); create table student (studentId int primary key auto_increment, name varchar(20), classId int, foreign key (classId) REFERENCES class(classId));

父约束子,子也在约束父——这就是外键的精髓!

当你往student表插入数据时,会先触发一次针对class表的查询,查到结果了才能插入,没有查到就会报错:

insert into student values(1, '张三', 1), (2, '李四', 2), (3, '王五', 3); -- 如果class表里没有classId=3,这里就会报错

修改时同样会触发查询:

update student set classId = 100 where studentId = 3; -- 也会报错

更狠的是删除和修改父表时,也会去查询子表,看子表是否有数据使用,有的话就失败,没有才能正常进行:

delete from class where classId = 2; -- 会报错

实战场景:电商网站的商品下架

我这里可以提一个很经典的场景:淘宝这样的电商网站,商品表goods(id, name, price...),订单表order(id, time, goodsId)。订单表的goodsId应该是出自于商品表。

如果商品下架了,delete能删除吗?如果用外键约束,是不能直接delete的,会报错!

那怎么办?逻辑删除不是使用delete,而是通过update把is_online字段改成0。返回商品列表的时候,select ... where is_online = 1

这就像是学习数据结构中的顺序表里的"逻辑删除"——不需要把usedSize那个位置的元素干掉,只是把标志位改成0。虽然意味着数据库的内容越来越多,空间浪费就浪费了,毕竟硬盘不值钱,这不是主要矛盾。

如果不加外键约束就会报错,核心问题在于"索引"。子表中插入数据,就会涉及到自动在父表中进行查询。索引相当于在表中搞了一个特殊的数据结构,相当于"目录",可以加快查询的速度。默认是顺序遍历O(N)比较低效,被标记为主键的列会自动创建索引。如果引用的是其他列,也可以给其他的列手动创建索引:

create table class(classId int unique, name varchar(20)); create table student(studentId int, name varchar(20), classId int, FOREIGN key (classId) REFERENCES class(classId));

unique这样也可以起到一个自动创建索引的效果。

三、check约束

check (表达式) 是用来做条件判断的,后续插入修改数据,都会自动代入条件,条件成立才能够进行插入修改。

create table student (id int, name varchar(20), gender varchar(10)); insert into student values (1, '张三', '武装直升机'), (2, '李四', '沃尔玛购物袋'); select * from student; -- 可以明显看到这样插入的性别非常不合理,但也可以插入

然后加上check约束:

drop table student; create table student (id int, name varchar(20), gender varchar(10), check (gender = '男' or gender = '女')); insert into student values (1, '张三', '武装直升机'), (2, '李四', '沃尔玛购物袋'); select * from student; -- 这样就会报错了!!!!!!!!!!!!!!!!!!!!!!!!!!

再比如:

create table score(id int, score int check (score >= 0 and score <= 100)); insert into score values(1, 101); -- 像这种约束也能起作用

但是!​ check是从mysql 8.0.16这个版本开始支持的。当前很多公司用的是5.7版本,也有老项目用更早的。组件的升级,对于很多公司来说是不愿意做的。之前check虽然不会报错,但是实际没有生效——纯属摆设!


希望这篇笔记能帮到正在学MySQL的兄弟们,少走点弯路,少踩点坑!有问题评论区交流,一起加油!

http://www.jsqmd.com/news/790847/

相关文章:

  • 强力揭秘:Windows热键冲突诊断神器,一键揪出“热键小偷“
  • 如何快速搭建抖音下载环境:3步完成高清无水印内容保存
  • BooruDatasetTagManager:智能标注架构革命,让AI训练数据预处理效率提升300%
  • 微信聊天记录数据化永久保存完整指南:WeChatMsg技术实现与应用实践
  • 10.数据库设计入门:从学生视角看三大范式与软性约定
  • 3步构建永久小说资产库:番茄小说下载器技术深度解析
  • 从TI官方方案到STM32实战:48V BMS核心芯片选型与调试避坑指南
  • 自制编程语言:挑战与乐趣并存,10000 行 C++ 代码实现多项功能,未来规划丰富!
  • [具身智能-632]:语音数据存储格式,一口气讲透(通俗 + 工程版)
  • SingleFile:一键保存完整网页的终极解决方案,告别碎片化保存烦恼
  • WindowResizer完整指南:如何强制调整任意Windows窗口大小
  • caj2pdf:3步轻松将知网CAJ文献转为可编辑PDF
  • CAPL脚本调试实录:diagGenerateKeyFromSeed参数填错,我的UDS安全解锁为什么总失败?
  • [具身智能-633]:语音 PCM 超通俗精讲(嵌入式 / 树莓派 / RK3588 专用)
  • SuperDuper框架:AI模型与数据库的无缝集成与向量搜索实践
  • 为Claude Code配置Taotoken解决封号与Token不足问题
  • 基于Simulink的SVG无功补偿装置谐波治理仿真​
  • N_m3u8DL-RE:如何5分钟掌握跨平台流媒体下载与解密核心技术?
  • 别再乱调字体了!Qt界面开发中QSS字体属性(font-family, size, weight)的实战避坑指南
  • CVT算法实战踩坑记:从点云到三角网格,我遇到的三个‘坑’及填坑方案
  • TikTok评论采集终极指南:3步轻松获取完整评论数据,无需编程技能
  • AI原生持续集成实战手册(SITS 2026 CI/CD for LLM全栈适配白皮书)
  • [具身智能-634]:语音全链路:通道 → PCM 编码 → 传输格式 → 存储格式 → WAV 文件
  • 2026新式酸奶饮品模式爆火,健康与口感成为竞争关键点 - 博客湾
  • 为什么ChatGPT Enterprise没敢用SITS 2026?——对话状态持久化设计中的3个IEEE标准冲突点(附合规改造路径)
  • NadirRouter/NadirClaw:高性能网络数据采集与智能代理路由实战指南
  • 独立开发者如何利用Taotoken管理多个个人项目的AI调用成本
  • TikTokCommentScraper:创新智能的抖音评论自动化采集解决方案,让数据驱动决策变得简单
  • 第51篇:Vibe Coding时代:LangGraph + 权限系统实战,解决 Agent 谁都能改代码、调用工具的安全问题
  • with open() 打开文件 文件被占用 except PermissionError