2010-07-02 62 views
2

背景:为Django应用程序运行PostgreSQL数据库(Django 1.1.1,Python2.4,psycopg2和Postgres 8.1)我已经多次从SQL转储中恢复数据库。每次我这样做,然后尝试添加一个新行,无论是外壳,管理员或网站前端,我得到这个错误:Django ORM误读PostgreSQL序列?

IntegrityError: duplicate key violates unique constraint "app_model_pkey"

的数据转储是罚款,并重置序列。 但是,如果我尝试再次添加该行,则会成功!所以我可以尝试在每个表格中堵塞一个新的行,然后一切似乎都是一致的。

问题:鉴于(1)SQL转储是好的和Postgres正确阅读它(每earlier question),和(2)Django的ORM似乎并没有被失败的全身得到下一个值,这是怎么回事在这个特定的例子?

回答

1

Django不以任何方式持有或直接读取序列值。我已经解释过f.ex.在this question: 2088210/django-object-creation-and-postgres-sequences

即使操作的结果不成功,Postgresql也会在您尝试添加行时增加序列(引发重复键错误),序列增量不会回滚。所以,这就是第二次尝试添加一行时工作的原因。

我不知道为什么你的序列设置不正确,你可以检查转储前和恢复后的序列值是什么,并且对表中的max()pk做同样的处理?也许这是恢复的8.1错误?我不知道。我敢肯定:这不是Django的错。

+0

我想我明白为什么,但是这似乎是答案。我只有一个认证组,并且转储将该ID序列的当前值设置为1:'SELECT pg_catalog.setval('auth_group_id_seq',1,false);'。如果我尝试从该序列中选择nextval,它也是1. nextval的后续查询会将序列颠倒为2. – bennylope 2010-07-08 01:09:34

+0

这是不正确的; Django实际上是从PostgreSQL序列中获取值。如果启用数据库中所有语句的日志记录,则会看到Django发出了不少“SELECT CURRVAL('”app_table_id_seq“');'命令。事实上,如果你看看'django.db.models.sql.compiler.SQLInsertCompiler.execute_sql()'和'django.db.backends.postgresql.operations.DatabaseOperations.last_insert_id()'的代码,你会发现它在每个单独的INSERT命令之后取出序列值,除非'autocommit = True'。 – 2010-07-18 06:44:29

2

我猜你的序列已经过时。

可以解决这个问题是这样的:

select setval('app_model_id_seq', max(id)) from app_model;