为什么模型 ID 不总是 Postgres/Django 中的下一个递增数字?

Why isn't model ID always the next incremented number in Postgres/Django?

我在 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 时会跳过数字是否有技术原因?

来自postgres docs

Because smallserial, serial and bigserial are implemented using sequences, there may be "holes" or gaps in the sequence of values which appears in the column, even if no rows are ever deleted. A value allocated from the sequence is still "used up" even if a row containing that value is never successfully inserted into the table column. This may happen, for example, if the inserting transaction rolls back. See nextval() in Section 9.16 for details.

以及 nextval

的文档

To avoid blocking concurrent transactions that obtain numbers from the same sequence, a nextval operation is never rolled back; that is, once a value has been fetched it is considered used and will not be returned again. This is true even if the surrounding transaction later aborts, or if the calling query ends up not using the value. For example an INSERT with an ON CONFLICT clause will compute the to-be-inserted tuple, including doing any required nextval calls, before detecting any conflict that would cause it to follow the ON CONFLICT rule instead. Such cases will leave unused "holes" in the sequence of assigned values. Thus, PostgreSQL sequence objects cannot be used to obtain "gapless" sequences.