ORACLE编译失效对象小结

在平常数据库维护过程当中,咱们会发现数据库中一些对象(包Package、存储过程Procedure、函数Function、视图View、同义词.....)会失效,呈现无效状态(INVALID)。有时候须要按期检查数据库中存在哪些失效对象,对于存在异常的对象须要从新编译,有些自动失效的对象,通常会在下次调用的时候,会被从新编译,因此这些不须要人工干预。那么为何对象忽然会失效呢?又如何快速、高效的编译失效对象呢?哪些失效的对象不须要咱们去从新编译呢?html

数据库对象失效缘由sql

数据库对象失效的缘由不少,下面大体概括了一些常见的缘由(有些漏掉的,但愿你们补充):数据库

1: 当被引用对象的结构变动时,都会使得相关的依赖对象转变为INVALID状态。oracle

数据库中的对象(存储过程,函数,包,视图,触发器),它们每每须要直接或者间接的引用其它对象,对象的依赖包括直接和间接二种,其中直接依赖是指存储对象直接依赖于被引用对象,而间接依赖是指对象间接依赖于被引用对象app

要查看被引用的对象,能够经过下面SQL查看函数

select * from dba_dependencies where name='&objectname';
    
select * from all_dependencies where name='&objectname';
 
select * from user_dependencies where name='&objectname';

举个简单例子,视图V_TEST引用了表TEST,TEST表修改了表结构时,会致使视图V_TEST变为无效对象。测试

SQL> CREATE TABLE TEST ( ID NUMBER(10));
 
Table created.
 
SQL> CREATE VIEW V_TEST AS SELECT * FROM TEST;
 
View created.
 
SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';
 
OBJECT_NAME STATUS
 
------------------- ----------------
 
V_TEST VALID
 
--修改表结构,增长一个字段NAME后,视图V_TEST变为无效
 
SQL> ALTER TABLE TEST ADD NAME VARCHAR(12);
 
Table altered.
 
SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';
 
OBJECT_NAME STATUS
 
------------------- ----------------
 
V_TEST INVALID
 
--查询视图V_TEST后,数据库会从新编译视图
 
SQL> SELECT * FROM V_TEST;
 
no rows selected
 
SQL> SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME='V_TEST';
 
OBJECT_NAME STATUS
 
------------------- ----------------
 
V_TEST VALID
 

其实无论视图,像存储过程,函数、包等,若是代码自己没有什么错误,只是引用的对象发生了变化。也会失效。但并不影响调用,由于ORACLE在调用时会自动从新编译的,若是其它对象变化后致使编译有错误。这时调用时从新编译后也是错误并处于失效状态,因此调用会出错。this

2:发布SQL脚本时(包、存储过程、函数等),没有充分测试,编译时出错,这时对象变为无效。spa

3: 数据库升级、迁移时,出现大量无效对象(本质缘由,我的臆测归结为缘由1)。.net

4: 诸如此类各类状况:例如,Oracle 会自动维护分区索引,对于全局索引,若是在对分区表操做时,没有指定update index,则会致使全局索引失效,须要重建。

 

编译失效对象的方法

统计失效的对象:

select owner, object_type, status, count(*)
 
from dba_objects
 
  where status='INVALID'
 
group by owner, object_type, status
 
order by owner, object_type
 

查看具体失效对象

col owner for a20;
 
col object_name for a32;
 
col object_type for a16
 
col status for a8
 
select owner, object_name, object_type, status
 
from dba_objects
 
where status='INVALID'
 
order by 1, 2,3;
 

下文大多参考博文Oracle中编译无效的对象经常使用方法,修改并做了总结、整理

 

1:   使用ALTER *** COMPLIE语句手工进行编译,这个适用于少数、个别对象失效

        alter package <schema name>.<package_name> compile;

        alter package <schema name>.<package_name> compile body;

        alter view <schema name>.<view_name> compile;

       alter trigger <schema).<trigger_name> compile;

 

2:执行@$ORACLE_HOME/rdbms/admin/utlrp.sql脚本编译数据库失效对象。

许多状况下,因为数据库的升级或迁移,会致使数据库中的对象失效。因为对象之间可能存在复杂的倚赖关系,因此手工编译一般没法顺利经过。一般咱们会在Oracle的升级指导中看到这个脚本,Oracle强烈推荐在migration/upgrade/downgrade以后,经过运行此脚本编译失效对象。可是注意,Oracle提醒,此脚本须要用SQLPLUS以SYSDBA身份运行,而且当时数据库中最好不要有活动事物或DDL操做,不然极容易致使死锁的出现(这是很容易理解的)。

Oracle highly recommends running this script towards the end of of any migration/upgrade/downgrade.

另外,utlrp.sql 里面其实调用了$ORACLE_HOME/rdbms/admin/utlrcmp.sql来编译失效对象。

 

3:ORACLE提供了自动编译的接口dbms_utility.compile_schema(user,false); 调用这个过程就会编译全部失效的过程、函数、触发器、包

exec dbms_utility.compile_schema( 'SCOTT' )

 

4:  一些网友书写的编译失效对象(通过整理)

SQL 1: 编译失效对象

set heading off; 
set feedback off; 
set echo off; 
Set lines 999; 
 
Spool run_invalid.sql 
 
select 
'ALTER ' || OBJECT_TYPE || ' ' || 
OWNER || '.' || OBJECT_NAME || ' COMPILE;' 
from 
dba_objects 
where 
status = 'INVALID' 
and 
object_type in ('PACKAGE','FUNCTION','PROCEDURE','TRIGGER','JAVA SOURCE','JAVA CLASS','') 
; 
spool off; 
set heading on; 
set feedback on; 
set echo on; 
 
@run_invalid.sql  

SQL 2:在上面的方法中,只能知道某某编译失败,不清楚失败缘由,能够用PL/SQL实现更详细的错误信息

DECLARE 
 v_objname        user_objects.object_name%TYPE; 
 v_objtype        user_objects.object_type%TYPE; 
 CURSOR cur IS 
    SELECT object_name,object_type 
      FROM USER_OBJECTS 
     WHERE status = 'INVALID' 
       AND object_type IN ('FUNCTION','JAVA SOURCE','JAVA CLASS','PROCEDURE','PACKAGE','TRIGGER'); 
BEGIN 
 OPEN cur; 
 LOOP 
    FETCH cur into v_objname, v_objtype; 
 
EXIT WHEN cur%NOTFOUND; 
    BEGIN 
      EXECUTE Immediate 'alter ' || v_objtype || ' ' || v_objname||' Compile'; 
      dbms_output.put_line('编译' || v_objtype || ' ' || v_objname || '()成功'); 
    EXCEPTION 
      WHEN OTHERS THEN 
        dbms_output.put_line('编译' || v_objtype ||' ' || v_objname || '()失败.' || SQLERRM); 
    END; 
 END LOOP; 
 CLOSE cur; 
END; 

 

参考资料:

http://jzhil2004.blog.163.com/blog/static/275585042010117113214172/

http://blog.csdn.net/tianlesoftware/article/details/4843600

http://www.233.com/oracle/jishu/20071014/101911246.html

相关文章
相关标签/搜索