尋找無效對象
你可以根據這個查詢結果來判斷使用下面的哪種方法來編譯你資料庫裡面的無效對象.
COLUMN object_name FORMAT A30 SELECT owner, object_type, object_name, STATUS FROM dba_objects WHERE STATUS = 'INVALID' ORDER BY owner, object_type, object_name;
1.手動編譯
如果無效對象的數量很少,那麼你可以逐個編譯這些對象.
如:
ALTER PACKAGE my_package COMPILE; ALTER PACKAGE my_package COMPILE BODY; ALTER PROCEDURE my_procedure COMPILE; ALTER FUNCTION my_function COMPILE; ALTER TRIGGER my_trigger COMPILE; ALTER VIEW my_view COMPILE;
你也可以用DBMS_DDL包來編譯(但只用於PL/SQL對象,所以你不用它來編譯視圖等):
EXEC DBMS_DDL('PACKAGE', 'MY_SCHEMA', 'MY_PACKAGE'); EXEC DBMS_DDL('PACKAGE BODY', 'MY_SCHEMA', 'MY_PACKAGE'); EXEC DBMS_DDL('PROCEDURE', 'MY_SCHEMA', 'MY_PROCEDURE'); EXEC DBMS_DDL('FUNCTION', 'MY_SCHEMA', 'MY_FUNCTION'); EXEC DBMS_DDL('TRIGGER', 'MY_SCHEMA', 'MY_TRIGGER');
2.泛型指令碼
在某些情況下你可能有很多無效對象要編譯,這樣話手工編譯就顯得效率太低了.
在這種情況下你可以些一個通用的指令碼產生編譯指令碼.
下面的指令碼用來查詢無效的package 和package body並產生便宜這些對象的指令碼.
但是這方法不會考慮ORACLE對象之間的依賴關係.
SET SERVEROUTPUT ON SIZE 1000000 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; /
3.使用DBMS_UTILITY.compile_schema
使用這個包將會編譯指定schema下的所有procedures, functions, packages, and triggers.
你可以在sqlplus 下使用它,如:
EXEC DBMS_UTILITY.compile_schema(schema => ‘SCOTT’);
4.使用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 IN VARCHAR2 DEFAULT NULL,
flags IN PLS_INTEGER DEFAULT 0);
參數使用方法:
schema
- 想編譯的模式,如果為NULL,將編譯資料庫的所有無效對象.
threads
- 並行度,如果為NULL,會使用參數job_queue_processes的值.
通常threads的值最好和CPU的數量想匹配,以發揮並行的最大優勢.
flags -
ORACLE內部使用的診斷測試參數.
如:
-- Schema level. EXEC UTL_RECOMP.recomp_serial('SCOTT'); EXEC UTL_RECOMP.recomp_parallel(4, 'SCOTT'); -- Database level. EXEC UTL_RECOMP.recomp_serial(); EXEC UTL_RECOMP.recomp_parallel(4); -- Using job_queue_processes value. EXEC UTL_RECOMP.recomp_parallel(); 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語句可能會導致死結.
4.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:
0 - 基於CPU_COUNT參數設定並行度.
1 - 以串列方式編譯對象,一次編譯一個.
N - 以N個並行度進行編譯.
指令碼需要以sys使用者或者有sysdba許可權的使用者來運行.