修改並重新編譯預存程序 B 後,需手動重新編譯呼叫它的程序 A。若在重新編譯 A 之前 先去呼叫/執行 A,極易導致 A 編譯過程卡死,尤其在高併發環境下更明顯。強制終止編譯會話後,會話狀態顯示 INACTIVE 但實際未釋放,再次 Recompile 仍會 Hang 住。
編譯過程需取得 Library Cache Lock/Pin,若先前有會話持有相關鎖且未正常釋放(如中斷的執行、未提交的交易),後續編譯會阻塞於等待鎖釋放,形成看似「卡死」的現象。
SELECT V.OSUSER,
V.PROCESS,
V.PROGRAM,
V.MACHINE,
V.TERMINAL,
V.MODULE,
V.USERNAME,
V.STATUS,
V.SID,
V.SERIAL#,
'ALTER SYSTEM KILL SESSION ''' || V.SID || ',' || V.SERIAL# || ''';' AS KILL_SESSION,
V.PADDR
FROM V$SESSION V
WHERE V.USERNAME LIKE '%USERNAME%'
AND V.PROGRAM LIKE 'PlSqlDev%'
AND V.OSUSER LIKE '%%'
AND V.STATUS = 'INACTIVE';
註:USERNAME、PROGRAM、OSUSER 條件請依實際環境調整,關鍵在於 STATUS = 'INACTIVE' 且為開發工具產生的會話。
將查詢結果的 KILL_SESSION 欄位複製,在 SQL*Plus 中執行,終止殘留會話。
殺掉會話後,重新連線至 PL/SQL Developer 或其他工具,對目標預存程序執行 Recompile,即可恢復正常。
DBMS_UTILITY.COMPILE_SCHEMA: 批次編譯 Schema 物件,由 Oracle 內部處理依賴順序預存程序編譯 Hang 多因殘留 INACTIVE 會話持有鎖資源。透過 V$SESSION 精準定位並 Kill 掉這些會話,配合正確的編譯順序,即可徹底解決並預防此類問題。