Использование DBMS_PIPE.PACK_MESSAGE и DBMS_PIPE.SEND_MESSAGE в триггере - PullRequest
2 голосов
/ 02 мая 2020

Env: Oracle 12 c

Я смотрю на использование Oracle DBMS_PIPE в триггере таблицы, который будет использоваться многими пользователями. Триггер сработает только при обновлении STATUS, как показано ниже:

CREATE OR REPLACE TRIGGER MY_TRG  
AFTER UPDATE OF STATUS ON "MY_TABLE"  
REFERENCING NEW AS NEW OLD AS OLD  
FOR EACH ROW  
declare  
   v_status    INTEGER;  
begin      
    if :OLD.status = 'ERROR' and (:NEW.status = 'OK' or :NEW.status = 'ERROR') then  
       DBMS_PIPE.PACK_MESSAGE(:OLD.id_key);  
       DBMS_PIPE.PACK_MESSAGE(:NEW.status);  

       v_status := DBMS_PIPE.SEND_MESSAGE('MY_PIPE');  

       if v_status != 0 THEN  
         raise_application_error(num => -20002,msg => 'error message on trigger!');  
      end if;  
    end if;
  end;  

Следующий вызов будет инициирован из процесса страницы Oracle APEX, где он может быть снова отправлен несколькими пользователями.

DBMS_PIPE.receive_message(pipename => 'MY_PIPE', timeout  => 10);   

Мой вопрос заключается в том, что для каждого пользователя здесь необходимо убедиться, что ИМЯ ТРУБЫ указано c для каждого пользователя, чтобы они могли видеть только свои сообщения в своей ТРУБЕ или могли только одно имя канала 'MY_PIPE' обрабатывает все транзакции для нескольких пользователей?

Если в случае, когда каждому пользователю необходимо назначить свое ИМЯ ТРУБЫ, как мне это сделать, если SEND_MESSAGE('USER_1_PIPE') инициируется из триггера таблицы , который мой receive_message_pro c не будет знать об этом имени 'USER_1_PIPE'.

Мой канал создания выглядит так:

v_res := DBMS_PIPE.create_pipe(pipename => 'MY_PIPE', private => TRUE);  

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

1 Ответ

2 голосов
/ 04 мая 2020

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

Но, возможно, более серьезной проблемой является то, что канал не является транзакционным. Таким образом, в тот момент, когда срабатывает триггер, сообщение помещается в канал ... даже если эта транзакция позже откатывается, или происходит сбой, или что-то еще, что не обновляет статус окончательно. Кроме того, сообщение о конвейере будет отправлено ДО совершения транзакции. Другой сеанс (получающий это конвейерное сообщение) не сможет увидеть изменения, выполненные до тех пор, пока не произойдет фиксация, что может привести к несогласованности по времени.

Возможно, AQ (Advanced Queuing) является альтернативой, которую вы, возможно, захотите рассмотреть. Сообщения в очереди по умолчанию являются транзакционными, поэтому сообщение в очереди будет приятно привязано к тому, действительно ли ваши изменения в STATUS действительно успешны.

Вызывающее приложение просто прослушивает очередь, а не конвейерное сообщение.

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