Seit Oracle 10g kann man über die View sys.x$dbgalertext die alert.log auslesen. Diese stellt aber nur die Zeilen derjenigen alert.log zur Verfügung, die auf dem Server lesbar ist, an dessen Instance man angemeldet ist. Wie kann man nun aber in einem RAC – Umfeld alle alert.log gleichzeitig auslesen, obwohl man in der Regel nur an einer Instance angemeldet ist?
Angenommen, es existiert bereits eine View „v_dbalertlog“, über die man allen Usern das Leserecht über eine Rolle auf diese interne View zugewiesen hat. Dann kann jeder angemeldete User die „lokale“ alert.log“ auslesen.
1 2 3 4 5 6 7 8 9 | CREATE OR REPLACE FORCE VIEW SYS.V_ALERTLOG AS SELECT * FROM sys.v_x$dbgalertext x WHERE x.COMPONENT_ID = 'rdbms'; CREATE ROLE ROLE_ALERTLOG; GRANT SELECT ON SYS.V_ALERTLOG TO PUBLIC; CREATE PUBLIC SYNONYM V_ALERTLOG FOR SYS.V_ALERTLOG; |
Doch wie liest man nun im RAC – Umfeld mit zwei oder mehr laufenden Instanzen alle zugehörigen alert.log aus?
Die hier vorgestellte Lösung wurde von John Beresniewicz
auf der UKOUG Conferenz 2011 schon vorgestellt:
Anstelle einfach ein
1 2 3 | SELECT * FROM V_ALERTLOG ORDER BY ORIGINATING_TIMESTAMP; |
wird dies – auf den ersten Blick – sehr umständlich erweitert zu:
1 2 3 | SELECT * FROM TABLE(GV$(CURSOR(SELECT * FROM V_ALERTLOG))) ORDER BY ORIGINATING_TIMESTAMP; |
Was bewirkt dies:
Durch den GV$(CURSOR(…)) wird das im innern befindliche Statement auf allen Instancen ausgeführt und an den Query Coordinator (QC) zurückgeliefert, der dann das Ergebnis in der aktuellen Session zusammenfasst.
Wenn man auf der DB eingeschränkt ist und keine Rechte hat, eine View anzulegen, so kann man dies auch direkt so ausführen lassen:
1 2 3 4 5 6 7 | SELECT TO_CHAR (originating_timestamp, 'DD.MM.YYYY HH24:MI') date_and_time, inst_id, MESSAGE_TEXT FROM TABLE(GV$(CURSOR(SELECT * FROM sys.v_x$dbgalertext x WHERE x.COMPONENT_ID = 'rdbms')) ) ORDER BY ORIGINATING_TIMESTAMP |