пятница, 13 декабря 2013 г.

Пользовательская блокировка в PLSQL Oracle (DBMS_LOCK)

Проблема

Предположим у нас есть PLSQL-функция записи в файл на диске. И есть функция удаления файла (например, чтобы начать записывать в новый). Значит во время удаления, ни одна другая сессия не должна писать в файл.

"Старое" решение

Можно сделать LOCK-таблицу с одним полем-PK, и при входе в функцию делать туда insert c константным ключём. Если вставка удачна, то выполняем код в самой функции и в конце строку из LOCK-таблицы. Любая другая сессия в это время при попытке вставки получит exception, который будет означать, что функция "заблокирована"

"Новое" решение

С некоторых пор (точно не знаю когда, но в 10-ке уже было), в БД Oracle появился пакет DBMS_LOCK, который предоставляет возможность блокировок в обычном программном ключе. Там есть возможности ожидания, shared и exclusive блокировок, ну и всё что в такого рода механизме должно быть.
Для нашего примера всё достаточно просто:

function turnFile return integer is
    lockId             varchar2(30);
    lockCode           number;
begin
    --выделена блокировка
    DBMS_LOCK.allocate_unique('MY_LOCK_NAME', lockId);
    --  запрошена блокировка в исключительном режиме (0)
    lockCode := DBMS_LOCK.request(lockId, dbms_lock.x_mode, 0);
    -- если захватить не удалось, то выходим, очищая попытку блокировки
    if lockCode <> 0 then
      lockCode := DBMS_LOCK.release(lockId);
      return;
    end if;
    
    -- что-то сделаем с файлом
    ...
    
    -- снять блокировку 
    lockCode := DBMS_LOCK.release(lockId);
exception
    when others then
      -- снять блокировку, если что-то пошло не так
      lockCode := DBMS_LOCK.release(lockId);    
end turnFile;

Комментариев нет:

Отправить комментарий