Skip to Main Content

Breadcrumb

Server Error

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)