Logo Oracle Deutschland   DBA Community  -  Oktober 2013
Ereignisbenachrichtigung mit DBMS_ALERT im RAC
von Frank Großheim, Competence Center Oracle, IT-P GmbH

Das Built-In Package DBMS_ALERT, welches seit Oracle 8i verfügbar ist, unterstützt bei der asynchronen Verarbeitung von Datenbankereignissen zwischen mehreren Datenbanksessions. Eine Session, die über ein Ereignis (Alert) benachrichtigt werden möchte, registriert sich für den Empfang eines bestimmten Ereignisses und wartet anschließend. Eine zweite Session, die über ein Ereignis informieren möchte, löst das Ereignis über den Versand eines Signals aus. Das Package spielt seine Stärken insbesondere im Zusammenhang mit Triggern aus, indem zum Beispiel der Trigger das Ereignis-Signal mit der Prozedur DBMS_ALERT.SIGNAL auslöst, das dann wiederum eine wartende Session zu einer Aktion veranlasst.

Beispielsweise kann so eine Session über die von einer anderen Session durchgeführte Inhaltsänderung einer Tabelle informiert werden, ohne dass sie immerzu die Tabelle abfragen muss. Eine Session, die sich für den Empfang eines Ereignisses registriert hat (dbms_alert.register) und dann wartet (dbms_alert.register.waitone oder dbms_alert.register.waitany), präsentiert sich mit dem DBA im Oracle Wait Interface als "pipe get" Wait Event, welches zu der Kategorie der Idle Events zählt.


Abbildung 1: Schematischer Ablauf Single Instance

DBMS_ALERT im RAC-Betrieb

Die Besonderheit, auf die hier in dem Artikel eingegangen werden soll, ist das wenig bekannte Verhalten im RAC. Die Benachrichtigung zwischen den Sessions erfolgt bei einer Single-Instance-Datenbank nahezu in Echtzeit (ca. 10 ms). Anders verhält es sich im RAC-Betrieb. Befinden sich beispielsweise die signalisierende und die wartende Session auf unterschiedlichen Instanzen eines 2-Knoten-RAC, so verwendet Oracle ein Polling-Verfahren, bei dem die wartende Session in einem regelmäßigen Intervall die zweite Instanz nach aufgetretenen Events abfragt.

Das Polling-Intervall ist standardmäßig auf 5 Sekunden eingestellt. Dies hat zur Folge, dass die vorher in Echtzeit zur Verfügung stehenden Benachrichtigungen nun im ungünstigsten Fall bis zu 5 Sekunden benötigen. Die Laufzeit ist davon abhängig, zu welchem Zeitpunkt innerhalb des Intervalls das Event auftritt und variiert daher stark. Gemessen wurden, bei mehrfacher Wiederholung des im unteren Abschnitt beschriebenen Testcases, Werte im Bereich 0,1 bis 5 Sekunden.

Eine Applikation, die intensiv das DBMS_ALERT Package zum Austausch von Ereignissen nutzt, wird beim Wechsel von einer Single-Instance zum RAC teilsweise unter langen Laufzeiten zwischen Auftreten eines Ereignis und des Eintreffens dessen Benachrichtigung leiden.

Bei einer Performanceanalyse der Datenbank, ist dieses Problem durch den DBA nicht auf den ersten Blick zu erkennen, da die dabei auftretenden "get pipe"-Wait Events "Idle Events" sind und darüber hinaus kein Unterschied zu einem Single Instance-Betrieb festzustellen ist.

select sid, Username, wait_class, event, seconds_in_wait from v$session 
where username = 'APPUSER';

       SID USERNAME     WAIT_CLASS      EVENT           SECONDS_IN_WAIT
---------- ------------ --------------- --------------- ---------------
        52 APPUSER      Idle            pipe get                      3



Abbildung 2: Schematischer Ablauf im RAC

DBMS_ALERT.SET_DEFAULTS

Um das Problem zu mindern, lässt sich durch Verwendung der Prozedur DBMS_ALERT.SET_DEFAULTS in der wartenden Session das Polling-Intervall auf einen Minimalwert von 1 Sekunde reduzieren. Zwar werden damit keine Echtzeitwerte wie beim "Single-Instance-Betrieb" erreicht, möglicherweise hilft es jedoch die Gesamtperformance auf einen akzeptablen Wert zu anzuheben. Ein Herabsetzen auf einen Wert unterhalb einer Sekunde ist nicht möglich.

Reduzierung des Polling-Intervalls der wartenden Session auf 1 Sekunde:

         DBMS_ALERT.SET_DEFAULTS(1);
         

Die Prozedur kann entweder direkt in der Session oder innerhalb des PL/SQL Blocks, der DBMS_ALERT.REGISTER und DBMS_ALERT_WAITON aufruft, ausgeführt werden.

Laufzeiten RAC vs. Single Instance

Bei Betrachtung der zu erwartenden Laufzeiten wird schnell ersichtlich, dass DBMS_ALERT im RAC-Betrieb hinsichtlich der Performance beschränkt ist.

Session ASession BLaufzeitPolling Intervall
Single InstanceSingle Instanceca. 0,01 - 0,02 SekundenNicht relevant, da beide Sessions auf gleicher Instanz.
RAC Instance 1RAC Instance 1ca. 0,01 - 0,02 SekundenNicht relevant, da beide Sessions auf gleicher Instanz.
RAC Instance 1RAC Instance 2ca. 0,1 - 5 Sekunden5 Sekunden (Default)
RAC Instance 2RAC Instance 2ca. 0,1 - 1 Sekunde1 Sekunde (Minimum)


Testcase

Mit folgendem Testcase können die Zeiten ermittelt werden, die zwischen Signalisierung und Empfang liegen.

Vorbereitung

  • Applikationsbenutzer anlegen
  • CONNECT / as sysdba
    CREATE USER appuser IDENTIFIED BY appuserpw;
    GRANT CONNECT TO appuser;
    GRANT CREATE TABLE TO appuser;
    GRANT CREATE VIEW TO appuser;
    ALTER USER appuser QUOTA UNLIMITED ON USERS;
    GRANT EXECUTE ON dbms_alert TO appuser;
    


  • Zeittabellen und View anlegen anlegen
  • CONNECT appuser/appuserpw
    
    CREATE TABLE send_alert_table (no number, send_time timestamp);
    CREATE TABLE receive_alert_table (no number, receive_time timestamp);
    
    CREATE VIEW view_alert_elapse_time AS 
    SELECT s.no, to_char(send_time,'HH24:MI:SSXFF') SEND_TIME, 
    TO_CHAR(receive_time,'HH24:MI:SSXFF') RECEIVE_TIME, receive_time-send_time DURATION
    FROM send_alert_table s, receive_alert_table r 
    WHERE s.no = r.no
    ORDER BY no;
    


Ablauf
  • Session A registriert sich für das Ereignis "TESTEVENT" und wartet dann mittels Prozedur WAITONE auf das Signal. Wenn das Signal eintrifft, wird der aktuelle Zeitstempel in die Tabelle RECEIVE_ALERT_TABLE eingefügt und die Laufzeit ausgegeben. Wenn innerhalb von 60 Sekunden kein Signal eintrifft wird eine Timeout-Meldung ausgegeben und die Prozedur beendet sich.
  • CONNECT appuser/appuserpw
    
    SET SERVEROUTPUT ON
    DECLARE
      v_alert_msg VARCHAR2(1800);
      v_alert_status INTEGER;
      v_duration VARCHAR2(40);
    BEGIN
      --dbms_alert.set_defaults(1); -- Zum Herabsetzen auf 1 Sekunde Polling Intervall
      execute immediate 'truncate table send_alert_table';
      execute immediate 'truncate table receive_alert_table';
      dbms_alert.register('TESTEVENT');
      dbms_alert.waitone('TESTEVENT', v_alert_msg, v_alert_status, 60);
      IF v_alert_status = 1
        THEN
        dbms_output.put_line ('timed out');
      ELSE
        execute immediate 'insert into receive_alert_table values (1, SYSTIMESTAMP)';
        dbms_output.put_line('Received alert');
      END IF;
      dbms_alert.remove('TESTEVENT');
      select duration into v_duration from v_alert_elapse_time where no = 1;
      dbms_output.put_line('Duration: '|| SUBSTR(v_duration, 19) ||' seconds' );
    END;
    /
    


  • Session B löst das Ereignis "TESTEVENT" aus und schreibt den aktuellen Zeitstempel in die Tabelle SEND_ALERT_TABLE.
  • CONNECT appuser/appuserpw
    
    BEGIN
     dbms_alert.signal('TESTEVENT','Die ist eine Messaqe');
     execute immediate 'insert into send_alert_table values (1, SYSTIMESTAMP)';
     commit;
    END;
    /
    


  • Die Laufzeit wird anschließend in der Session A ausgegeben.
  • Received alert
    Duration: 4.399956 seconds
    


Fazit

Das Package DBMS_ALERT funktioniert grundsätzlich auch im RAC. Allerdings ist gegenüber dem Single Instance Betrieb aufgrund des eingesetzten Polling Verfahren mit Verzögerungen zu rechnen. Mit der Reduzierung des Polling-Intervalls mittels der Prozedur DBMS_ALERT.SET DEFAULT lassen sich allerdings diese Verzögerungen bis zu einem gewissen Grad reduzieren. Ist eine Applikation allerdings auf eine Echtzeitsynchronisation angewiesen, ist der Einsatz von DBMS_ALERT im RAC-Betrieb ungeeignet. Funktion ist zwar gegeben, aber Zeitverzögerungen müssen in Kauf genommen werden.

Nützliche Links und Referenzen

  • Online Documentation: Oracle Database PL/SQL Packages and Types Reference - DBMS_ALERT
  • Oracle Support Note 1012173.6: Using DBMS_ALERT To Notify Sessions Of Database Events
  • Oracle Support Note 67538.1: PACKAGE DBMS_ALERT Specification


  • Zurück zur Community-Seite

    (SoS)