web-dev-qa-db-ja.com

Djangoすべてのインスタンスが削除された後、モデルインスタンスの主キーが1にリセットされない

私は自分のDjango Webアプリのオフラインバージョンで作業しており、特定のModelXのモデルインスタンスを頻繁に削除しました。

私は管理者ページからこれを行い、問題は発生していません。モデルには、名前と順序の2つのフィールドのみがあり、他のモデルとの関係はありません。

新しいインスタンスには次に意味のある利用可能なpkが与えられます。すべてのインスタンスを削除したら、新しいインスタンスを追加するとpk = 1が得られます。

コードを実際のデータベースにオンラインで移動したところ、そうではないことに気付きました。モデルインスタンスを変更する必要があったので、すべて削除しましたが、驚いたことに、1にリセットせずに主キーを増やし続けました。

Django APIを使用してデータベースにアクセスすると、以前のインスタンスは削除されましたが、新しいインスタンスを追加しても、1つではなく最後に削除されたインスタンスが中断した場所を取得する主キーが生成されます。

誰かがここで問題になる可能性があることを知っているかどうか疑問に思っています。

24
pj2452

他の人が述べたように、これは完全にデータベースの責任です。

しかし、これは望ましいの動作であることを理解する必要があります。 IDは、データベース内のエンティティを一意に識別します。そのため、1行のみを参照する必要があります。その行が後で削除された場合、新しい行でそのIDを再利用する必要がある理由はありません。そうした場合、以前そのIDを持っていた削除済みエンティティと、それを再利用した新しく作成されたもの。これを行う意味はないので、実行する必要はありません。

21
Daniel Roseman

私はそれを問題とは呼びません。これは、多くのデータベースシステムのデフォルトの動作です。基本的に、テーブルの自動インクリメントカウンターは永続的であり、エントリを削除してもカウンターには影響しません。主キーの実際の値はパフォーマンスなどには影響せず、美的価値しかありません(20億の制限に達すると、他の問題が発生する可能性が高くなります)。

本当にカウンターをリセットしたい場合は、テーブルを削除して再作成できます。

_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として再計算されます。テーブルが空の場合、再起動時に完全にリセットされます。これはおそらくオフライン環境では非常に頻繁に発生し、オンライン環境ではほとんど発生しません。

23
knbk

実際にデータベースから削除しましたか、それともDjangoを使用して削除しましたか? Django変更されませんAUTO_INCREMENTテーブルから行を削除するだけなので、主キーをリセットする場合は、dbに移動して次の操作を行う必要があります。

ALTER TABLE <my-table> AUTO_INCREMENT = 1;

(これは、MySQLなどを使用していることを前提としています)。

3
xnx

問題はありません。それがデータベースの動作方法です。 Djangoは、IDの生成とは何の関係もありません。データベースに行を挿入し、データベースからの応答としてIDを取得するように指示するだけです。IDは、各テーブルで1から始まり、毎回増加します行を挿入します。行を削除しても、IDは元に戻りません。通常、そのことを気にする必要はありません。知っておく必要があるのは、各行に一意のIDがあることだけです。
もちろん、データベースコマンドを使用してテーブルのIDを生成し、使用している特定のデータベースシステムに依存するカウンターを変更できます。

3
nima

SQLiteを使用している場合は、次のシェルコマンドを使用して主キーをリセットできます。

Your_tableから削除します。 DELETE FROM SQLite_sequence WHERE name = 'your_table';

3
Juan Navarrete

これがいつ追加されたかはわかりませんが、次の管理コマンドはすべてのテーブルからすべてのデータを削除し、自動インクリメントカウンターを1にリセットします。

./manage.py sqlflush | psql DATABASE_NAME
0
Dan Loewenherz