【原創】ORA-04068: 已丟棄程序包 的當前狀態研究


不久前在市檢的生產環境上有個存儲過程執行報錯,錯誤信息如下:

ORA-04068: 已丟棄程序包  的當前狀態
ORA-04061: package "ZHANGXSH.PR_TEST" 的當前狀態失效
ORA-04065: 未執行, 已更改或刪除 package "ZHANGXSH.PR_TEST"
ORA-06508: PL/SQL: 無法找到正在調用 : "ZHANGXSH.PR_TEST" 的程序單元
ORA-06512: 在 line 2

當然這個錯誤信息是我在我本機試驗復現的,不是真實的報錯信息,不過都是一樣的

開始懷疑是存儲過程編譯失敗造成,但是經過仔細排查,發現沒有編譯失敗,該包所依賴的其他過程、函數、視圖等都沒有問題。仔細分析了下,發現該包里面有多個全局變量,懷疑是全局變量的問題,於是我在本機做了個測試,將該問題復現了下:
首先在會話1中創建以下包:

CREATE OR REPLACE PACKAGE PKG_TEST AS
  LDLX NUMBER := 1000;
END PKG_TEST;
/

CREATE OR REPLACE PACKAGE BODY PKG_TEST AS
END PKG_TEST;
/

然后創建測試的存儲過程:

create or replace procedure pr_test2 as
begin
  PKG_TEST.LDLX := PKG_TEST.LDLX+110;
  dbms_output.put_line(PKG_TEST.LDLX);
end;
/
然后在會話2中執行pr_test2;
SQL> set serveroutput on
SQL> exec pr_test2;

1110

PL/SQL procedure successfully completed

可以成功執行。
然后回到會話1中重新編譯PKG_TEST 包。再回到會話2執行存儲過程:

SQL> /

begin pr_test2; end;

ORA-04068: 已丟棄程序包  的當前狀態
ORA-04061: package "ZHANGXSH.PKG_TEST" 的當前狀態失效
ORA-04065: 未執行, 已更改或刪除 package "ZHANGXSH.PKG_TEST"
ORA-06508: PL/SQL: 無法找到正在調用 : "ZHANGXSH.PKG_TEST" 的程序單元
ORA-06512: 在 "ZHANGXSH.PR_TEST2", line 3
ORA-06512: 在 line 2

SQL> 

此時,該錯誤立刻被拋出,原因就是全局變量在會話2中存在一個拷貝,當會話不關閉時,該拷貝會一直存在於pga中,如果該包在此時被重新編譯會導致該拷貝失效而報錯。在實際測試中發現,該錯誤出現的概率約為60%左右,也就是說重新編譯100次,約會出現60次,而且詭異的是在rh5+10G下面居然不出現該錯誤,只有當全局變量的值改變時才報該錯。原因有待進一步研究。
因此,很多人包括我自己都偏愛存儲過程,原因之一就是修改后無需重啟中間件立刻生效,這個案例說明,存儲過程也是可能發生問題的,因此提供以下避免的方法:

1.全局變量不要和相關的函數、存儲過程定義在一個包里面,而是單獨定義,單獨定義的目的是減少被重新編譯的概率。
2.不要使用全局變量,如果要使用,則參考1.

如果已經發生了該錯誤,解決辦法如下:

1.將運行報錯的會話kill掉。
2.刷新共享區:alter system flush shared_pool;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM