一度に 1 つずつ実行するプロシージャがあります。つまり、プロシージャが他のプロセス/ユーザーを実行しているとき、同じプロシージャを実行できないはずです。
プロシージャが実行された後、次に実行できるようになったときのみ
助けてください
プロシージャの実行をシリアル化するには、dbms_lock
パッケージ、具体的allocate_unique()
にはそのパッケージのrelease()
プロシージャとrequest()
関数を使用できます。以下は、ロック取得プロセスを規制するパッケージを作成する例です。
パッケージの仕様
create or replace package proc_lock as
function request_lock( p_lock_name in varchar2) return varchar2;
procedure release_lock(p_l_handle in varchar2);
end;
パッケージ本体
create or replace package body proc_lock as
function request_lock( p_lock_name in varchar2) return varchar2
is
l_request number;
l_lock_handle varchar2(1000);
begin
dbms_lock.allocate_unique(p_lock_name, l_lock_handle);
-- waits 5 sec trying to acquire a lock
l_request := dbms_lock.request(l_lock_handle, timeout=>5);
if l_request <> 0
then
raise_application_error(-20001, 'Lock cannot be acquired.');
end if;
return l_lock_handle;
end;
procedure release_lock(p_l_handle in varchar2)
is
begin
if dbms_lock.release(p_l_handle) > 0
then
raise_application_error(-20000, 'Cannot release lock');
end if;
end;
end;
シリアル化する必要がある簡単な手順を次に示します。
create or replace procedure test_proc
is
l_handle varchar2(1000); -- lock handle
begin
-- trying to acquire a lock
l_handle := proc_lock.request_lock('test');
-- here goes all usefull work that this procedure
-- would do if lock acquired successfully
dbms_output.put_line('procedure is working');
-- mimic large amount of work
dbms_lock.sleep(10);
dbms_output.put_line('procedure is done');
-- release the lock after work is done
proc_lock.release_lock(l_handle);
end;
テストケース:
--Session #1
SQL> exec test_proc;
--Session #2 at the same time
SQL> exec test_proc;
BEGIN test_proc; END;
*
ERROR at line 1:
ORA-20001: Lock cannot be acquired.
ORA-06512: at "HR.PROC_LOCK", line 11
ORA-06512: at "HR.TEST_PROC", line 6
ORA-06512: at line 1
--Session #1
SQL> exec test_proc;
procedure is working
procedure is done
PL/SQL procedure successfully completed.
詳しくはdbms_lock
パッケージをご覧ください。