Является ли вставка и соответствующий триггер вызовом атомарного процесса? - PullRequest
0 голосов
/ 11 января 2019

У меня есть таблица с именем LOCK, и я хочу убедиться, что существует не более одной строки с данным именем и типом WRITE. Хотя допускается несколько строк с типом READ и одинаковым именем, но только если нет строки с таким же именем и типом WRITE.

create table "LOCK"
(
    "LOCK_ID" NUMBER(19,0) NOT NULL,
    "NAME" VARCHAR2(255 CHAR),
    "TYPE" VARCHAR2(32 CHAR),
    CONSTRAINT "SYS_LOCK_PK" PRIMARY KEY ("LOCK_ID")
);

Вставка строки должна быть атомарной, например, нет запроса с последующей вставкой в ​​зависимости от результата запроса (потому что он мог измениться за это время).

Чтобы обеспечить атомизацию, я создал триггер для проверки первоначально упомянутого условия (повышение ошибки при сбое), которое иногда заканчивается различными недопустимыми состояниями, такими как две строки WRITE.

Если вставки выполняются последовательно, триггер работает отлично, что приводит к предположению, что вставка + триггер не является атомарным процессом, и если так, есть ли безопасный способ решить мою проблему?

Вот триггер:

create or replace trigger "LOCK_TRIGGER"
before insert on "LOCK" 
referencing NEW AS NEW
for each row
declare
    c   integer := 0;
begin
    select count(*) into c from "LOCK" where (:NEW.typ = 'WRITE' and name = :NEW.name) or (:NEW.typ = 'READ' and name = :NEW.name and typ = 'WRITE');
    if (c > 0) then
        raise_application_error(-20634, 'Nope!');
    end if;
end;

1 Ответ

0 голосов
/ 11 января 2019

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

  1. получает пользовательскую блокировку для входящего имени - эта блокировка должна создаваться с возможностью, чтобы она не снималась при фиксации / откате
  2. делает проверку в таблице для имени
  3. вставляет запись, если это возможно (если проверка прошла успешно) и фиксирует ее
  4. освобождает пользовательский замок
  5. возвращает результат (либо OK, либо NOK)

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...