MongoDb ObjectId 中的 4 字节时间戳值是否会溢出?

问题描述

如果在某个时间,纪元是 ffffffff,那么此时创建的 objectId 类似于:

ffffffff15580625bcb65364

那么,1 秒后创建的 ObjectId 可能是什么?

解决方法

正如 docs 所说,时间戳由 4 字节表示。

4 字节的时间戳值,代表 ObjectId 的创建时间,以 Unix 纪元以来的秒数为单位

4 个字节是从 -2,147,483,648 到 2,647 个值,因此,即 4,294,967,295 个值。

根据 unix 时间戳从 4,295 开始的日期是:GMT:2106 年 2 月 7 日星期日 6:28:15

在此日期之后,ObjectId 将无法存储时间戳。

那么,ObjectId 会溢出吗? 85 年后,每个新创建的 ObjectId 都会失败,因为它无法创建只有 4 个字节的时间戳。

,

那么,[Unix 纪元以 32 位翻转] 之后创建的 ObjectId 可能是什么?

这取决于具体的实现、其编程语言及其对数学计算的处理。

当某些实现和语言将自 Unix 纪元以来的秒数检索为 64 位整数(这在今天很常见)然后尝试使用大小超过 32 位的值时,它们可能会出错用于 ObjectId 生成。如果发生这种情况,驱动程序将无法生成 ObjectId,因此,如果应用程序使用其他生成策略提供 _id 值,它可能无法插入文档。

在其他实现中,时间戳本身可能会回滚到零,此时 ObjectId 生成将成功,并且时间戳值非常小。

然而,其他实现可能会截断(从最重要或最不重要的一侧)时间戳以将其强制转换为 ObjectId 的 32 个可用位。

ObjectId 值本身实际上并不具有准确的时间戳 - 它要求在集合中是唯一的并且它“通常会增加”但 MongoDB-the-database 不会关心 ObjectId 值是否在某个时刻环绕为零。