2022年2月7日月曜日

SESSION_EXIT_ON_PACKAGE_STATE_ERRORの動作を確認する

 最近Autonomous Databaseに追加された初期化パラメータSESSION_EXIT_ON_PACKAGE_STATE_ERRORの動作を確認しました。その作業ログです。

東京リージョンのAlways FreeのATPで作業を行なっています。


最初に初期化パラメータの有無を確認します。データベース・アクションを使用します。

select name,value,isses_modifiable,issys_modifiable
from v$parameter where name = 'session_exit_on_package_state_error';


デフォルトではFALSEに設定されています。

NAME                                VALUE ISSES_MODIFIABLE ISSYS_MODIFIABLE 
----------------------------------- ----- ---------------- ---------------- 
session_exit_on_package_state_error FALSE TRUE             IMMEDIATE        

ISSES_MODIFIABLEがTRUEなので、ALTER SESSIONで変更できることになっていますが(マニュアルにもそう記載されています)実際に実行するとORA-1031: insufficient privilegesが発生します。おそらくDatabase Vaultによって保護されていると思われます。

そのため、このパラメータはユーザーADMINでalter systemを実行して変更します。

パッケージmy_parent_pkgおよびchild_pkgは、こちらの記事で作成したものを使用します。Autonomous Databaseの接続には、APEXのワークスペースとして作成したスキーマAPEXDEVを使用します。

動作に確認のために、以下のスクリプトを実行します。s01.sqlというファイルに保存します。

set serveroutput on

select sys_context('USERENV','SESSIONID') sessionid, status from all_objects

where object_type = 'PACKAGE BODY'

  and object_name = 'MY_PARENT_PKG'

  and owner = 'APEXDEV';

begin

    dbms_output.put_line(my_parent_pkg.count_up(1));

end;

/

select sys_context('USERENV','SESSIONID') sessionid, status from all_objects

where object_type = 'PACKAGE BODY'

  and object_name = 'MY_PARENT_PKG'

  and owner = 'APEXDEV';


最初にCHILD_PKGとしてG_TESTが1のパッケージを使用します。以下の手順で初期化します。

SQL> @child_pkg1


Package CHILD_PKGがコンパイルされました



Package Body CHILD_PKGがコンパイルされました


SQL> alter package my_parent_pkg compile body;


Package MY_PARENT_PKGが変更されました。


SQL> 


スクリプトs01.sqlを実行します。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


2



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


SQL> 


スクリプトを実行するたびに、1つずつ出力される数値が増えます。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


3



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


SQL> 


別セッションにてパッケージCHILD_PKGをG_TESTが100のものに入れ替えたのち、再度、スクリプトを実行します。ORA-4068、ORA-4061、ORA-4065といった例外が発生します。

しかし、例外が発生する前後のSESSIONIDに変化はありません

SQL> @s01


    SESSIONID     STATUS 

_____________ __________ 

2197167149    INVALID    



次の開始中にエラーが発生しました : 行 6 ファイル @ /Users/ynakakoshi/Documents/ora4061/s01.sql

コマンド -

begin

    dbms_output.put_line(my_parent_pkg.count_up(1));

end;

エラー・レポート -

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

ORA-04061: package "APEXDEV.CHILD_PKG"の既存状態は無効になりました。

ORA-04065: package "APEXDEV.CHILD_PKG"は変更/削除されているので、実行できません

ORA-06508: PL/SQL: コールしているプログラム単位が見つかりませんでした: "APEXDEV.CHILD_PKG"

ORA-06512: "APEXDEV.MY_PARENT_PKG", 行7

ORA-06512: 行2

04068. 00000 -  "existing state of packages%s%s%s has been discarded"

*Cause:    One of errors 4060 - 4067 when attempt to execute a stored

           procedure.

*Action:   Try again after proper re-initialization of any application's

           state.


    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


SQL> 


再度スクリプトを実行すると、置き換えられたパッケージを使って正常に終了します。セッションは継続しているため、SESSIONIDに変化はありません。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


101



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

2197167149    VALID     


SQL> 


SESSION_EXIT_ON_PACKAGE_STATE_ERRORをTRUEに変更し、同様にスクリプトを実行します。データベース・アクションから実行します。

alter system set session_exit_on_package_state_error = true;


パッケージCHILD_PKGのG_TESTが1となるように初期化します。

s01.sqlを複数回実行します。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

2071203142    VALID     


3



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

2071203142    VALID     


SQL> 


別セッションでCHILD_PKGをG_TESTが100のものに入れ替えます。

SQL> @s01


    SESSIONID     STATUS 

_____________ __________ 

2071203142    INVALID    



次の開始中にエラーが発生しました : 行 6 ファイル @ /Users/ynakakoshi/Documents/ora4061/s01.sql

コマンド -

begin

    dbms_output.put_line(my_parent_pkg.count_up(1));

end;

エラー・レポート -

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

ORA-04061: package "APEXDEV.CHILD_PKG"の既存状態は無効になりました。

ORA-04065: package "APEXDEV.CHILD_PKG"は変更/削除されているので、実行できません

ORA-06508: PL/SQL: コールしているプログラム単位が見つかりませんでした: "APEXDEV.CHILD_PKG"

ORA-06512: "APEXDEV.MY_PARENT_PKG", 行7

ORA-06512: 行2

04068. 00000 -  "existing state of packages%s%s%s has been discarded"

*Cause:    One of errors 4060 - 4067 when attempt to execute a stored

           procedure.

*Action:   Try again after proper re-initialization of any application's

           state.


次の開始中にエラーが発生しました : 行 10 ファイル @ file:/Users/ynakakoshi/Documents/ora4061/s01.sql

コマンド -

select sys_context('USERENV','SESSIONID') sessionid, status from all_objects

where object_type = 'PACKAGE BODY'

  and object_name = 'MY_PARENT_PKG'

  and owner = 'APEXDEV'

コマンド行 : 10 列 : 1 ファイル @ file:/Users/ynakakoshi/Documents/ora4061/s01.sql でのエラー

エラー・レポート -

SQLエラー: クローズされた接続です。

SQL> 


ORA-4068、4061、4065の例外が発生するところまでは同じですが、その後のSELECT文の実行時にSQLエラー:クローズされた接続です。が発生しています。

初期化パラメータSESSION_EXIT_ON_PACKAGE_STATE_ERRORをTRUEに変更し、ORA-4068が発生するとセッションが中断するという動作が確認できました。

データベースに再度接続し、スクリプトを実行すると正常に終了します。SESSIONIDは異なります。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

3423382160    VALID     


101



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

3423382160    VALID     


SQL> 


ちなみに、パッケージCHILD_PKGをG_TESTが100のものに入れ替えた後に、dbms_session.reset_packageを呼び出してパッケージの状態を初期化した後にs01.sqlを実行すると、ORA-4068は発生しません。

SQL> @s01


    SESSIONID    STATUS 

_____________ _________ 

3423382160    VALID     


3



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

3423382160    VALID     


SQL> begin

  2  dbms_session.reset_package;

  3  end;

  4* /


PL/SQLプロシージャが正常に完了しました。


SQL> @s01


    SESSIONID     STATUS 

_____________ __________ 

3423382160    INVALID     <- SESSIONIDに変化はない。


101  <- パッケージが入れ替わっている。



PL/SQLプロシージャが正常に完了しました。



    SESSIONID    STATUS 

_____________ _________ 

3423382160    VALID     


SQL> 


パッケージを置き換えるとORA-4068が発生するのは、パッケージが初期化されていることが理由です。処理の開始時点ではなく途中でdbms_session.reset_packageを呼び出すと、パッケージの初期化という同じ理由により、ORA-4068の例外が発生します。


RESTサービスのテスト



こちらの記事のTEST4番を実行すると、パッケージを置き換えたときに以下のエラーが発生します。

555 User Defined Resource Error

{
"code": "UserDefinedResourceError"
"title": "User Defined Resource Error"
"message": "The request could not be processed due to an error in a user defined resource"
"o:errorCode": "ORDS-25001"
"cause": "An error occurred when evaluating the SQL statement associated with this resource. SQL Error Code 17410, Error Message: No more data to read from socket"
"action": "Ask the user defined resource author to check the SQL statement is correctly formed and executes without error"
"type": "tag:oracle.com,2020:error/UserDefinedResourceError"
"instance": "tag:oracle.com,2020:ecid/33defd24642593b60959f644ee6ce4b5"
}

RESTサービスの処理の途中でデータベースの接続が中断されたことが確認できます。RESTサービスを再度呼び出すと、正常な結果を得られます。

TEST5番の実行でも同じエラーが発生します。RESTサービスの再呼び出しで回復します。

終了