2009-01-29 8 views

Respuesta

0

Puede hacer esto con un disparador del sistema.

He copiado directamente este código desde http://www.psoug.org/reference/system_trigger.html.

CREATE TABLE servererror_log (
error_datetime TIMESTAMP, 
error_user  VARCHAR2(30), 
db_name   VARCHAR2(9), 
error_stack  VARCHAR2(2000), 
captured_sql VARCHAR2(1000)); 





CREATE OR REPLACE TRIGGER log_server_errors 
    AFTER SERVERERROR 
    ON DATABASE 
    DECLARE 
    captured_sql VARCHAR2(1000); 
    BEGIN 
     SELECT q.sql_text 
     INTO captured_sql 
     FROM gv$sql q, gv$sql_cursor c, gv$session s 
     WHERE s.audsid = audsid 
     AND s.prev_sql_addr = q.address 
     AND q.address = c.parent_handle; 

     INSERT INTO servererror_log 
     (error_datetime, error_user, db_name, 
     error_stack, captured_sql) 
     VALUES 
     (systimestamp, sys.login_user, sys.database_name, 
     dbms_utility.format_error_stack, captured_sql); 
    END log_server_errors; 
    /
3

En lugar de golpear los puntos de vista del sistema, como en la respuesta de Demge, hay una función ora_sql_txt que da la correspondiente declaración.

create or replace TRIGGER log_err after servererror on schema 
DECLARE 
    v_stack VARCHAR2(2000) := substr(dbms_utility.format_error_stack,1,2000); 
    v_back VARCHAR2(2000);-- := substr(dbms_utility.format_error_backtrace,1,2000); 
    v_num NUMBER; 
    v_sql_text ora_name_list_t; 
    procedure track(p_text in varchar2) is 
    begin 
    insert into .... values (p_text); 
    end; 
begin 
    v_stack := translate(v_stack,'''','"'); 
    track(v_stack); 
    v_back := translate(v_back,'''','"'); 
    if v_back is not null then track(v_back); end if; 
    v_num := ora_sql_txt(v_sql_text); 
    BEGIN 
    FOR i IN 1..v_num LOOP 
     track(to_char(i,'0000')||':'||v_sql_text(i)); 
    END LOOP; 
    EXCEPTION 
    WHEN VALUE_ERROR THEN NULL; 
    END; 
end; 

En mi propio entorno, que en realidad tienen 'pista' como un procedimiento independiente que utiliza una transacción autónoma, en lugar de un bloque que el anterior.

create or replace procedure track (p_text IN VARCHAR2) IS 
    PRAGMA AUTONOMOUS_TRANSACTION; 
    cursor c_user is 
    select sys_context('USERENV','CLIENT_INFO')  client_info, 
      sys_context('USERENV','CURRENT_SCHEMA') curr_schema, 
      sys_context('USERENV','CURRENT_USER')  curr_user, 
      sys_context('USERENV','DB_NAME')   db_name, 
      sys_context('USERENV','HOST')    host, 
      sys_context('USERENV','IP_ADDRESS')  ip, 
      sys_context('USERENV','OS_USER')   osuser, 
      sys_context('USERENV','SESSIONID')   sessid, 
      sys_context('USERENV','SESSION_USER')  sess_user, 
      sys_context('USERENV','TERMINAL')   terminal 
    from dual; 
    user_rec c_user%rowtype; 
    v_mod VARCHAR2(48); 
    v_act VARCHAR2(32); 
    v_cli_info varchar2(64); 
begin 
    open c_user; 
    fetch c_user into user_rec; 
    close c_user; 
    DBMS_APPLICATION_INFO.READ_MODULE (v_mod, v_act); 
    --DBMS_APPLICATION_INFO.READ_CLIENT_INFO(v_cli_info); 
    insert into track_detail 
    (id, track_time, detail, client_info, curr_schema, curr_user, db_name, 
    host, ip, osuser, sessid, sess_user, terminal, module, action) 
    values (track_seq.nextval, systimestamp, p_text, 
      user_rec.client_info, user_rec.curr_schema, user_rec.curr_user, 
      user_rec.db_name,  user_rec.host,  user_rec.ip, 
      user_rec.osuser,  user_rec.sessid,  user_rec.sess_user, 
      user_rec.terminal, v_mod,    v_act); 
    commit; 
end; 
10

Es posible que desee utilizar como Auditoría:

AUDITORÍA TABLA SELECT, TABLE INSERT, DELETE TABLE, ejecute el procedimiento POR ACCESO SIEMPRE no tiene éxito;

Por ACCESS es para cada declaración (que parece lo que quieres). Por SESSION registraría un registro por sesión (ambiente de alto volumen).

La auditoría incorporada de Oracle tiene menos carga que un activador. Un desencadenante, que contiene otras respuestas, le permite registrar la información exacta que desea. La auditoría también solo detectará visitas a objetos existentes. Si alguien selecciona en una tabla inexistente (mal escrito o lo que sea), la auditoría no lo detectará. Los desencadenantes anteriores lo harán.

Mucho más información en la guía de seguridad: http://download.oracle.com/docs/cd/B19306_01/network.102/b14266/auditing.htm#i1011984

+0

1 en un intento de conseguir esto (correcto) responder más arriba en la lista :) - si Tom K ve esta respuesta en la parte inferior con una gran cantidad de "uso un disparador "responde más arriba, nunca escucharemos el final". :) –

Cuestiones relacionadas