Как я могу гарантировать, что в Oracle работает только одна копия процедуры?

10

Нам необходимо убедиться, что в Oracle работает только одна копия определенной процедуры. Если он уже запущен, и пользователь пытается открыть другого, это должно привести к ошибке.

Какой лучший способ сделать это?

rfusca
источник

Ответы:

12

Вы можете сделать это с DBMS_LOCKпомощью эксклюзивного замка.

Смотрите следующую процедуру:

CREATE OR REPLACE PROCEDURE myproc
IS
  lockhandle VARCHAR2(128);
  retcode NUMBER;
BEGIN
  DBMS_LOCK.ALLOCATE_UNIQUE('myproclock',lockhandle);

  retcode:=DBMS_LOCK.REQUEST(lockhandle,timeout=>0, lockmode=>DBMS_LOCK.x_mode);

  IF retcode<>0
  THEN
    raise_application_error(-20000,'myproc is already running');
  END IF;

  /* sleep so that we can test with a 2nd execution */
  DBMS_LOCK.sleep(1000);

  retcode:=DBMS_LOCK.RELEASE(lockhandle);

END myproc;
/

Тест (сессия 1):

SQL> BEGIN
  2  myproc();
  3  END;
  4  /

(Очевидно, возвращается, когда DBMS_LOCK.sleep()возвращается).

Тест (сессия 2):

SQL> BEGIN
  2  myproc();
  3  END;
  4  /
BEGIN
*
ERROR at line 1:
ORA-20000: myproc is already running
ORA-06512: at "PHIL.MYPROC", line 12
ORA-06512: at line 2


SQL>

Очевидно, вам нужно GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;.

Philᵀᴹ
источник
2

Используйте таблицу блокировки.

Когда процедура начинается, проверьте в таблице известное значение, если оно присутствует, не переходите дальше и выходите из proc. Если нет, запишите значение в таблицу, выполните процедуру, затем удалите значение и выйдите как обычно.

Стюарт Мур
источник
Это хорошее решение для многих систем, но в этом особом случае Фил подходит лучше.
Дезсо
1

Когда у моих клиентов появляется запрос с уникальной бизнес-логикой, такой как этот, я пытаюсь перевернуть вопрос и спросить, зачем это нужно.

Лучший способ убедиться, что запущена только одна копия, - не дать пользователям вообще выполнить процедуру. Если эта процедура настолько особенная, то ее использование должно быть ограничено dba / developers.

Другой способ - запустить эту процедуру только как задание. Добавьте проверку в процедуру, чтобы увидеть, выполняются ли какие-либо задания, вызывающие это. Если это так, остановите дальнейшую обработку и зарегистрируйте вхождение.

kevinsky
источник