对于几个失败问题,我编写了此触发器-audit_failed_trg
作为after servererror on database
触发器。
我的第一个想法是根据需要只检查特定的异常\ user \ table。
但是我只是想知道-数据库应该为任何失败触发该触发器。
在生产环境中启用它是一个好主意吗?
这会导致性能问题或其他问题吗?
我正在使用Oracle 11g。
create or replace trigger audit_failed_trg
after servererror on database
declare
l_sql_text ora_name_list_t;
l_n number;
begin
insert into T values ( S.NEXTVAL, 1, 'ora_sysevent = ' || ORA_SYSEVENT ,sysdate);
insert into T values ( S.CURRVAL, 2, 'ora_login_user = ' || ORA_LOGIN_USER,sysdate );
insert into T values ( S.CURRVAL, 3, 'ora_server_error = ' || ORA_SERVER_ERROR(1),sysdate );
insert into T values ( S.CURRVAL, 4, 'SID = ' || SYS_CONTEXT ('USERENV','SID'),sysdate);
insert into T values ( S.CURRVAL, 5, 'host = ' || SYS_CONTEXT ('USERENV','HOST') ,sysdate);
insert into T values ( S.CURRVAL, 6, 'ip = ' || SYS_CONTEXT ('USERENV','IP_ADDRESS') ,sysdate);
insert into T values ( S.CURRVAL, 7, 'module = ' || SYS_CONTEXT ('USERENV','MODULE') ,sysdate);
insert into T values ( S.CURRVAL, 8, 'serverhost = ' || SYS_CONTEXT ('USERENV','SERVER_HOST') ,sysdate);
l_n := ora_sql_txt( l_sql_text );
for i in 1 .. l_n
LOOP
insert into t values ( s.CURRVAL,8+i, 'l_sql_text(' || i || ') = ' || l_sql_text(i),sysdate );
end loop;
end;
答案 0 :(得分:3)
记录所有服务器错误是一个好主意,我已经看到它在生产环境中运行良好。
理论上,错误记录由应用程序处理。实际上,大多数应用程序不会捕获所有数据库错误。拥有一个包含数据库生成的所有错误的表是很有用的。
但是,这种触发因素有一些特殊的挑战,需要仔细考虑:
AFTER SERVERERROR
是更安全的事件,因为某些东西在调用之前已经坏掉了。但是奇怪的事情仍然可能发生。例如,您会注意到exception when others then null;
代码。该代码通常是一种反模式,但这是您真正想要抑制所有异常以避免无限循环的少数几个地方之一。花一些时间在更好的桌子设计上。忽略问题中使用的表的键值对类型。而是创建一个表,该表将为每个错误存储一行,并使用有意义的名称。像这样的表将更容易有意义地查询:
--drop trigger audit_failed_trg;
--drop table server_errors;
--drop sequence server_error_seq;
create sequence server_error_seq;
create table server_errors
(
id number not null,
error_date date not null,
ora_sysevent varchar2(128),
ora_login_user varchar2(128),
ora_server_error varchar2(4000),
sid number,
host varchar2(256),
ip varchar2(15),
module varchar2(4000),
serverhost varchar2(256),
sql clob,
constraint server_errors_pk primary key(id)
);
create or replace trigger audit_failed_trg
after servererror on database
declare
v_sql_text ora_name_list_t;
v_sql clob;
v_n number;
begin
v_n := ora_sql_txt(v_sql_text);
for i in 1 .. v_n loop
v_sql := v_sql || v_sql_text(i);
end loop;
--If you find a huge number of irrelevant errors, you might want to filter them out here.
insert into server_errors
values
(
server_error_seq.nextval,
sysdate,
ora_sysevent,
ora_login_user,
ora_server_error(1),
sys_context ('USERENV','SID'),
sys_context ('USERENV','HOST'),
sys_context ('USERENV','IP_ADDRESS'),
sys_context ('USERENV','MODULE'),
sys_context ('USERENV','SERVER_HOST'),
v_sql
);
commit;
--Never raise an exception from this trigger.
--No matter what happens we don't want recursive errors.
exception when others then
null;
end;
/