その場合、カーソルでfor update nowait
を使用する必要があります。
for update nowait
を使用すると、行がビジーになり、コミットまたはロールバックが実行されるまでロックを取得します。ロックを取得しようとする他のセッションは、ロックの解放を待機する代わりに、ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
などのOracleエラーメッセージを取得します。
セッション1:
CURSOR abc_cur
IS
select * from dept where deptno =10 for update nowait;
ここでは、カーソルが閉じられるか、コミット/ロールバックが実行されるまで行がロックされます。一方、セッション2の別のユーザーが同じレコードにアクセスしようとすると、次のようにエラーがスローされます。
セッション2:
select * from dept where deptno =10 for update nowait;
このユーザーは、最初のセッションでロックされた同じレコードを更新または削除することさえできません。
ERROR at line 1:
`ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired`
使用法:特定のレコードセットに対して何らかの操作を行いたい場合、別のセッションの別のユーザーにデータを上書きさせたくない場合は、最初にレコードをロックする必要があります(for update nowait
)その後、操作を行います。操作が完了したら、カーソルを閉じてコミットします。
[〜#〜] edit [〜#〜] tempに10行あり、セッション1で次のスクリプトを実行するとします。
declare
cursor abc is select * from temp for update nowait;
temp abc%rowtype;
begin
open abc;
-- do slow stuff here
close abc;
commit;
end;
セッション2では、セッション1のスクリプトがまだ実行されている間に次を実行します
select * from temp;
10 rows found
セッション1のスクリプトがまだ実行中に、セッション2で同じスクリプトを実行した場合
declare
cursor abc is select * from temp for update nowait;
temp abc%rowtype;
begin
open abc;
-- do slow stuff here
close abc;
commit;
end;
次に、ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired instead of waiting the lock to release.
を取得します