2025年2月14日金曜日

Oracle Database 23ai 23.6のセッションレス・トランザクションを使ってみる

Oracle Databaseの開発ツールのPMであるJeff Smithさんのブログにアクセスしたところ、最近の記事として以下が公開されていました。

Sessionless Transactions in Database 23ai & your REST APIs
https://www.thatjeffsmith.com/archive/2025/02/sessionless-transactions-in-database-23ai-your-rest-apis/

セッションレス・トランザクション!? なんだろうと思ったので上記の記事を読んで、自分でも動作を確認してみました。

Oracle Databaseのトランザクションは基本的にデータベースのセッションに紐づいていますが、セッションレス・トランザクションはセッションと切り離すことができます。

セッションレス・トランザクションを使うと、Oracle REST Data Servicesの連続したREST API呼び出しをひとつのデータベース・トランザクションに含めることができます。

テストに使用したAPEXアプリケーションは以下のように動作します。

ボタンStart, Update, Commit, Rollbackはそれぞれ、1回のREST API呼び出しに対応しています。

ボタンStartをクリックしセッションレス・トランザクションを開始します。呼び出したブラウザにXID - トランザクションIDを返します。ボタンUpdateではそのXIDTextに入力した文字列を引数として、REST API経由で表TEST_SESSIONLESS_TXに文字列を書き込みます。

連続した文字列の書き込みは、ボタンCommitのクリックで確定します。これもREST API呼び出しです。ボタンRollbackをクリックすると、それまで書き込まれた文字列はロールバックされます。


REST APIやSQLclのセッションからはDBMS_TRANSACTION.SUSPEND_TRANSACTIONを呼び出すことができますが、Oracle APEXのプロセスからDBMS_TRANSACTION.SUSPEND_TRANSACTIONを呼び出すと、処理がハングします。Oracle APEXに埋め込まれたSQLはDBMS_SQL(正確にはDBMS_SYS_SQL)パッケージを呼び出して実行されるので、一般的なセッションとは扱いが異なることがハングする理由だと思われます。そのため、セッションレス・トランザクションは概ねOracle REST Data ServicesのREST APIとともに使用することになると思われます。

以下より、上記のサンプル・アプリケーションの実装について簡単に紹介します。

ボタンUpdateをクリックしたときにデータを挿入する表をTEST_SESSIONLESS_TXとして作成しています。画面下に配置されたクラシック・レポートのソースです。

セッションレス・トランザクションを開始、再開するには、DBMS_TRANSACTION.START_TRANSACTIONを呼び出します。

ボタンStartUpdateCommitRollbackの処理に対応するファンクションやプロシージャを組み込んだパッケージTEST_SESSIONLESS_TX_PKGを作成します。

ファンクションSTART_TXがボタンStart、プロシージャUPDATE_TXがボタンUpdate、プロシージャCOMMIT_TXがボタンCommit、プロシージャROLLBACK_TXがボタンRollbackの処理になります。

パッケージTEST_SESSIONLESS_TX_PKGの定義部です。


パッケージTEST_SESSIONLESS_TX_PKGの本体部です。ほとんどはDBMS_TRANSACTION.START_TRANSACTIONを呼び出しセッションレス・トランザクションの開始または再開をした後に、1行データベースの操作を行っているだけです。


これらの処理を呼び出すRESTサービスを作成します。RESTサービス・モジュールとしてsessionlessを作成し、そのテンプレートとしてstartupdatecommitrollbackを作成します。テンプレートstartにはGETハンドラを作成し、それ以外はPOSTハンドラを作成します。ハンドラの処理はすべてPL/SQLで記述します。

処理内容自体は、パッケージTEST_SESSIONLESS_TX_PKGの対応するファンクションまたはプロシージャの呼び出しです。


RESTモジュールsessionlessとして作成したREST APIのブラウザからの呼び出しは、APEXアクションとして実装します。

共有コンポーネントの静的アプリケーション・ファイルとしてtest.jsを作成します。


作成したファイルtest.jsは、ページ・プロパティJavaScriptファイルURLに記述します。

[defer]#APP_FILES#test#MIN#.js


アプリケーションの画面を作成します。

ボタンに紐づけるAPEXアクションのコンテキストを作成するリージョンとしてControlsを作成しています。静的IDCONTROLSを設定しています。REST API呼び出しに関わるボタンはすべてのこのリージョンに含めます。


セッションレス・トランザクションのトランザクションIDを保持するページ・アイテムとして、P1_XIDを作成しています。セッション・ステートストレージリクエストごと(メモリーのみ)を選択します。


ボタンSTARTUPDATECOMMITROLLBACK動作アクションはすべて動的アクションで定義とします。詳細カスタム属性data-action=を設定し、呼び出すAPEXアクションを指定します。


ボタンUpdateをクリックしたときに表TEST_SESSIONLESS_TXに書き込む文字列を入力するページ・アイテムをP1_TEXTとして作成しています。セッション・ステートストレージリクエストごと(メモリーのみ)です。


TEST_SESSIONLESS_TXを一覧するリージョンをクラシック・レポートとして作成しています。ソース表名TEST_SESSIONLESS_TXを指定しています。


ボタンREFRESHを作成し、動的アクションでクラシック・レポートのリージョンをリフレッシュしています。

ボタンUpdateをクリックして表TEST_SESSIONLESS_TXを更新しても、レポートに更新した行は現れません。ボタンCommitをクリックしてレポートをリフレッシュすると、それまでにUpdateした行が表示されます。


ボタンRESETはハウスキーピングに使用します。クリックするとプロセスRESETを呼び出し、表TEST_SESSIONLESS_TXの内容を全削除します。


プロセスRESETソースPL/SQLコードとして以下を記述します。

delete from test_sessionless_tx;

ボタンRESETをクリックしたときに実行されるように、サーバー側の条件ボタン押下時RESETを指定します。


確認用のアプリケーションについての説明は以上です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/test-sessionless-tx.zip

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