主键值未正确递增

17 浏览
0 Comments

主键值未正确递增

我有一个Django模型,它的id开始以奇怪的方式递增。

这个列在postgres中的定义(从Django模型生成):

id | integer | not null default nextval('billing_invoice_id_seq'::regclass)
tpg=> SELECT MAX(id) FROM billing_invoice;
  max  
-------
 16260

然后我通过Django管理界面创建了一条新记录:

tpg=> SELECT MAX(id) FROM billing_invoice;
  max  
-------
 17223
tpg=> SELECT nextval('billing_invoice_id_seq');
 nextval 
---------
   17224

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

tpg=> SELECT nextval('billing_invoice_id_seq');
 nextval 
---------
   17226

有人知道为什么会发生这种情况吗?目前应用程序并不关心,因为id仍在递增,但在最近的几个新对象中,主键从427跳到了4357,然后在2个对象中跳到了8378,然后在3个对象中跳到了14k。

0
0 Comments

主键值不正确递增的问题可能是由于以下原因导致的:

1. 序列生成的默认值不保证是连续的。它们保证是唯一的和递增的,对于并发使用是安全的。

2. 如果从序列中取出的数值在事务回滚时没有被使用,那么这个数值就会被浪费,不会再被使用。

解决这个问题的方法是:

1. 根据文档,我们知道即使没有删除任何行,序列中的值可能会有"holes"或间隔。即使包含该值的行从未成功插入到表列中,从序列分配的值仍然被使用掉。这可能发生在插入事务回滚的情况下。因此,出现间隔并不一定意味着存在问题。

2. 如果你看到类似于"427 -> 4357"这样的大间隔,那么这可能是一个严重的问题。可能是其他列(或任何其他进程)也在使用同一个序列,或者是你的应用逻辑存在问题,导致大量的序列号被浪费。

3. 可能的原因是循环出现错误或事务没有被成功提交。

因此,要解决这个问题,你需要仔细检查你的应用逻辑,确保没有其他地方在使用同一个序列,并确保你的事务正确提交。

0