天天看點

重新編譯資料庫中的失效對象

原文整理自:http://www.51testing.com/?uid-16403-action-viewspace-itemid-98161;http://www.eygle.com/archives/2005/01/ecioaeaoeeeaoea.html

先看個文章:http://www.itpub.net/thread-1112553-1-1.html

每次資料庫做了更新(打各種資料庫方面的更新檔後,不是資料庫本身的更新,是各種對象改變增加修改等,呵呵不,别誤解)

完了以後我都要查一下資料庫中的失效對象,每次都發現多了好多,尤其是包啊過程啊等,都要重新再編譯一次,才全部都好了,有點奇怪,為什麼總需要這樣呢?

大家有這樣的經曆把,隻要重新編譯就OK了,不這樣做,生産中一堆失效對象,不編譯估計對生産有影響吧,系統用到這些包和過程等的時候,發現失效會自己去編譯嗎?

跟帖解答:你修改對象的操作導緻了存儲過程被置于invalid 狀态。因為更新有一些DDL操作,導緻相關存儲過程失效。可以使用自帶的重編譯腳本$ORACLE_HOME/rdbms/admin/utlrp.sql ,存儲過程再次使用的時候自動編譯。但是,自動編譯可能成功也可能失敗,

更新完檢查失效對象是好習慣。

更好的習慣是,更改對象之前先檢視會影響哪些對象

1、查找無效對象

SQL> COLUMN  object_name  FORMAT  A30

SQL> SELECT owner,object_type,object_name,STATUS

FROM dba_objects WHERE

STATUS='INVALID' ORDER BY owner,object_type,object_name;

2、手動編譯

如果無效對象的數量很少,那麼你可以逐個編譯這些對象.

如:

SQL> ALTER PACKAGE my_package COMPILE;

SQL> ALTER PACKAGE my_package COMPILE BODY;

SQL> ALTER PROCEDURE my_procedure COMPILE;

SQL> ALTER FUNCTION my_function COMPILE;

SQL> ALTER TRIGGER my_trigger COMPILE;

SQL> ALTER VIEW my_view COMPILE;

你也可以用DBMS_DDL包來編譯(但隻用于PL/SQL對象,是以你不用它來編譯視圖等):

SQL> EXEC DBMS_DDL('PACKAGE','MY_SCHEMA','MY_PACKAGE'); 

SQL> EXEC DBMS_DDL('PACKAGE BODY','MY_SCHEMA','MY_PACKAGE'); 

SQL> EXEC DBMS_DDL('PROCEDURE','MY_SCHEMA','MY_PROCEDURE'); 

SQL> EXEC DBMS_DDL('FUNCTION','MY_SCHEMA','MY_FUNCTION'); 

SQL> EXEC DBMS_DDL('TRIGGER','MY_SCHEMA','MY_TRIGGER');

3、通用腳本

在某些情況下你可能有很多無效對象要編譯,這樣話手工編譯就顯得效率太低了.

在這種情況下你可以些一個通用的腳本生成編譯腳本.

下面的腳本用來查詢無效的package 和package body并生成便宜這些對象的腳本.

但是這方法不會考慮ORACLE對象之間的依賴關系.

SQL>

SET SERVEROUTPUT ON SIZE 1000000 

 SQL>  BEGIN 

                   FOR cur_rec IN (SELECT owner,object_name,object_type,DECODE (object_type,'PACKAGE',1,'PACKAGE BODY',2,2)  AS  recompile_order   FROM  dba_objects  WHERE  object_type IN  ('PACKAGE','PACKAGE BODY') AND  STATUS!='VALID' ORDER BY 4)   LOOP 

               BEGIN 

                      IF cur_rec.object_type='PACKAGE '   THEN 

                            EXECUTE  IMMEDIATE  'ALTER '||cur_rec.object_type||' 

                                   "'||cur_rec.owner||'"."'||cur_rec.object_name||'" COMPILE'; 

                      ElSE 

                             EXECUTE IMMEDIATE'ALTER PACKAGE 

                                   "'||cur_rec.owner||'"."'||cur_rec.object_name||'" COMPILE BODY'; 

                     END IF; 

              EXCEPTION 

                      WHEN OTHERS THEN 

                                  DBMS_OUTPUT.put_line(cur_rec.object_type||' : '||cur_rec.owner||' : 

                                  '||cur_rec.object_name); 

              END; 

    END LOOP; 

END;

/

4、使用DBMS_UTILITY.compile_schema

使用這個包将會編譯指定schema下的所有procedures, functions, packages, and triggers.

你可以在sqlplus 下使用它,如:

SQL>  EXEC DBMS_UTILITY.compile_schema(schema => ‘SCOTT’);

5、使用UTL_RECOMP

UTL_RECOMP包有兩個存儲過程:RECOMP_SERIAL 和  RECPMP_PARALLEL

從存儲過程的名字可以看出一個是非并行,一個是并行方式.

使用并行方式會加快編譯速度,包的定義如下:

PROCEDURE  RECOMP_SERIAL(

schema IN VARCHAR2 DEFAULT NULL,

flags IN PLS_INTEGER DEFAULT 0);

PROCEDURE RECOMP_PARALLEL

threads IN PLS_INTEGER DEFAULT NULL,

參數使用方法:

schema

- 想編譯的模式,如果為NULL,将編譯資料庫的所有無效對象.

threads

- 并行度,如果為NULL,會使用參數job_queue_processes的值.

通常threads的值最好和CPU的數量想比對,以發揮并行的最大優勢.

flags

-- Schema level.EXEC UTL_RECOMP.recomp_serial('SCOTT'); 

SQL> EXEC UTL_RECOMP.recomp_parallel(4,'SCOTT'); 

 -- Database level.EXEC UTL_RECOMP.recomp_serial(); 

SQL> EXEC UTL_RECOMP.recomp_parallel(4); 

 -- Using job_queue_processes value.EXEC UTL_RECOMP.recomp_parallel(); 

SQL>  EXEC UTL_RECOMP.recomp_parallel(NULL,'SCOTT');

UTL_RECOMP包的一些使用限制

(1).并行執行使用的是job隊列.當運作并行編譯的時候所有job都會被diable直到編譯完成.

(2).包必須在sqlplus中以sys使用者或者有sysdba權限的使用者運作.

(3).UTL_RECOMP依賴于DBMS_STANDARD,DBMS_JOB,DBMS_RANDOM

(4).如果在運作這個包的時候執行DDL語句可能會導緻死鎖.

6、utlrp.sql 和 utlprp.sql

utlrp和utlprp腳本可以用來重編譯資料庫的所有無效對象.通常我們會在Oracle的更新指導中看到這個腳本,Oracle強烈推薦在migration/upgrade/downgrade之後,通過運作此腳本編譯失效對象.

腳本位于$ORACLE_HOME/rdbms/admin目錄.你可以看到utlrp.sql隻是調用utlprp.sql,  utlrp.sql在調用utlprp.sql的時候會傳遞給它一個參數,預設為0,這個參數其實就是并行度,其實utlprp.sql調用的是utl_recomp.recomp_parallel:

- 基于CPU_COUNT參數設定并行度.

1 - 以串行方式編譯對象,一次編譯一個.

N - 以N個并行度進行編譯.

腳本需要以sys使用者或者有sysdba權限的使用者來運作,并且當時資料庫中最好不要有活動事物或DDL操作,否則極容易導緻死鎖的出現(這是很容易了解的)

自動編譯可能成功也可能失敗。

下一篇: Spring配置RMI