Oracle默认不会对连接数据库的IP信息进行跟踪,如果需要反查执行SQL的IP信息,要么通过监听日志去分析,要么通过创建触发器来实现。

我遇到的问题是触发器创建了但不生效。相同的触发器语句在不同的库上,有的生效有的不生效。一度怀疑是触发器语句有问题或创建触发器的用户权限有问题,甚至怀疑过数据库的系统包被破坏了。这个问题纠结了近半年,一朝得到解决,豁然开朗心情舒畅。

触发器创建语句如下:

create or replace trigger tr_logon_ip
  after logon on database
begin
  dbms_application_info.set_client_info(sys_context('USERENV',
                                                    'IP_ADDRESS'));
end;

或者

create or replace trigger tr_logon_ip
  after logon on database
declare
  ipinfo varchar2(30);
begin
  select sys_context('USERENV', 'IP_ADDRESS') INTO ipinfo from dual;
  dbms_application_info.set_client_info(ipinfo);
end;

两段代码都是有效的,第一段更简洁,有效语句都是调用dbms包写会话的client_info字段。

通过查询会话信息,来确认触发器是否生效。IP信息记录在client_info字段。

select t.inst_id,
       t.username,
       t.machine,
       t.client_info,
       t.module,
       t.username
  from gv$session t
 where t.client_info is not null;

如果触发器没有生效,需要检查一下_system_trig_enabled 参数的状态

sys@HIS>col name_col_plus_show_param for a20
sys@HIS>col value_col_plus_show_param for a5
sys@HIS>col type for a7
sys@HIS>show parameter _system_trig_enabled


NAME                 TYPE    VALUE
-------------------- ------- -----
_system_trig_enabled boolean FALSE
sys@HIS>

_system_trig_enabled 为 false 时,系统触发器不会生效。

将_system_trig_enabled 设置为 true,再观察一下会话中IP信息。

sys@HIS>alter system set "_system_trig_enabled" = TRUE;


System altered.


sys@HIS>show parameter _system_trig_enabled


NAME                 TYPE    VALUE
-------------------- ------- -----
_system_trig_enabled boolean TRUE

参数设置成功后,会话的IP已经被记录下来了,触发器生效。

需要注意的是 _system_trig_enabled 是Oracle隐含内置参数,打开可能会引发安全问题。如果你的数据库权限没有做到严格管理,有可能会存在注入风险,比如被创建恶意触发器,有一类触发器会在数据库重启时触发,删掉系统表,破坏数据字典,最终导致数据库无法启动。

使用alter语句设置参数时要使用双引号将_system_trig_enabled引起来,不然会报错。

Reference

http://www.dba-oracle.com/t_system_trig_enabled.htm

system_trig_enabled tips

最后修改:2021 年 10 月 01 日
如果觉得我的文章对你有用,请随意赞赏