为什么不是';t模型ID是否始终是Postgres/Django中的下一个递增数字?

为什么不是';t模型ID是否始终是Postgres/Django中的下一个递增数字?,django,postgresql,auto-increment,Django,Postgresql,Auto Increment,我在Django中有一个Booking模型,它的ID是Django创建的内置ID列。以下是它在Postgres数据库级别的表现: integer not null default nextval('bookings_booking_id_seq'::regclass) 客户今天打电话来,担心这些数字似乎是连续的,但并不总是连续的。例如,顺序如下: ..2, ..3, ..4, ..6, ..8, ..9 他们担心该系统正在取消或删除预订。哪里是.5和.7?我们[实际上]记录了所有可以删除

我在Django中有一个
Booking
模型,它的ID是Django创建的内置
ID
列。以下是它在Postgres数据库级别的表现:

integer   not null default nextval('bookings_booking_id_seq'::regclass)
客户今天打电话来,担心这些数字似乎是连续的,但并不总是连续的。例如,顺序如下:

..2, ..3, ..4, ..6, ..8, ..9
他们担心该系统正在取消或删除预订。哪里是
.5
.7
?我们[实际上]记录了所有可以删除预订的内容,所以我很有信心这不是系统问题。程序员的直觉也教会了我不要期望自动ID的连续性,但仅仅凭直觉还不足以向客户解释

是否有技术原因导致Postgres在分配这些ID时跳过数字?

来自:

因为smallserial、serial和bigserial是使用序列实现的,列中出现的值序列中可能会有“孔”或间隙,即使从未删除任何行。从序列中分配的值仍然“用完”,即使包含该值的行从未成功插入表列。例如,如果插入事务回滚,可能会发生这种情况。有关详细信息,请参见第9.16节中的nextval()

也可以从

为了避免阻塞从同一序列获取数字的并发事务,nextval操作永远不会回滚;也就是说,一旦获取了一个值,它就被视为已使用,不会再次返回。即使周围的事务稍后中止,或者如果调用查询最终没有使用该值,这也是正确的。例如,带有ON CONFLICT子句的INSERT将计算要插入的元组,包括执行任何必需的nextval调用,然后再检测可能导致其遵循ON CONFLICT规则的任何冲突。这种情况将在指定值序列中留下未使用的“孔”。因此,PostgreSQL序列对象不能用于获取“无间隙”序列

这是正常的,当事务回滚时,序列中可能存在漏洞,等等。技术原因是这样序列是无锁的(否则它可能成为锁定热点或漏斗)。