• ORACLE编译失效对象小结


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

    数据库对象失效原因

    数据库对象失效的原因很多,下面大致归纳了一些常见的原因(有些漏掉的,希望大家补充):

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

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

    要查看被引用的对象,可以通过下面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在调用时会自动重新编译的,如果其它对象变化后导致编译有错误。这时调用时重新编译后也是错误并处于失效状态,所以调用会出错。

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

    3: 数据库升级、迁移时,出现大量无效对象(本质原因,个人臆测归结为原因1)。

    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

  • 相关阅读:
    《陶哲轩实分析》习题10.4.3
    陶哲轩实分析定理10.1.3:导数运算的积法则和商法则
    《数学分析新讲》_张筑生,12.5节:隐函数定理(1)
    《数学分析新讲》_张筑生,12.5节:隐函数定理(1)
    《陶哲轩实分析》定理10.1.15:导数的链法则
    我的博客园的CSS和html设置
    陶哲轩实分析定理10.1.3:导数运算的积法则和商法则
    关于Eclipse中一个错误排查总结
    RMI, Dynamic Proxies, and the Evolution of Deployment
    Java垃圾回收机制浅析
  • 原文地址:https://www.cnblogs.com/kerrycode/p/3723715.html
Copyright © 2020-2023  润新知