Создаем таблицу куда будем записывать запросы с ошибками:
CONNECT SYSTEM; DROP TABLE servererror_log; CREATE TABLE servererror_log ( error_datetime TIMESTAMP, error_user VARCHAR2(30), db_name VARCHAR2(30), error_stack VARCHAR2(2000), call_stack VARCHAR2(2000), SID NUMBER, SQL_ID VARCHAR2 (13), sql_statement VARCHAR2(2000), sql_statement_all CLOB, CLIENT_INFO VARCHAR2(256 BYTE), CURR_SCHEMA VARCHAR2(256 BYTE), CURR_USER VARCHAR2(256 BYTE), CURR_DB_NAME VARCHAR2(256 BYTE), HOST VARCHAR2(256 BYTE), IP VARCHAR2(256 BYTE), OSUSER VARCHAR2(256 BYTE), SESSID VARCHAR2(256 BYTE), SESS_USER VARCHAR2(256 BYTE), TERMINAL VARCHAR2(256 BYTE) ); GRANT SELECT, INSERT, UPDATE, DELETE ON SYSTEM.SERVERERROR_LOG TO SCOTT;Выдаем явный грант на V_$SESSION пользователю SYSTEM для того чтобы триггер log_server_errors указанный ниже скомпилировался.
CONNECT SYS AS SYSDBA; GRANT SELECT ON V_$SESSION TO SYSTEM;Триггер базы данных на SERVERERROR(в условии WHEN можем исключить ошибки которые не нужно логгировать, в данном примере - это
ORA-25254):CONNECT SYSTEM;
DROP TRIGGER log_server_errors;
CREATE OR REPLACE TRIGGER log_server_errors
AFTER SERVERERROR
ON DATABASE WHEN (
ORA_SERVER_ERROR(1)<>25254 /*ORA-25254: time-out in LISTEN while waiting for a message*/
)
DECLARE
v_sql_statement VARCHAR2(32767);
sql_text ora_name_list_t;
n pls_integer;
cursor c_user is
select vs.sid sid,
vs.sql_id sql_id,
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
cross join v$session vs
where 1 = 1
and sys_context('USERENV','SESSIONID') = audsid
;
user_rec c_user%rowtype;
BEGIN
open c_user;
fetch c_user into user_rec;
close c_user;
n := ora_sql_txt(sql_text);
FOR i IN 1..n LOOP
v_sql_statement := v_sql_statement || sql_text(i);
END LOOP;
INSERT INTO servererror_log(
error_datetime, error_user, db_name,
error_stack, call_stack,
SID, SQL_ID,
sql_statement, sql_statement_all,
CLIENT_INFO, CURR_SCHEMA, CURR_USER, CURR_DB_NAME,
HOST, IP, OSUSER, SESSID,
SESS_USER, TERMINAL
) VALUES(
systimestamp, sys.login_user, sys.database_name,
ora_server_error_msg(1)/*dbms_utility.format_error_stack*/,
dbms_utility.format_call_stack,
user_rec.sid, user_rec.sql_id,
substrb(v_sql_statement, 1, 2000),
v_sql_statement,
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
);
--commit;
END;
/
Выбираем запросы с ошибками(см. поля SID, SQL_STATEMENT, SQL_STATEMENT_ALL):
CONNECT SCOTT; select * from system.servererror_log --where ERROR_USER = 'SCOTT' order by error_datetime desc ;Дополнительные команды которые возможно пригодятся для трассировки сессии:
CONNECT SYSTEM;
ALTER SYSTEM SET sql_trace = true SCOPE=MEMORY;
...
select * from system.servererror_log;
...
ALTER SYSTEM SET sql_trace = false SCOPE=MEMORY;
--After Logon Trigger for Tracing on Schema:
CONNECT SCOTT;
CREATE OR REPLACE TRIGGER SCOTT_AFTER_LOGON_TRG_00
AFTER LOGON ON SCOTT.SCHEMA
DECLARE
sqlstr VARCHAR2(200) := 'ALTER SESSION SET EVENTS ''10046 TRACE NAME CONTEXT FOREVER, LEVEL 4''';
BEGIN
IF (USER = 'SCOTT') THEN
execute immediate sqlstr;
END IF;
END;
/