UUID(通用唯一标识符) 就是一个全宇宙唯一的 ID,常用来标识用户、订单、设备、会话等。
🧊 举个现实生活中的例子
比如你去医院挂号,每个人都有一个唯一的挂号编号。
你去银行开账户,每个账户也有个唯一的编号。
那在编程世界里,如果你想标识一个用户或订单,并且不想依赖数据库的自增主键怎么办?
你就用 UUID!因为它能保证唯一性,不会重复。
👀 UUID 看起来像什么?
一个标准的 UUID 长这样:
550e8400-e29b-41d4-a716-446655440000
这是 36 个字符(包含 4 个 -),由 128 位(16 字节)的数据组成。
格式结构如下:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M 表示 UUID 的版本(最常用的是 v4)N 表示变体
🧪 UUID 有哪些版本?
UUID 有很多版本,最常见的是:
版本名称特点v1基于时间戳包含 MAC 地址 + 当前时间v3/v5基于名字可重复(名字 + 命名空间 hash)✅ v4基于随机数最常用,完全随机,适合通用生成比如:
from uuid import uuid4
print(uuid4()) # 随机生成一个 v4 UUID
输出类似:
e21f1c68-18f9-4728-a364-278195fd61ae
🔐 UUID 为什么说“几乎不可能重复”?
因为它有 2 的 128 次方种组合(约等于 3.4 × 10^38)
就算你每秒生成 10 亿个 UUID,连续生成 100 年,也不太可能碰撞。
✅ UUID 在实际项目中的用途:
场景用法说明用户 ID不用数据库自增,提前生成 UID订单号 / 交易号确保唯一,适合分布式系统文件命名上传文件时用 UUID 防止重名冲突会话 / token ID标识用户会话
📌 UUID vs 数据库自增 ID 的区别?
特点UUID数据库自增 ID唯一性全局唯一(跨系统不重复)只在一个库唯一安全性不容易猜测可以被预测顺序性不连续,不适合做排序/索引优化是连续的数字使用场景分布式、需要提前生成的 ID单库、简单系统
🧪 Python 中怎么用 UUID?
from uuid import uuid4
user_id = uuid4()
print(user_id) # 输出一个随机 UUID
print(user_id.bytes) # 输出 16 字节二进制形式
✅ 总结一句话:
UUID 是一种在全球范围内都唯一的标识符,常用于分布式系统、用户 ID、订单号等,不依赖数据库自增,非常适合需要“唯一性 + 不重复”的场景。
MongoDB能直接存储UUID么?
MongoDB 不是不能存储 UUID,而是它内部没有专门的 UUID 类型,只能用 Binary(二进制)格式来存储 UUID。
这就好比:
UUID 是个「身份证号」,但 MongoDB 的抽屉里没有专门的「身份证类型」,只能当「字节流」装进去。
🔍 更详细的解释:
✅ UUID 是什么?
UUID 是一种 128 位(16 字节)长度的唯一标识符:
import uuid
print(uuid.uuid4())
# 输出:3fa85f64-5717-4562-b3fc-2c963f66afa6
它的本质是 16 个字节的二进制数据。
❓为什么 MongoDB 不能直接存 UUID?
因为 MongoDB 的 BSON 数据格式没有一个专门叫 UUID 的字段类型。
它只能识别以下几种:
类型说明String普通字符串Int32/Int64整数Boolean布尔值Binary二进制数据(支持 UUID)Date日期所以,MongoDB 会用 Binary subtype 4(也叫 UUID 子类型)来保存 UUID。
🧩 举个例子:
假设我们生成了一个 UUID:
uuid_val = uuid.uuid4()
# 例如:'3fa85f64-5717-4562-b3fc-2c963f66afa6'
我们不能直接丢进 MongoDB,必须先转换成 Binary:
from bson.binary import Binary, UuidRepresentation
binary_data = Binary.from_uuid(uuid_val, uuid_representation=UuidRepresentation.STANDARD)
这样才能被 MongoDB 正确识别为 UUID。
✅ MongoDB 怎么识别这是 UUID?
它通过 Binary 类型的 子类型(subtype) 来识别。
Subtype 值含义0x00普通 Binary 数据0x04UUID 标准表示(推荐)也就是说,UUID 在 MongoDB 里是 Binary 类型,但有一个特殊的 subtype,告诉数据库「这是 UUID」而不是纯二进制。
🔁 为什么读出来还要 .as_uuid()?
因为你存进去的是 Binary 对象,读取出来后是 Binary 类型,要还原成 uuid.UUID 对象,就需要:
uuid_val = binary_data.as_uuid()
就像你从冰箱里拿出一袋速冻水饺,还得煮一下才能吃。😄
🧵 总结:
问题回答MongoDB 能不能存 UUID?能,但它会存成 Binary 类型(subtype = 4)为什么不用字符串?可以用字符串,但 Binary 更节省空间(16字节 vs 36 字符)如何保存 UUID?用 Binary.from_uuid() 转换如何还原 UUID?用 binary_val.as_uuid()
再用一个完整例子来说明MongoDB 中没有直接的 UUID 类型,过程如下 :
✅ 生成 UUID
✅ 保存进 MongoDB(以二进制 Binary 格式)
✅ 从 MongoDB 读出并还原为 UUID 对象
我们会用到:
Python 内置模块:uuidMongoDB 驱动:pymongoBinary 类型支持:bson.binary.Binary
🧪 代码示例:保存和读取 UUID
from uuid import uuid4, UUID
from pymongo import MongoClient
from bson.binary import Binary, UuidRepresentation
import bson
# 🔌 连接 MongoDB
client = MongoClient("mongodb://localhost:27017")
db = client["demo_db"]
collection = db["users"]
# ✅ 模拟用户数据(生成 UUID)
user_uuid = uuid4()
print(f"原始 UUID: {user_uuid}")
# 👇 保存到 MongoDB,转成 Binary 格式
user_doc = {
"user_id": Binary.from_uuid(user_uuid, uuid_representation=UuidRepresentation.STANDARD),
"name": "张三"
}
collection.insert_one(user_doc)
# 🔍 从 MongoDB 查询出来
retrieved = collection.find_one({"name": "张三"})
# 👇 还原成 UUID 对象
stored_binary: Binary = retrieved["user_id"]
uuid_restored: UUID = stored_binary.as_uuid()
print(f"还原出来的 UUID: {uuid_restored}")
print("是否相等:", uuid_restored == user_uuid)
✅ 输出示例
原始 UUID: d5ecde7d-c1e5-42b3-8f1a-62ea5edb71e2
还原出来的 UUID: d5ecde7d-c1e5-42b3-8f1a-62ea5edb71e2
是否相等: True
🧠 为什么要 Binary.from_uuid() 和 as_uuid()?
MongoDB 中没有直接的 UUID 类型,它会存成 二进制的 16 字节数据(Binary)。
所以:
操作方法UUID → BinaryBinary.from_uuid(uuid)Binary → UUIDbinary_value.as_uuid()这就跟把“身份证号”压缩存入数据库,取出来后再“还原成人”的过程一样。
📌 小贴士:uuid_representation 参数
你可能注意到这一段 👇:
uuid_representation=UuidRepresentation.STANDARD
这个是 PyMongo 4.x 要求明确指定的 UUID 存储格式。推荐用 STANDARD,符合 RFC 4122 标准。