1

Postgres 9.1 を使用しています。同じトランザクションで複数の SELECT FOR UPDATES を使用すると、競合状態が発生する可能性があるかどうか疑問に思っています。

2 つの同時トランザクション:

トランザクション 1: テーブル 1 の更新を選択 -- ロックを正常に取得

トランザクション 2: テーブル 2 の更新を選択 -- ロックを正常に取得

トランザクション 2: テーブル 1 の更新を選択 -- トランザクション 1 からのロック解放を待機

トランザクション 1: テーブル 2 の更新を選択 -- トランザクション 2 からのロック解放を待機

この状況ではどうなりますか?待機中のトランザクションの 1 つが最終的にタイムアウトしますか? もしそうなら、タイムアウト期間を設定する方法はありますか?

編集:deadlock_timeout は私が探している構成ですか?

4

2 に答える 2

2

deadlock_timeoutはい、ドキュメントでを探す必要があります。

ただし、シナリオはデッドロックが発生することを意味するものではありません。'cosPostgreSQLは行レベルのロックを使用しており、トランザクションが同じ行に対して一致しているかどうかは明確ではありません。

もう1つのオプションは、デフォルトREAD COMMITTEDよりも高いシリアル化レベルを使用することです。ただし、この場合、アプリケーションは次の例外を受け取る準備ができている必要がありますSQLCODE=40001

ERROR:  could not serialize access due to concurrent update

これは予想されることです。そのままトランザクションを再試行する必要があります。

ウィキで見つけることができるシリアル化可能な分離レベルの非常に優れた概要。

于 2013-02-16T19:50:47.320 に答える
1

PostgreSQL はステップ 4 でデッドロックを検出し、トランザクションに失敗します。試してみたところ、次のようになりましたpsql(ステップ4のみを表示):

template1=# SELECT * FROM table2 FOR UPDATE;
ERROR:  deadlock detected
DETAIL:  Process 17536 waits for ShareLock on transaction 166946; blocked by process 18880.
Process 18880 waits for ShareLock on transaction 166944; blocked by process 17536.
HINT:  See server log for query details.
template1=# 

これは、デフォルトのタイムアウトである 1 秒後に発生します。他の回答には、これに関する詳細情報があります。

于 2013-02-16T19:44:26.567 に答える