Teil 9: Server Errors protokollieren
Nicht immer ist es leicht heraus zu finden, was die Ursache für einen Applikationsfehler war. Sehr oft unterdrücken Applikationen die Oracle Fehlermeldung oder verstümmeln diese so, was eine Fehleranalyse erschwert bis unmöglich macht. Da wäre es natürlich hilfreich, wenn man nachsehen könnte, welcher Oracle-Fehler wirklich aufgetreten ist.
Das gelingt mit einer Tabelle, in der alle Server Errors protokolliert werden, zusammen mit einem Database Event Trigger, der im Fall eines Server Errors diese Tabelle mit Informationen befüllt.
Anlegen der Strukturen
Im folgenden Beispiel wird eine Tabelle für die Server Errors in einem passenden Schema angelegt (bitte nicht im SYS Schema!) - in unseren Beispiel unter SYSTEM. Wenn es ein anderes Schema sein soll, bitte nicht auf das Anpassen des Triggers vergessen!
/* Die Tabelle sollte nicht unter SYS angelegt werden, daher SYSTEM. Es geht aber auch ein anderer Datenbank Benutzer */
DROP TABLE system.server_errors purge;
CREATE TABLE system.server_errors
(zeitpunkt date
,error number
,error_msg varchar2(128)
,login_user varchar2(128)
,obj_owner varchar2(128)
,obj_name varchar2(128)
,sql_text clob)
TABLESPACE sysaux;
/* Der Trigger muss unter SYS angelegt werden */
CREATE OR REPLACE TRIGGER sys.server_errors
AFTER SERVERERROR ON DATABASE
DECLARE
p_sqltxt clob;
p_sql_text ora_name_list_t;
BEGIN
FOR i IN 1 .. ora_sql_txt(p_sql_text)
LOOP
p_sqltxt := p_sqltxt || p_sql_text(i);
END LOOP;
INSERT INTO system.server_errors
(zeitpunkt, error, error_msg, login_user, obj_owner, obj_name, sql_text )
VALUES (sysdate, ora_server_error(1), ORA_SERVER_ERROR_MSG(1), ORA_LOGIN_USER, ORA_DICT_OBJ_OWNER, ORA_DICT_OBJ_NAME, p_sqltxt);
END;
/
Hinweis
Es wird nur die erste Fehlernummer und die erste Fehlermeldung abgespeichert. Wenn der Fehler mehrere Ebenen hat (bei PLSQL Code) kann dies möglicherweise nicht ausreichen. Aus unserer Erfahrung, reicht die Information aber in mehr wie 95% der Fällen aus, da man ja auch das auslösende Statement abgespeichert bekommt.
Beispiel der Nutzung
Jemand versucht zwei mal die gleiche Tabelle anzulegen. Beim ersten mal gelingt das, beim zweiten Versuch kommt es zu einem Fehler.
create table system.foo(y number, z date);
create table system.foo(x number);
Diesen Fehler jetzt einfach aus der Tabelle Server_Error auslesen!
select * from system.server_errors;
ZEITPUNKT ERROR ERROR_MSG LOGIN_USER OBJ_OWNER OBJ_NAME
--------- ----- ----------------------------------------------------- ---------- --------- --------
SQL_TEXT
---------------------------------
12-JUL-18 955 ORA-00955: name is already used by an existing object SYS
create table system.foo(x number)