ページの先頭行へ戻る
Enterprise Postgres 14 SP1 スケールアウト運用ガイド
FUJITSU Software

4.4.5 複数ノードをまたいだデッドロックの検知について

複数ノードにまたがる更新トランザクションを同時に実行した場合など、デッドロックが発生する場合があります。例えば、以下のような順番で更新を実施した場合にデッドロックが発生します。

1) トランザクション1が、データノード1上の行1を更新します。

2) トランザクション2が、データノード2上の行2を更新します。

3) トランザクション1が、データノード2上の行2を更新します。

4) トランザクション2が、データノード1上の行1を更新します。

3)でトランザクション1はトランザクション2が更新した行がCOMMITされるのを待ち、4)でトランザクション2はトランザクション1が更新した行がCOMMITされるのを待ちます。これはデッドロックです。

PostgreSQLには、デッドロックを自動で検出して一方を自動でエラーにする機能がありますが、この機能はデッドロックが同一ノード内で発生した場合に有効です。

上記のケースでは、データノード1上ではトランザクション2がトランザクション1を待っているだけで、データノード2上ではトランザクション1がトランザクション2を待っているだけです。つまり、各データノードではデッドロックが発生していないため、このようなデッドロックは自動で検出されません。デッドロックが検出されないことで、トランザクション1とトランザクション2は永久的に待たされることになります。この状態になった場合、pg_cancel_backend()などで一方のトランザクションを手動でキャンセルする必要があります。

この問題を解決するため、アプリケーションがノードをまたいだデッドロックを発生させる可能性がある場合には、各データノード上でlock_timeoutの機能を使用することによりデッドロックを解消してください。ロック獲得の待機時間がlock_timeoutで指定した時間を超えた場合にトランザクションがエラーになるため、ノードをまたがるデッドロックが発生した場合にも、自動でトランザクションをエラーにできます。ただし、デッドロックが発生していない場合でも指定した時間を超えて待機した場合にエラーになることに注意してください。

lock_timeoutをデータノード上のpostgresql.confに設定すると、データノードに接続するすべてのセッションに影響を与える可能性があるため推奨されません。下記のいずれかの方法を使用してください。