django - 如何安全地转发 Django 中的主键序列?

标签 django postgresql sequence

使用带有 PostgreSQL (8.x) 后端的 Django,我有一个模型,我需要跳过一个 id block ,例如在发出 49999 之后,我希望下一个 id 是 70000 而不是 50000(因为该 block 是为另一个源保留的,其中实例是用 id 显式添加的——我知道这不是一个很好的设计,但这是我必须使用的)。

执行此操作的正确/最安全的地方是什么?

我知道我可以设置顺序

SELECT SETVAL(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id')),
    70000,
    false
);

但是 Django 何时真正从序列中提取数字? 我是否重写 MyModel.save(),调用它的 super 然后捕获我的光标并检查

SELECT currval(
    (SELECT pg_get_serial_sequence('myapp_mymodel', 'id'))
);

?

我相信即使保存模型失败,django 也可能会推进一个序列,所以我想确保每当它达到那个数字时它就会推进 - 有比 save() 更好的地方吗?

P.S.:即使那是要走的路——我真的能像这样计算出 save() session 的当前值吗?如果我获取一个连接和游标,并执行第二个 SQL 语句,我是否会处于另一个 session 中,因此不会获得 currval?

感谢您的指点。

编辑:我觉得这必须在数据库级别完成(并发问题)并发布了相应的 PostgreSQL 问题 - How can I forward a primary key sequence in PostgreSQL safely?

最佳答案

由于我还没有找到执行此操作的“自动化”方式,我正在考虑以下解决方法 - 它对我的特定情况是可行的:

  1. 使用 MAXVALUE 49999 NO CYCLE 设置序列
  2. 当达到 49999 时,下一个 save() 将遇到 postgres 错误
  3. 捕获该异常并作为表单错误重新引发“你的数字用完了,请重置到下一个 block 然后重试”
  4. 提供一个 View ,用户可以在其中激活下一个 block ,即执行“ALTER SEQUENCE my_seq RESTART WITH 70000 MAXVALUE 89999”

我对捕获异常时自动重启感到不安:

try:
    instance.save()
except RunOutOfIdsException:
    restart_id_sequence()
    instance.save()

因为我担心两个并发的 save() 用完 id 会导致两次单独的重新启动,并随后违反唯一约束。 (与原始问题的概念基本相同)

关于django - 如何安全地转发 Django 中的主键序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9307896/

相关文章:

r - 根据以前的评级创建顺序排名

bash - 为什么在循环时出现此bash错误?它不会让我使用C语法

django - ModelChoiceField 上的验证错误

python - 制作 Django Rest Framework (DRF) 工作流的方法

postgresql - 如何在 Kubernetes 上实现 Postgres 备份?

postgresql - PGError : ERROR: column "p.name" must appear in the GROUP BY clause or be used in an aggregate function

python - Django-summernote 工作正常,但显示带有 HTML 标签的文本

python - Django更改密码而无需再次登录

c# - Entity Framework 在数据库中添加了额外的字段。并添加复合键的两个成员

algorithm - 原始数据中的模式发现