http://www.oraclefans.cn/forum/s ... d=5055&CPages=1
drop index导致相关对象INVALID的分析
DROP INDEX会导致对象失效吗?这个话题需要从Oracle 7.3.3说起,Oracle的这个版本对UPDATABLE JOIN VIEW(UJV)进行了功能增强,从这个版本开始,如果删除索引,会将索引基表相关的UJV设置为INVALID。从这个时候开始,围绕这个功能,就出现了一系列的问题。针对不同的数据库版本,这些问题的表现略有不同。这个INVALID的设置原本是为了强制对UJV进行强制编译。
从Oracle的初衷来看,是希望对DROP INDEX/CONSTRAINT后的基表相关的VIEW,PROCEDURE,FUNCTION,TRIGGER等设置INVALID,使之强制重新编译。但是在不同的版本中,情况不尽相同。
我们来看一个在9.2.0.4上的例子(不同的数据库版本可能略有不同):
create table tinv as select * from dba_objects;
create unique index idx_tinv on tinv(object_id);
create or replace procedure proc_tinv is
v integer;
begin
dbms_output.enable;
select count(*) into v from tinv ;
dbms_output.put_line(to_char(v));
end;
/
create view view_tinv as select * from tinv;
create or replace procedure proc_tinv1 is
v integer;
begin
dbms_output.enable(2048);
select count(*) into v from VIEW_tinv ;
dbms_output.put_line(to_char(v));
end;
/
col object_name format a20 truncate;
col status format a10 truncate;
select object_name,status from user_objects where object_name in ('TINV','IDX_TINV','PROC_TINV','VIEW_TINV','PROC_TINV1');
OBJECT_NAME
STATUS
-------------------- ----------
PROC_TINV1 VALID
VIEW_TINV
VALID
PROC_TINV
VALID
IDX_TINV
VALID
TINV
VALID
SQL> DROP INDEX IDX_TINV;
Index dropped.
SQL> select object_name,status from user_objects where object_name in ('TINV','IDX_TINV','PROC_TINV','VIEW_TINV','PROC_TINV1');
OBJECT_NAME
STATUS
-------------------- ----------
PROC_TINV1 INVALID
VIEW_TINV
INVALID
PROC_TINV
VALID
TINV
VALID
SQL> EXEC PROC_TINV1
6066
PL/SQL procedure successfully completed.
SQL> select object_name,status from user_objects where object_name in ('TINV','IDX_TINV','PROC_TINV','VIEW_TINV','PROC_TINV1');
OBJECT_NAME
STATUS
-------------------- ----------
PROC_TINV1 VALID
VIEW_TINV
VALID
PROC_TINV
VALID
TINV
VALID
当UNIQUE索引删除后,VIEW和VIVEW相关的PROC都变为INVALID,但是访问基表的PROC并没有变化。执行INVALID的过程后,过程自动重新编译,状态恢复。
按照METALINK Note:282991.1 的建议,可以通过设置EVENT 10624来关闭INVALID校验。
10624, 00000, "Disable UJV invalidation on drop index"
// *Cause:
// *Action: set this event only under the supervision of Oracle development
SQL> alter session set events '10624 trace name context forever, level 12' ;
Session altered.
SQL> DROP INDEX IDX_TINV;
Index dropped.
SQL> select object_name,status from user_objects where object_name in ('TINV','IDX_TINV','PROC_TINV','VIEW_TINV','PROC_TINV1');
OBJECT_NAME
STATUS
-------------------- ----------
PROC_TINV1 VALID
VIEW_TINV
VALID
PROC_TINV
VALID
TINV
VALID
设置EVENT 10624似乎是能够解决这个问题,但是这也会导致其他的一些问题,比如Bug 3288804。从上述的实验来看,虽然有些对象被置为INVALID了,但是在第一次访问这个对象的时候,会自动重新编译,好像又不会对系统有直接的影响。针对某些版本,对象实效可能会导致部分存储过程实效,影响系统运行,这种情况,需要对这些实效对象进行重新编译(针对BUG 3288804,需要重建触发器)。
Oracle设置这个功能的初衷是对UJV进行重新编译,从而修改UJV的属性。但是发展到目前,已经很难找到一个文档,能够很清晰的说明这个机制了,也许在某个版本里,会把这个东西好好整理一下,同时也更新一下文档里的内容。
相关文档:
1076322.6
1057944.6
282991.1
BUG:3796251
259854.1
BUG:728106(文档BUG) |