Первичные ключи экземпляров модели Django не сбрасываются до 1 после удаления всех экземпляров

Я работал над автономной версией моего веб-приложения Django и часто удалял экземпляры модели для определенного ModelX.

Я сделал это со страницы администратора и не испытывал никаких проблем. Модель имеет только два поля: Имя и порядок и никаких других отношений с другими моделями.

новые экземпляры получают следующий доступный pk, который имеет смысл, и когда я удалил все экземпляры, добавление нового экземпляра дает pk=1, который я ожидать.

перемещение кода онлайн в мою фактическую базу данных я заметил, что это не так. Мне нужно было изменить экземпляры модели, поэтому я удалил их все, но, к моему удивлению, первичные ключи продолжали увеличиваться без сброса на 1.

вход в базу данных с помощью API Django, который я проверил, и старые экземпляры исчезли, но даже добавление новых экземпляров дает первичный ключ, который подбирает, где последний удаленный экземпляр остановился, а не 1.

интересно, знает ли кто-нибудь, что может быть проблемой здесь.

6 ответов


Как заявили другие, это полностью ответственность базы данных.

но вы должны понимать, что это желательно поведение. Идентификатор однозначно идентифицирует объект в базе данных. Таким образом, он должен относиться только к одной строке. Если эта строка впоследствии удаляется, нет причин, по которым вы должны хотеть, чтобы новая строка повторно использовала этот идентификатор: если вы это сделали, вы создадите путаницу между теперь удаленной сущностью, которая имела этот идентификатор, и недавно созданный, который использовал его повторно. Нет смысла делать это, и вы не должны хотеть делать так.


Я бы не назвал это проблемой. Это поведение по умолчанию для многих систем баз данных. В принципе, счетчик автоматического приращения для таблицы является постоянным, и удаление записей не влияет на счетчик. Фактическое значение первичного ключа не влияет на производительность или что-то еще, оно имеет только эстетическую ценность (если вы когда-либо достигнете предела в 2 миллиарда, у вас, скорее всего, будут другие проблемы).

Если вы действительно хотите переустановить счетчик, то вы можете упасть и воссоздать таблица:

python manage.py sqlclear <app_name> > python manage.py dbshell

или, если вам нужно сохранить данные из других таблиц в приложении, вы можете вручную сбросить счетчик:

python manage.py dbshell
mysql> ALTER TABLE <table_name> AUTO_INCREMENT = 1;

наиболее вероятная причина, по которой вы видите различное поведение в автономных и онлайн-приложениях, заключается в том, что значение автоматического приращения хранится только в памяти, а не на диске. Он пересчитывается как MAX(<column>) + 1 при каждом перезапуске сервера базы данных. Если таблица пуста,она будет полностью сброшена при перезапуске. Это, вероятно, очень часто для вашего автономная среда и близкая к нулю для вашей онлайн-среды.


вы действительно удалили их из своей базы данных или удалили их с помощью Django? Django не изменится AUTO_INCREMENT для вашей таблицы просто удалив строки из нее, поэтому, если вы хотите сбросить свои первичные ключи, вам, возможно, придется войти в свою БД и:

ALTER TABLE <my-table> AUTO_INCREMENT = 1;

(это предполагает, что вы используете MySQL или аналогичных).


нет никаких проблем, так работают базы данных. Django не имеет ничего общего с созданием идентификаторов, он просто говорит базе данных вставить строку и получает идентификатор в ответ от базы данных. Идентификатор начинается с 1 для каждой таблицы и увеличивается каждый раз при вставке строки. Удаление строк не приводит к возвращению идентификатора. Обычно вы не должны беспокоиться об этом, все, что вам нужно знать, это то, что каждая строка имеет уникальный идентификатор.
Конечно, вы можете изменить счетчик, который генерирует id для ваша таблица с командой базы данных, и это зависит от конкретной системы базы данных, которую вы используете.


Если вы используете SQLite, вы можете сбросить первичный ключ со следующими командами оболочки:

удалить из your_table; Удалить из SQLite_sequence, где name= 'your_table';


Я не уверен, когда это было добавлено, но следующая команда управления удалит все данные из всех таблиц и сбросит счетчики автоматического приращения до 1.

./manage.py sqlflush | psql DATABASE_NAME