将Django与PostgreSQL(8.x)后端一起使用,我有一个模型,我需要跳过一块id,例如在给出49999之后,我希望下一个id为70000而不是50000(因为该块是为另一个源保留的,其中实例是用id明确添加的 - 我知道这不是一个很棒的设计,但它是我必须使用的。)< / p>
这样做的最正确/最安全的地方是什么?
我知道我可以用
设置序列SELECT SETVAL(
(SELECT pg_get_serial_sequence('myapp_mymodel', 'id')),
70000,
false
);
但Django什么时候从序列中拉出一个数字? 我是否覆盖MyModel.save(),调用它的超级,然后抓住一个光标并检查
SELECT currval(
(SELECT pg_get_serial_sequence('myapp_mymodel', 'id'))
);
我相信django可能会推进一个序列,即使保存模型失败了,所以我想确保无论什么时候它都会触及它前进的数字 - 还有比save()更好的地方吗?
P.S。:即使这是可行的方法 - 我真的可以像这样找出save()会话的currval吗?如果我抓住一个连接和光标,并执行第二个SQL语句,我不会在另一个会话中,因此没有得到一个currval?
感谢您的任何指示。
编辑:我觉得这必须在数据库级别完成(并发问题)并发布相应的PostgreSQL问题 - How can I forward a primary key sequence in PostgreSQL safely?
答案 0 :(得分:0)
由于我还没有找到一种“自动化”方式,我正在考虑以下解决方法 - 这对我的特殊情况是可行的:
我很难在捕获异常时自动重启:
try:
instance.save()
except RunOutOfIdsException:
restart_id_sequence()
instance.save()
因为我担心两个并发的save()用完了id会导致两次单独的重启,并且后续违反了唯一约束。 (与原始问题基本相同的概念)
答案 1 :(得分:0)
我的下一个想法是不使用主键的序列,而是总是从一个单独的计数器表中明确指定id,我在使用其最新数字之前检查/更新 - 应该是避免并发问题。唯一的问题是虽然我只有一个地方可以添加模型实例,但django或第三方应用程序的其他部分仍然可能依赖于隐式ID,我不想破坏它。
但同样的机制碰巧很容易在postgres级别实现 - 我相信这是解决方案: