前言
几乎每段后端代码里都有这么一行:
constid=crypto.randomUUID();看起来 UUID 就是“不会重复的全局 ID”,随手用、随手存。但真到排查问题时,你会发现很多人对 UUID 的理解只停留在“32 个字符”上——版本号是什么、能不能当主键、会不会冲突、需不需要加索引,一问一个懵。
这篇文章把 UUID 最常见的 5 个误区讲清楚,下次选型时少走弯路。
一、UUID 的 5 个版本
UUID 标准(RFC 9562)目前定义了 8 个版本,日常最常见的是:
- v1:基于时间戳 + MAC 地址,有序、可反推设备,不适合暴露给外部。
- v4:完全随机,最常用,128 位里有 122 位随机,冲突概率极低。
- v5:基于 SHA-1 的确定性哈希,同一名称空间 + 名称永远生成同一个 UUID,适合需要“可复现 ID”的场景。
- v7:时间排序 + 随机,数据库友好,正在成为新项目的首选。
如果你只是需要“一个不会重复的值”,v4 够用;如果你要当数据库主键并且在意写入性能,优先考虑 v7。
二、5 个常见误区
误区 1:UUID 绝对不会重复
v4 的冲突概率确实极低,数学上需要生成数万亿个才可能出现一次碰撞。但“极低”不等于“零”。如果你的生成器随机源不够真(比如某些早期实现),或者自己手写了一个“看起来随机”的算法,冲突风险就会上升。
结论:业务上如果要求绝对唯一,仍需数据库唯一约束兜底。
误区 2:把 UUID 直接当数据库主键
UUID 最大的问题是随机、无序。直接当 MySQL InnoDB 主键时,频繁插入会导致 B+ 树页分裂、索引碎片化,写入性能比自增 ID 差很多。
常见优化方案:
- 用 v7 替代 v4,天然时间有序;
- 或者使用
BINARY(16)存储,比CHAR(36)省一半空间。
误区 3:UUID 字符串需要去掉横杠
去掉横杠只是从 36 位变 32 位,省下 4 个字节,对存储帮助有限。真正占空间的是文本本身:一个 UUID 字符串要 36 字节,而BINARY(16)只要 16 字节。
建议:存储用二进制,展示再用带横杠的字符串。
误区 4:UUID 适合作为短链或邀请码
36 个字符的 URL 又长又丑,用户也不友好。短链、邀请码这类场景更适合自增 ID + 62 进制混淆,或者专门的短码生成策略。
误区 5:手动拼接字符串生成 UUID
不要自己写:
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,...);这种代码在浏览器里能跑,但随机源质量、版本位填充都容易出错。现代环境直接用:
crypto.randomUUID();// v4Node.js 18+、Chrome 92+、Edge 92+ 都已支持。
三、什么时候用 v4,什么时候用 v7
| 场景 | 推荐版本 | 原因 |
|---|---|---|
| 会话 ID、日志 Trace | v4 | 简单、随机、无顺序要求 |
| 数据库主键 | v7 | 时间有序,减少页分裂 |
| 需要可复现 ID | v5/v8 | 同一输入固定输出 |
| 暴露给用户的 ID | 避免 v1 | 防止泄露 MAC 地址和时间 |
四、快速生成工具
调试时经常需要批量生成 UUID,或者验证两个 UUID 是否版本正确。可以用浏览器本地工具:
打开 vaultool.com 的 UUID Generator(中文版:vaultool.com/zh/tools/uuid-generator),一键生成 v4/v7、批量导出、复制即用,所有计算都在本地完成,不会上传任何数据。
五、总结
- UUID 有多个版本,v4 最通用,v7 最适合数据库主键。
- UUID 冲突概率极低,但不能替代唯一约束。
- 直接当主键要注意写入性能,优先选有序版本或二进制存储。
- 不要手动拼接 UUID,用标准 API。
- 暴露给用户时避免 v1,防止信息泄露。
UUID 看似简单,但选型错了会在数据量上去之后还债。花 5 分钟搞清楚版本和场景,能省掉很多后期的迁移成本。
项目地址:vaultool.com(中文版:vaultool.com/zh/)
所有工具 100% 本地运行,数据永不离开你的设备。欢迎试用反馈!