Создаем таблицу куда будем записывать запросы с ошибками:
Выдаем явный грант на V_$SESSION пользователю SYSTEM для того чтобы триггер log_server_errors указанный ниже скомпилировался.
- 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;
Триггер базы данных на SERVERERROR(в условии WHEN можем исключить ошибки которые не нужно логгировать, в данном примере - это
- CONNECT SYS AS SYSDBA;
- GRANT SELECT ON V_$SESSION TO SYSTEM;
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;
- /