2023年4月27日木曜日

APEX 23.1で追加されたセッション・ステート・コミットの注意点

 Oracle APEX 23.1より、アプリケーション定義セキュリティセッション管理のセクションに、セッション・ステート・コミットという属性が追加されました。

セッション・ステート・コミットには、即時またはリクエストの終わりのどちらかを設定します。

セッション・ステート・コミット即時の場合、APEX 22.2までと同じ動作になります。そのため、APEX 23.1にアップグレードする以前から存在するアプリケーションのセッション・ステート・コミットは即時が設定されます。

Oracle APEX 23.1の環境で新規に作成したアプリケーションは、セッション・ステート・コミットリクエストの終わりが設定されます。

セッション・ステート・コミットの設定は、セッション・ステートの操作で発生する暗黙コミットに影響を与えます。Oracle APEXの暗黙コミットについては、以下の記事で説明しています。

APEXのプロセスで発生する暗黙コミットの注意点

上記の記事で使用しているサンプル・アプリケーションを使って、セッション・ステート・コミットの効果を確認できます。
https://github.com/ujnak/apexapps/blob/master/exports/test-implicit-commit.zip

このサンプル・アプリケーションの含まれるプロセスUpdate Page Itemに、以下のコードが記述されています。
:P1_TEXT := '処理完了';
-- apex_util.set_session_state('P1_TEXT','処理完了',true);
-- apex_util.set_session_state('P1_TEXT','処理完了',false);
-- rollback;
元記事では、ページ・アイテムの3種類の操作で発生する暗黙コミットについて、動作の違いを説明しています。

セッション・ステート・コミットリクエストの終わりが設定されていると、上記すべての操作で暗黙コミットは行われなくなります。つまり、どれも以下と同じ動作になります。

apex_util.set_session_state('P1_TEXT','処理完了',false);

セッション・ステートの操作(主にページ・アイテムであるバインド変数への代入)で暗黙コミットが行われると、その後、プロセスで例外が発生したときにトランザクションがロールバックされても、リクエストを受け付ける直前の状態には(完全には)戻りません。よって、処理のべき等性が確保されません。

Oracle APEXのページ・プロパティにページの重複送信の許可という属性があります。これはデフォルトでははい - ページの再ポストを許可するになっています。


ブラウザからのリクエストの再送が発生した場合、これまでは2重にデータが挿入されることがありました。そのような場合、いいえ - ページの再ポストを防止するへの変更が対応方法のひとつでした。

セッション・ステート・コミットの追加は、上記の対応が必要なケースを少なくするでしょう。

また、こちらが本命ですが、Oracle Database側でApplication Continuityの機能を有効にすると、Oracle REST Data ServicesとOracle Databaseの間で障害が発生した際に、失敗したリクエストが自動的に再実行されます。処理のべき等性が確保されていないと問題が発生する可能性があります。

プロセスのPL/SQLコードを記述する際に、あまり暗黙コミットを意識していることはない(プロセスで例外が発生しなければ、中間でコミットしても、最後にコミットしても結果は同じ)と思います。

Oracle DatabaseにApplication Continuity(実際にはTransparent Application Continuity)を設定する場合などで、APEX 23.1以前に作成したアプリケーションのセッション・ステート・コミットの設定を即時からリクエストの終わりに変更する場合は、アプリケーションの動作が変わる可能性があるため、気を付ける必要があります。

APEX 23.1のセッション・ステート・コミットのデフォルトがリクエストの終わりになっていますが、Oracle APEXのアプリケーション開発者は、元々リクエストの終わりにコミットされると理解している場合が多く(プロセスで例外が発生しない限り、暗黙コミットを意識する必要ことはありません)、この点についてはそれほど気にする必要はないかもしれません。

以上になります。Oracle APEXのアプリケーション作成の参考になれば幸いです。