开始前,会这些就够了
- 知道主键用于识别一行
遇到不熟悉的词,先看这 2 个解释
- 索引
- 数据库为查找数据维护的辅助结构,让某些查询可以缩小要检查的范围,而不必总从头逐行寻找;新增、修改和删除数据时,相关索引也需要维护。
- 主键
- 表中用来唯一识别一行的一列或一组列,要求这组值不重复、各列也不为空;其他数据或程序可以借它准确指向那一行,而不只依赖可能重名的文字。
假设一个练习商城最初只有一台数据库,用递增数字当订单主键很方便。后来移动端希望离线建立草稿,几个系统又要合并数据,于是有人提议全部换成 UUID。这个决定不能只用“数字短”或“UUID 不重复”来拍板,因为编号同时参与生成、存储、查询和外部交互。
先说明在哪个范围里不能重复
单个数据库可以用序列或自增列协调分配数字;多个互不联系的生成者则需要约定各自范围,或使用适当的分布式生成方式。UUID 是一组一百二十八位标识格式,其中 v4 使用随机或伪随机位,通常不必为每次生成联系一个中央计数器。
“极难碰撞”和“数学上绝不碰撞”不是同一句话。随机源、实现错误和数据导入仍需要考虑,数据库唯一约束仍有价值。对一条重要写入,应明确遇到冲突怎样处理,而不是因为名字里有“唯一”,就取消最后一道数据约束。
UUID 也有带时间顺序的版本
RFC 9562 定义的 UUIDv7 在高位放入毫秒时间信息,并用其余部分承载随机数据或符合规则的补充字段。因此讨论“UUID 的插入顺序”时,要先问是哪一版,不能把 v4 的随机性套到所有 UUID 上。时间排序也不自动等于多个机器上的真实全局发生顺序。
假设甲先取得一个编号,却做了较长计算;乙后取得编号,先提交事务。按编号排出来,甲仍可能在乙前面,但提交顺序恰好相反。需要展示创建时间、支付时间或严格业务序号时,应明确记录相应事件,而不是指望一个主键回答所有时间问题。
主键大小会影响其他索引
在 MySQL 8.4 InnoDB 中,表的行数据通常按主键组织为聚簇索引,二级索引记录也携带主键。因此较长主键的空间成本可能出现在多个索引里。UUID 是一百二十八位,但把它存成二进制还是带连字符文本,数据库字段与编码也会影响实际占用。
递增与分散的键会让插入位置不同,但性能还取决于数据量、缓存、并发和存储结构。不能仅凭一个编号样例就宣布谁快十倍,更不能把 InnoDB 的结论原封不动搬到另一种数据库。评估时固定存储类型、索引数量和负载,再比较写入与查询成本。
连续号码可以是另一项业务功能
递增也不代表没有缺号。PostgreSQL 17 文档明确说明,事务回滚等情况不会收回已领取的序列值,因此不能拿普通序列承诺连续无缺号。若业务确实要求编号连续,需要单独设计分配、作废和审计规则,并接受相应协调成本。
内部主键与给用户看的订单号可以分开设计:一个服务于存储关联,一个服务于输入、查找或业务规则。随机编号也不能代替权限检查,知道一个编号不意味着有权读取对应订单。最后把需求写成清单:谁生成、能否离线、怎样合并、如何排序、冲突怎么办,再选择符合它们的方案。
记住这三点
- 先界定唯一范围和生成者,再比较递增数字与 UUID。
- UUIDv4 与 UUIDv7 的结构不同,不能统称为随机主键。
- 编号大小、生成顺序、提交顺序和业务连续性是不同要求。
别把例子用过头
- 随机碰撞概率低不等于无条件唯一,仍应处理约束冲突。
- 本篇没有提供性能测评,索引影响需要在选定数据库中验证。
- 主键不能自动充当权限凭据或连续业务序号。
自己试一小步
离线草稿需要本地生成 ID,正式订单又想用短内部主键,能否分别设计?
- 列出草稿同步到服务器的身份对应关系。
- 假设同一草稿重传两次,描述如何避免生成两笔正式订单。
- 说明对外订单号、内部主键与创建时间分别负责什么。
做到这些,就算完成
- 没有把编号生成等同于重试去重。
- 定义了合并和冲突规则。
- 不要求一个字段同时保证连续、全局时间顺序和随机不可预测。
查原始资料
想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。
- RFC 9562:Universally Unique IDentifiers (新标签页)↗
第 5.4、5.7、6 节支持 UUIDv4 随机位、UUIDv7 毫秒时间字段和实现约束。
- MySQL 8.4: Clustered and Secondary Indexes (新标签页)↗
支持
InnoDB聚簇索引、二级索引携带主键,以及长主键的空间影响。 - PostgreSQL 17: Sequence Manipulation Functions (新标签页)↗
直接阅读 nextval 的并发分配与 Caution:回滚不收回序列值,普通序列不能保证无缺号。
找一份资料继续练
先选一项,按下面的范围继续学;不必从头读完整门课程。
CS 186 Introduction to Database Systems:数据库原理与 Java 项目 (新标签页)↗
已有数据结构基础后,只读 B+ 树的页面与插入部分,画出不同编号落在哪些页,再讨论索引空间与写入位置。
查看学习准备与访问说明 →