主键值未正确递增

dm0*_*514 2 django postgresql auto-increment

我有一个 django 模型,它的 id 开始奇怪地增加。

列的 postgres 定义(从 Django 模型生成):

id | integer | not null default nextval('billing_invoice_id_seq'::regclass)

tpg=> SELECT MAX(id) FROM billing_invoice;
  max  
-------
 16260
Run Code Online (Sandbox Code Playgroud)

然后我通过 django admin 创建了一个新记录:

tpg=> SELECT MAX(id) FROM billing_invoice;
  max  
-------
 17223

tpg=> SELECT nextval('billing_invoice_id_seq');
 nextval 
---------
   17224
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个新记录,它跳过了 17224 值并插入了 17225 的主键:

tpg=> SELECT nextval('billing_invoice_id_seq');
 nextval 
---------
   17226
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么会这样?应用程序此时并不关心,因为 id 仍在增加,但在最后几个新对象中,PK 在一次插入中从 427 -> 4357 跳过,然后在 2 个对象中跳到 8378,然后在 3 个对象中跳到 97xx它跳到了 14k。

Erw*_*ter 8

从序列中获取默认值的串行列永远不能保证是无间隙的。它们保证是唯一的升序的(如定义的)并且可以安全地并发使用
如果已从序列中提取数字的交易被回滚,则该数字将被销毁且不再使用......根据文档:

注意:由于smallserial,serialbigserial是使用序列实现的,因此列中出现的值序列中可能存在“漏洞”或间隙,即使从未删除任何行。从序列分配的值仍然“用完”,即使包含该值的行从未成功插入到表列中。例如,如果插入事务回滚,则可能会发生这种情况。见nextval()9.16节了解详情。

如果您看到类似 的大间隙427 -> 4357,则表明存在严重问题。其他某个列(或任何进程)正在从相同的序列中绘制,或者您的应用程序逻辑有问题,不知何故烧毁了很多序列 ID。

典型的候选对象是循环出错或从未提交的事务。