Вариант 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.
В вашей процедуре вызовите эту процедуру serialize_access следующим образом:
SQL> create procedure p1
2 is
3 begin
4 serialize_access('p1');
5 dbms_lock.sleep(30);
6 end;
7 /
Procedure created.
Где 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
Надеюсь, это поможет.
С уважением,
Роб.