web-dev-qa-db-ja.com

Postgresが既に使用されているPK値を生成するのはなぜですか?

私はDjangoを使用していますが、時々このエラーが発生します。

IntegrityError:重複するキー値が一意制約「myapp_mymodel_pkey」に違反しています
詳細:キー(id)=(1)はすでに存在します。

私のPostgresデータベースには、実際にはmyapp_mymodelオブジェクトがあり、主キーは1です。

なぜPostgresはその主キーを再び使用しようとするのですか?または、これはおそらく私のアプリケーション(またはDjangoのORM)が原因ですか?

この問題は今、さらに3回続けて発生しました。私が見つけたのは、doesが発生すると、指定されたテーブルの行で1回以上発生し、その後は発生しないことです。それは、数日間完全に停止する前に、すべてのテーブルで発生するようです。発生するテーブルごとに少なくとも1分程度発生し、断続的にのみ発生します(すべてのテーブルがすぐに発生するわけではありません)。

このエラーが断続的に発生する(2週間で3回程度発生する-DBに他の負荷がかからない、アプリケーションをテストするだけである)という事実が、低レベルの問題に非常に警戒しています。

27
orokusaki

PostgreSQLは独自に重複する値を挿入しようとはしません。それはあなた(あなたのアプリケーション、ORMを含む)が行うことです。

これは、誤った位置に設定されたPKと、nextval()に等しい値がすでに含まれているテーブルに値を供給するシーケンスであるか、または単にアプリケーションが間違ったことを行っている可能性があります。最初のものは修正が簡単です:

SELECT setval('your_sequence_name', (SELECT max(id) FROM your_table));

2番目はデバッグを意味します。

Django(またはその他の一般的なフレームワーク)は、それ自体でシーケンスをリセットしません。それ以外の場合、1日おきに同様の質問が出されます。

36
dezso

最も可能性が高いのは、シリアル列シーケンス値が更新されていない行をテーブルに挿入することです。

Django postgresのORMで定義された主キーであるテーブルの次の列を検討してください。

id serial NOT NULL

デフォルト値が設定されている人

nextval('table_name_id_seq'::regclass)

シーケンスは、idフィールドが空白に設定されている場合にのみ評価されます。しかし、すでにテーブルにエントリがある場合、それは問題です。

質問は、これらの以前のエントリがシーケンスの更新をトリガーしなかった理由ですか?これは、以前のすべてのエントリにid値が明示的に指定されていたためです。

私の場合、それらの初期エントリは、移行によってフィクスチャから読み込まれました。

この問題は、ランダムなPK値を持つカスタムエントリを介してトリッキーになることもあります。

たとえば、テーブルには10のエントリがあります。 PK = 15で明示的なエントリを作成します。コードを介した次の4つの挿入は完全に正常に機能しますが、5番目の挿入は例外を発生させます。

DETAIL: Key (id)=(15) already exists.
8
Abhishek

私はここで非常に同じエラーで終わりましたが、めったに発生せず、追跡するのが困難でした。

障害は、POSTをサーバーに2回行っていたJSの繰り返しでした!したがって、Django(または他の任意のWebフレームワーク)ビューとフォームだけでなく、最前面で何が起こるか。

4
andilabs

うん変なこと。私の場合、移行でデータをロードしているときに明らかに何かが間違っています。空の移行を追加し、いくつかの初期データを追加するように行を書きました。私の場合は6レコードです。

db_alias = schema_editor.connection.alias
bulk = []
for item in items:
    bulk.append(MyModel(
        id=item[0],
        value=item[1],
        slug=item[2],
        name=item[3],
    ))

MyModel.objects.using(db_alias).bulk_create(bulk)

次に、管理パネルで新しいアイテムを追加しようとしましたが、

最初の試み:

DETAIL:  Key (id)=(1) already exists.

その後の試み:

DETAIL:  Key (id)=(2) already exists.
DETAIL:  Key (id)=(3) already exists.
DETAIL:  Key (id)=(4) already exists.
DETAIL:  Key (id)=(5) already exists.
DETAIL:  Key (id)=(6) already exists.

そして最後に7日と時間にすべてが成功しています

そこで、6つの項目をロードしたときに、bulk_createに関連する何かがあると言っています。 Djangoプロジェクトが原因である可能性があります。

Django 1.9 PostgreSQL 9.3.14

1