ORA-04098错误解决方法

作者:网络 来源:佚名 更新时间:2008-02-09 10:10:34 点击:

ora-04098错误解决方法

数据库版本:8.1.5
平台:solaris 5.7

 

背景:

用户建立了一个trigger:
create or replace trigger ddl_deny
before create or alter or drop on database
declare
begin
insert into ddl_logs values(ora_dict_obj_owner,ora_dict_obj_name,sysdate);
exception
when no_data_found then
null;
end;
目的大概就是记录下所有的ddl操作,但trigger建立有错误,发现:

11:30:08 [email protected]>alter trigger ddl_deny disable;
alter trigger ddl_deny disable
*
error 位于第 1 行:
ora-04098: 触发器 'ddl_deny' 无效且未通过重新验证
11:31:45 [email protected]>drop trigger ddl_deny;
drop trigger ddl_deny
*
error 位于第 1 行:
ora-04098: 触发器 'ddl_deny' 无效且未通过重新验证

 

此时触发器不能编译过去,也不能删除了,因为触发器本身里面定义了ddl操作的触发,产生ora-04098: 触发器 'ddl_deny' 无效且未通过重新验证。

 

解决方法:

1、首先查看用户的权限是否正确:

select owner, object_name, object_type, status from dba_objects where object_name = '<trigger_name>';

12:42:38 [email protected]>select owner, object_name, object_type, status from dba_o
bjects where object_name='ddl_deny';
owner          object_name   object_type status
------------------------------------ --------------
system           ddl_deny     trigger invalid

发现用户权限没有问题。

2、接着设置诊断事件alter session set events='4098 trace name errorstack level 3';,查看trace文件的内容如下:

dump file /db1/app/oracle/admin/ora250/udump/ora250_ora_6834.trc
oracle8i enterprise edition release 8.1.5.0.0 - production
with the partitioning and java options
pl/sql release 8.1.5.0.0 - production
oracle_home = /db1/app/oracle/product/8.1.5
system name: sunos
node name: db250
release: 5.7
version: generic_106541-08
machine: sun4u
instance name: ora250
redo thread mounted by this instance: 1
oracle process number: 17
unix process pid: 6834, image: [email protected] (tns v1-v3)
*** session id30.829) 2004.11.17.20.53.38.000
*** 2004.11.17.20.53.38.000
ksedmp: internal or fatal error
ora-04098: 触发器'ddl_deny' 无效且未通过重新验证
current sql statement for this session:
alter trigger ddl_deny disable
----- call stack trace -----
calling call entry argument values in hex
location type point (? means dubious value)
-------------------- -------- -------------------- ----------------------------
ksedmp()+160 call ksedst()+0 508 ? 1 ? ffbeb31c ?
ffbeadc0 ? ffbeada4 ? 0 ?
ksddoa()+248 ptr_call 00000000 3 ? 0 ? 0 ? 16594fc ?
c0000025 ? 0 ?
ksdpcg()+212 call ksddoa()+0 16eb0ac ? 16e4c24 ? 3 ?
24939c ? 16eb0ac ? 16eb090 ?
ksdpec()+236 call ksdpcg()+0 1002 ? ffbeb8e4 ? 16e4c24 ?
0 ? 0 ? 0 ?
ksfpec()+136 call ksdpec()+0 1002 ? 165a800 ? 165a800 ?
7f3 ? 1659995 ? 16594fc ?
kgesev()+100 ptr_call 00000000 1659494 ? 1002 ? 262f80 ?
1002 ? 1 ? 0 ?
ksesec1()+48 call kgesev()+0 1659494 ? 16e8ca4 ? 1002 ?
1 ? ffbeba60 ? 1 ?
kkttrex()+2112 call ksesec1()+0 1002 ? 1 ? 8 ? 8e859d26 ? 2 ?
2 ?
kktexeevt()+616 call kkttrex()+0 8e996a20 ? 8e973b48 ?
ffbebae4 ? 1659000 ?
8e859d6c ? 165e800 ?.....

发现是内部严重错误,其他看不出太多错误信息,于是想到采用隐含参数_system_trigger_enabled=false,在数据库启动的时候让所有触发器不起作用,然后删除。数据库8.1.5的提示没这个参数,于是查询了一下:

14:28:32 [email protected]>select ksppinm from x$ksppi where substr(ksppinm,1,1)='_'
and ksppinm like '%tri%' order by ksppinm;
ksppinm
-------------------------------------------------------------------------------
_cleanup_rollback_entries
_distributed_lock_timeout
_distributed_recovery_connection_hold_time
_number_cached_attributes
_system_trig_enabled

发现8.1.5版本的参数是_system_trig_enabled,于是让用户在初始化参数文件中设置此参数为false,然后重启数据库,删除trigger,删除成功。

至此问题解决。