DBMS_ALERT - работа в RAC

На нашем семинаре RAC DD4D мы говорили о том, что пакет DBMS_ALERT не работает в RAC, но выяснилось что эта информация уже устарела, то есть сейчас это не так, и в настоящий момент в 10gR2 RAC и 11gR1 RAC указанный пакет полностью работоспособен! Спасибо за детальную информацию Тузову С.И. (ОАО "Россельхозбанк")!

Небольшой testcase демонстрирует это.
Подключаемся к четвертому узлу и регистрируем наш сигнал.

conn system/oracle@racdb4
set serveroutput on

declare
v_xMessage varchar2(1800);
v_xStatus number;
begin
dbms_output.put_line('Connected to node => ' dbms_utility.current_instance);

dbms_alert.register('MyAlert');

dbms_alert.waitone(name => 'MyAlert',
message => v_xMessage,
status => v_xStatus,
timeout => dbms_alert.maxwait);

if (v_xStatus = 0) then
dbms_output.put_line('Message recieved: ' v_xMessage);
else
dbms_output.put_line('Message NOT recieved: ');
end if;
end;
/


Сессия зависает, бесконечно ожидая сигнала... Открываем сессию на первый узел кластера, и пошлем сигнал:

conn system/oracle@racdb1
set serveroutput on

begin
dbms_output.put_line('Connected to node => ' dbms_utility.current_instance);
dbms_alert.signal('MyAlert','Hello World!');
commit;
end;
/

Соединено.
Connected to node => 1

Процедура PL/SQL успешно завершена.

В этот момент зависшая сессия на четвертом узле магически оживает:

Connected to node => 4
Message recieved: Hello World!

Процедура PL/SQL успешно завершена.

Как вы видите: сигнал созданный на первом узле, был доступен подписчику на другом узел. Более детальный анализ показывает что в процессе работы с DBMS_ALERT мспользуется системная табличка DBMS_ALERT_INFO. В момент регистрации на сигнал (вызов dbms_alert.register) трассировочный файл содержит следующие вызовы:

DELETE FROM DBMS_ALERT_INFO
WHERE
SID = :B1

COMMIT;

SELECT DISTINCT SUBSTR(KGLNAOBJ,11) SID
FROM
X$KGLOB WHERE KGLHDNSP = 7 AND KGLNAOBJ LIKE 'ORA$ALERT$%' AND
BITAND(KGLHDFLG,128)!=0 UNION SELECT DISTINCT SID FROM DBMS_ALERT_INFO

DELETE DBMS_ALERT_INFO
WHERE
SID = :B1

INSERT INTO DBMS_ALERT_INFO
VALUES
(UPPER(:B2 ), :B1 , 'N', NULL)


Ну и при создании сигнала, снова видна интенсивная работа с таблицей DBMS_ALERT_INFO:

UPDATE DBMS_ALERT_INFO SET CHANGED = 'Y', MESSAGE = :B2
WHERE
NAME = UPPER(:B1 )

SELECT SID
FROM
DBMS_ALERT_INFO WHERE NAME = UPPER(:B1 )

Понятно, что если вы интенсивно используете пакет DBMS_ALERT, то при переходе в RAC таблица DBMS_ALERT_INFO мгновенно становится "горячей". Поэтому в целом, наше утверждение и workaround-ы относительно пакета DBMS_ALERT остаются в силе ! Проверка на использование пакета DBMS_ALERT все-таки была оставлена в утилите RACChecker

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

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