9

行がOracleで更新のためにロックされているかどうかをテストできる方法はありますか?

例として、次のクエリが 1 人のユーザーによって実行されたとします。

select * from SOME_TABLE where THE_ID = 1000 for update;

THE_ID = 1000別のユーザーで、行がロックされているかどうかを確認したい。更新などを試みると、2 番目のユーザーがブロックされ、待機したままになります (それは望ましくありません)。

また、2 番目のユーザーで次のクエリを実行してみました。

select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT;

同じ行に 2 つのロックを配置できないため、これは失敗します。そして、そうです。「ORA-00054: リソースがビジーで、NOWAIT 指定エラーで取得します」というメッセージが表示されます。ロックの存在を確認するためにこのエラーを常に当てにすることはできますか、または行がロックされているかどうかを判断するためのより簡単でクリーンな方法はありますか?

ありがとうございました!

4

2 に答える 2

16

FOR UPDATE NOWAIT を使用してプロシージャを記述し、行がロックされているときにエラー メッセージを返すことができます。

SQL> CREATE OR REPLACE PROCEDURE do_something(p_id NUMBER) IS
  2     row_locked EXCEPTION;
  3     PRAGMA EXCEPTION_INIT(row_locked, -54);
  4  BEGIN
  5     FOR cc IN (SELECT *
  6                  FROM some_table
  7                 WHERE ID = p_id FOR UPDATE NOWAIT) LOOP
  8        -- proceed with what you want to do;
  9        NULL;
 10     END LOOP;
 11  EXCEPTION
 12     WHEN row_locked THEN
 13        raise_application_error(-20001, 'this row is locked...');
 14  END do_something;
 15  /

Procedure created

それでは、2 つのセッションで小さな例を作成しましょう。

session_1> select id from some_table where id = 1 for update;

        ID
----------
         1

session_2> exec do_something(1);

begin do_something(1); end;

ORA-20001: this row is locked...
ORA-06512: at "VNZ.DO_SOMETHING", line 11
ORA-06512: at line 2

session_1> commit;

Commit complete

session_2> exec do_something(1);

PL/SQL procedure successfully completed
于 2009-10-15T12:46:23.333 に答える
1

シンプルでもクリーンでもありませんが、V$LOCKおよびV$SESSIONビューで情報を入手できます。

ただし、通常のアプリケーション コードの一部としてこのようなものを使用する必要がある場合は、もう一度考える必要があります。アプリケーションは、データベースがロックを行う方法を気にする必要はありません。デッドロックが発生している場合は、クエリを再構築してデッドロックが発生しないようにする必要があります。

于 2009-10-15T12:34:31.967 に答える