mongodb原生不支持自增主键,其默认objectid由客户端生成,设计上摒弃全局递增序列以保障分布式扩展性;所谓“id不连续”实为应用层模拟计数器(如findandmodify)导致,并非数据库自身行为。

AUTO_INCREMENT),也不支持传统关系型数据库那种由存储引擎内建、全局递增且带事务语义的自增 ID 机制。所谓“MongoDB 事务回滚后自增 ID 不连续”,本身是个伪命题——因为 MongoDB 根本不提供这种 ID。
如果你在代码里看到类似“ID 跳号”“回滚后 ID 缺失”的现象,那一定是你在应用层模拟了自增逻辑(比如用 findAndModify 更新计数器),而不是 MongoDB 原生行为。
为什么 MongoDB 没有 AUTO_INCREMENT?
MongoDB 的设计哲学是去中心化和水平扩展,_id 字段默认由客户端生成(ObjectId),天然避免单点 ID 分配瓶颈。它不依赖服务端维护一个全局递增序列,因此不存在“回滚后 ID 是否回收”这类问题。
你真正在用的“自增 ID”大概率是手动计数器
当你用如下方式模拟自增 ID:
db.counters.findAndModify({
query: { _id: "users" },
update: { $inc: { seq: 1 } },
new: true
})
这个 seq 字段的行为才可能表现出“不连续”。原因包括:
- 事务中调用
findAndModify后又回滚:计数器已 +1,但业务数据没写入,ID 就空耗了 - 并发请求同时读到同一旧值,各自 +1 → 写冲突重试失败,但部分计数操作可能已落盘(取决于重试逻辑)
-
findAndModify本身不是事务内原子操作:若放在多文档事务里,它不能跨集合使用,且不能作为事务的一部分被回滚
innodb_autoinc_lock_mode 这类参数对 MongoDB 完全无效
这是 MySQL InnoDB 特有的配置项,只影响 INSERT ... VALUES (NULL, ...) 类语句的 ID 预分配策略。MongoDB 没有对应概念,也不存在 innodb_autoinc_lock_mode、AUTO_INCREMENT=100 或 SHOW CREATE TABLE 这类语法。混淆这两套系统,是排查方向错误的常见源头。
真正该警惕的是 ObjectId 时间戳与排序假象
很多人误把 ObjectId 当成“时间序自增 ID”,并期望它严格按插入顺序递增。但它只是前 4 字节为秒级时间戳,后段含随机值;高并发下完全可能出现 ObjectId A > ObjectId B 但插入时间更晚的情况。这不是“不连续”,而是设计如此——别把它当主键序列用。











