我有一个运行进程的应用程序,我只希望一次运行一个进程.一些选项是:
使用对象锁定可防止后续进程运行.
这没关系,但我希望调用会话立即返回,而不是等待正在运行的会话完成.
使用自定义Y/N设置进程是否正在运行.
我在进程开始时设置了一个"Y"标志,并在完成或失败时将其设置为"N".也很好,但感觉我正在重新发明轮子,感觉不像是要走的路.如果运行会话被杀死,因为标志保持在"Y",它也会失败.
使用 dbms_application_info.set_module
这种方法看起来最强大,但如果我知道现有的运行进程,我认为我需要能够查询v$session,我不希望这个应用程序具有如此广泛的访问权限.
有任何想法吗?
选项4:使用DBMS_LOCK序列化访问.以下是文档的链接:http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10577/d_lock.htm#i1002556
一个例子:
首先创建一个辅助过程来序列化对某个过程的访问.该过程使用过程的名称来生成唯一的锁定句柄.'NOTORA $'确保锁名不以'ORA $'开头,因为它们是为Oracle保留的.
SQL> create procedure serialize_access (p_procedure_name in varchar2)
2 is
3 l_lockhandle varchar2(128);
4 l_return integer;
5 begin
6 dbms_lock.allocate_unique
7 ( lockname => 'NOTORA$' || p_procedure_name
8 , lockhandle => l_lockhandle
9 );
10 l_return := dbms_lock.request
11 ( lockhandle => l_lockhandle
12 , lockmode => dbms_lock.x_mode
13 , timeout => 0 -- do not wait
14 , release_on_commit => true
15 );
16 if l_return = 1
17 then
18 raise_application_error
19 ( -20000
20 , 'Someone else is running this procedure, so you''ll have to wait'
21 );
22 end if;
23 end serialize_access;
24 /
Procedure created.
Run Code Online (Sandbox Code Playgroud)
在您的过程中调用此serialize_access过程,如下所示:
SQL> create procedure p1
2 is
3 begin
4 serialize_access('p1');
5 dbms_lock.sleep(30);
6 end;
7 /
Procedure created.
Run Code Online (Sandbox Code Playgroud)
其中dbms_lock.sleep用作实际代码的替代品.现在打开两个或更多其他会话并发出"exec p1"命令.第一节将以等待30秒开始.第二场会议将向您展示:
ERROR at line 1:
ORA-20000: Someone else is running this procedure, so you'll have to wait
ORA-06512: at "[schema].SERIALIZE_ACCESS", line 18
ORA-06512: at "[schema].P1", line 4
ORA-06512: at line 1
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
问候,Rob.