運用時に発生するエラー

ORA-04068: パッケージの既存状態は廃棄されました

  • エラーの原因

パッケージがセッションに読み込みされた状態(※)でパッケージが INVALID になった場合や再コンパイルした場合には ロードされたパッケージの状態が破棄される。

(※) パッケージがセッション情報にインスタンス化されていない場合には、パッケージはインスタンス化する前に自動的に再コンパイルされてエラーもなくロードされる。

ORA-04068: パッケージの既存状態は廃棄されました。
ORA-04061: package body "schema.package_name"の既存状態は無効になりました。
ORA-06508: PL/SQL: コールしているプログラム単位が見つかりませんでした。

のエラーが発生する。これはセッション毎にパッケージの内部ステータスを管理するインスタンス(⇔クラス)が存在するためである。(※1)
セッションが一度パッケージをロードした後に INVALID にしてしまったり、関連あるストアドプログラムを再コンパイルするとコンパイルの連鎖が発生する。

(※1) セッション情報にインスタンス化されているため ALTER SYSTEM FLUSH SHARED_POOL で SGA 内のパッケージのキャッシュをフラッシュさせてもリセットされない。

パッケージ変数をコールするたびにクリアするプラグマ(※2)では、このエラーを回避することはできない。 以下のメッセージからセッションに読み込まれるパッケージの情報に LAST_DDL_TIME が保持されているようにみえる(※3)。

ORA-04062: timestamp(xxxxx "yyyyy"について)が変更されました。

(※2) SERIALLY_REUSABLE プラグマの使用例

CREATE PACKAGE package_name
IS
PRAGMA SERIALLY_REUSABLE;
...

(※3) リモートオブジェクトの場合にはデータベースサーバー間のタイムスタンプを信用できないため REMOTE_DEPENDENCIES_MODE 初期化パラメータ により TIMESTAMP モデル(デフォルト)と SIGNATURE モデルを選択できる。

  • 対応

DBMS_SESSION 組み込みパッケージに RESET_PACKAGE と MODIFY_PACKAGE_STATE Oracle 9i というパッケージのインスタンス状態を制御するプロシージャを使用することでパッケージを再初期化することが可能。しかし パッケージのリファレンスマニュアルには

RESET_PACKAGE は、起動したPL/SQL コールの実行が完了した後でのみ
メモリー、カーソルおよびパッケージ変数を解放します。

と記されている。

つまり、RESET_PACKAGE の記述があるコール以降から有効になるということ。さらに DBMS_OUTPUT の出力バッファが標準出力に書かれる前にバッファクリアしてしまう仕様らしく記述する場所を問わず、すべてのメッセージが表示されないようである。

(注意書きは見当たらないが MODIFY_PACKAGE_STATE も同様のようである) また、このエラーが発生することが予知できても他のセッションからは操作する方法は見当たらない。

パッケージのコンパイルエラーがない場合、このエラー発生時の対処はパッケージの呼び出しをリトライすることで パッケージ情報を再読み込みすることは可能であるが、一般的なアプリケーションにおいては、 あまり実装する価値がないと思われる。

ただし、コネクションプーリングを使用したアプリケーションでシングルインスタンス、ダウンタイム0などの厳しい制約がある場合には唯一で十分価値のある実装であるだろう。

 


 

一覧ページへ戻る

OTN (Oracle Technology Network)によるエラーメッセージによる情報だけでは、対処に困ったエラーについてのプラクティスです。
ベスト・プラクティスというわけではないので、書いてあることに固執しないで広い視野でエラー対応してください。

ORA-04068の関連トピックス

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)