2

私は興味があります、その小さな問題を回避するためのベストプラクティスは何ですか:)

2 つのクライアントを取り上げてみましょう。どちらも一意の制約を使用してテーブルに行を挿入しようとしています。
「url」列だとします。

ある時点で、次のような状況が発生することがあります。
  1) クライアント A は、テーブルに URL "a" があるかどうかを確認します
  2) クライアント A は、その URL がないという回答を取得します
  3) クライアント A は、URL "a" を挿入しようとしています
  4) クライアント B は、テーブルに URL "a" があるかどうかを確認します
  5) クライアント B は、その URL がないという回答を取得します
  6) クライアント A は、URL "a"を挿入しました
  7) クライアント B は、URL "a" を挿入しようとしています。しかし、重複キーエラーが発生します

それを回避する最善の方法は、アプリケーションレベルで再試行することです。

4

2 に答える 2

2

トランザクションの開始時に明示的なロックを取得することでエラーを回避できますが、同時実行性とスループットが低下する可能性があります。

http://www.postgresql.org/docs/current/interactive/explicit-locking.html

同時試行をブロックしない場合は、何らかの方法で再試行に対処する必要があります。そのロジックをアプリケーション コードに入れるのではなく、関数内にカプセル化できます。ロジックは、merge_db() の例に似ています。

http://www.postgresql.org/docs/current/interactive/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING

于 2012-05-04T12:39:23.900 に答える
1

SERIALIZABLE 分離レベルで実行すると、クライアント B は URL の値が返される前に、A のトランザクションが完了するまで待機する必要があります。この値はまだ存在しないため、レコードにロックを設定することはできません (レコードがありません)。そのため、インデックスのギャップ ロックが代わりに使用されます。しかし、@kgrittn が述べたように、これはパフォーマンスと同時実行性に悪影響を及ぼします。したがって、重複キーエラーを処理する方が良いです

于 2012-05-04T12:48:35.343 に答える