主键值未正确递增
主键值未正确递增
我有一个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。
主键值不正确递增的问题可能是由于以下原因导致的:
1. 序列生成的默认值不保证是连续的。它们保证是唯一的和递增的,对于并发使用是安全的。
2. 如果从序列中取出的数值在事务回滚时没有被使用,那么这个数值就会被浪费,不会再被使用。
解决这个问题的方法是:
1. 根据文档,我们知道即使没有删除任何行,序列中的值可能会有"holes"或间隔。即使包含该值的行从未成功插入到表列中,从序列分配的值仍然被使用掉。这可能发生在插入事务回滚的情况下。因此,出现间隔并不一定意味着存在问题。
2. 如果你看到类似于"427 -> 4357"这样的大间隔,那么这可能是一个严重的问题。可能是其他列(或任何其他进程)也在使用同一个序列,或者是你的应用逻辑存在问题,导致大量的序列号被浪费。
3. 可能的原因是循环出现错误或事务没有被成功提交。
因此,要解决这个问题,你需要仔细检查你的应用逻辑,确保没有其他地方在使用同一个序列,并确保你的事务正确提交。