Django ORM неправильно читает последовательности PostgreSQL?

Предыстория: запуск базы данных PostgreSQL для приложения Django (Django 1.1.1, Python2.4, psycopg2 и Postgres 8.1). Я несколько раз восстанавливал базу данных из дампа SQL. Каждый раз, когда я делаю это, а затем пытаюсь добавить новую строку, будь то оболочка, администратор или внешний интерфейс сайта, я получаю эту ошибку:

IntegrityError: duplicate key violates unique constraint "app_model_pkey"

Дамп данных в порядке и сбрасывает последовательности. Но если я попытаюсь добавить строку еще раз, все будет успешно! Так что я могу просто попробовать втиснуть новую строку в каждую таблицу, и тогда все будет выглядеть как единое целое.

Вопрос: Учитывая, что (1) дамп SQL в порядке и Postgres правильно его считывает (согласно предыдущий вопрос), и (2) ORM Django, похоже, не дает системных сбоев при получении следующих значений, что происходит в данном конкретном случае?


person bennylope    schedule 02.07.2010    source источник


Ответы (2)


Django никоим образом не хранит и не считывает значения последовательности. Я объяснил это напр. в этот вопрос: 2088210/django-object-creation-and-postgres-sequences.

Postgresql увеличивает последовательность, когда вы пытаетесь добавить строку, даже если результат операции неуспешен (возникает ошибка дублирования ключа), приращение последовательности не откатывается. Вот почему он работает во второй раз, когда вы пытаетесь добавить строку.

Я не знаю, почему ваши последовательности не установлены должным образом, не могли бы вы проверить, каково значение последовательности до дампа и после восстановления, и сделать то же самое с max() pk таблицы? Может это баг 8.1 с восстановлением? Я не знаю. В чем я уверен: это не вина Джанго.

person zalew    schedule 05.07.2010
comment
Хотел бы я понять, почему, но это, кажется, ответ. У меня была только одна группа авторизации, и дамп устанавливает текущее значение последовательности этого идентификатора в 1: SELECT pg_catalog.setval('auth_group_id_seq', 1, false);. Если я попытаюсь выбрать nextval из этой последовательности, это также будет 1. Последующий запрос для nextval увеличивает последовательность до 2. - person bennylope; 08.07.2010
comment
Это неправильно; На самом деле 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. - person Aram Dulyan; 18.07.2010

Я предполагаю, что ваша последовательность устарела.

Вы можете исправить это следующим образом:

select setval('app_model_id_seq', max(id)) from app_model;
person Wolph    schedule 05.07.2010