5

アプリケーションで断続的にデッドロックが発生します。私のアプリケーションには EMPLOYEE (ID (PK), NAME, SAL) などの 1 つのテーブルがあり、2 つのセッションがあります。

セッション 1:

SELECT ID, NAME, SAL FROM EMPLOYEE WHERE SAL = (SELECT MIN(SAL) FROM 
EMPLOYEE) FOR UPDATE
Let say the query return EMPLOYEE ROW having ID=2
then application does some processing like rs.updateInt(ID_SAL, 10);

セッション 2: (その他のビジネス ロジック用)

SELECT ID, NAME, SAL FROM EMPLOYEE WHERE ID=2 FOR UPDATE.

したがって、アプリケーションでは、両方のセッションが同じ行を更新しようとします (例では ID=2 の行)。このような状況は予想されるため、SELECT .. FOR UPDATE が役立つと考えました。

私は何か間違ったことをしていますか?SELECT FOR UPDATE が行をロックし、他のセッションが同じ行を更新しようとすると、セッション 1 の実行が完了するまで待機すると想定しています。

4

1 に答える 1

10

SELECT FOR UPDATE が行をロックし、他のセッションが同じ行を更新しようとすると、セッション 1 の実行が完了するまで待機すると想定しています。

まさにそうです。ただし、この行を終了するか、セッションを閉じると、トランザクションを閉じる必要があります。問題の考えられる状況は次のとおりです。

プロセス 1 は ID=2 の行をロックし、それを更新して ID=1 の次のレコードに進みます (ただし、セッションとトランザクションはまだアクティブです) プロセス 2 は ID=1 の行を既にロックしており、ID=2 の行をロックしようとしています (ただし、セッションとトランザクションはまだアクティブです)。セッションとトランザクションはまだアクティブです)

したがって、プロセス 1 はレコード ID=1 を待機し、レコード ID=2 を保持します。

プロセス 2 はレコード ID=2 を待機しており、レコード ID=1 を保持しています

これはデッドロックです。他のプロセスのためにレコードを解放するには、レコードの作業が終了した後にトランザクションを完了する必要があります。

1 つのトランザクションで複数のレコードを更新する必要がある場合は、それらをまとめてロックし、作業が終了したら解放します。

于 2013-10-11T18:02:19.910 に答える