38 セッションレス・トランザクション
セッションレス・トランザクションは、トランザクションのライフサイクル中にトランザクションを柔軟に中断および再開できるトランザクションです。
セッションレス・トランザクションを使用する場合は、Oracle Database (シングル・インスタンスまたはマルチ・インスタンス)との通信時にトランザクション・マネージャを使用する必要はありません。そのトランザクションを調整する作業すべてが、データベースによって実行されます。さらに、アプリケーション側のロジックを必要とせずに、データベースによって内部的に2フェーズ・コミット(2PC)プロトコルが調整されます。
ノート:
この機能は、Oracle Databaseリリース23aiバージョン23.6以降でのみサポートされています。38.1 セッションレス・トランザクションについて
セッションレス・トランザクションでは、トランザクションとセッションの間の結合が切断されています。トランザクションを開始した後に、それをセッションや接続に関連付ける必要はありません。
セッションまたは接続を解放して、それを別のクライアントで使用できるようにすることができます。また、XAプロトコルの調整にトランザクション・マネージャは必要ありません。これは、2フェーズ・コミット・プロセスとエラー・リカバリ・プロセスがデータベースによって自動的に処理されるためです。したがって、インダウト・トランザクションのリスクはなく、リカバリ・メカニズムの必要性はありません。セッションレス・トランザクション、そのユースケースおよび利点の詳細は、Database開発ガイドのセッションレス・トランザクションを使用したアプリケーションの開発を参照してください。
ノート:
セッションレス・トランザクションは、単一データベースにのみ適用されます。セッションレス・トランザクションを使用して、複数のリソース・マネージャにまたがるトランザクションを管理しないでください。38.2 JDBC APIの使用によるセッションレス・トランザクションの管理
この項で説明するJDBC APIを使用して、新しいトランザクションの開始、既存トランザクションの再開、トランザクションの中断、変更内容のコミットまたはロールバックによるトランザクションの終了を実行します。
これらのAPIは、oracle.jdbc
パッケージのOracleConnection
インタフェースで使用できます。Oracle® Database JDBC Java APIリファレンスを参照してください。
この項の内容は次のとおりです:
38.2.1 セッションレス・トランザクションの開始
oracle.jdbc
パッケージのOracleConnection
インタフェースにあるstartTransaction()
メソッドを使用してセッションレス・トランザクションを開始します。トランザクションについて、一意のグローバル・トランザクションID (GTRID)およびタイムアウトを指定できます。
startTransaction()
ではデータベースに対するラウンドトリップは実行されないため、これは非同期コールです。かわりに、Oracle JDBC Thinドライバにより、Oracle Databaseへの次のラウンドトリップの実行時に、セッションレス・トランザクションを開始するリクエストが送信されます。トランザクションは、サーバーからそのコールが正常に返された場合のみ開始されます。
セッションレス・トランザクションを開始するには、次のタスクを実行します:
新しいセッションレス・トランザクションが開始されると、それがアクティブ状態になります。トランザクションのGTRIDは、一意である必要があります。新しいセッションレス・トランザクションを開始するリクエストを発行したときに、アクティブなセッションレス・トランザクションがすでに存在する場合は、Oracle Databaseによって既存のトランザクションが中断され、リクエストに基づいて新しいセッションレス・トランザクションが開始されます。
38.2.2 GTRIDの取得
現在アクティブ状態であるセッションレス・トランザクションのGTRIDを取得します。
例
GTRIDの取得では、そのセッションレス・トランザクションの、ローカルでの状態が反映されます。サーバーでの状態ではありません。次のシナリオを使用してこれについて説明します。startTransaction()
は非同期コールであり、それによってデータベースに対するラウンドトリップは実行されません。かわりに、Oracle JDBC Thinドライバにより、Oracle Databaseへの次のラウンドトリップの実行時に、セッションレス・トランザクションを開始するリクエストが送信されます。トランザクションは、サーバーからそのコールが正常に返された場合のみ開始されます。
...
conn.startTransaction();
byte[] gtrid = getTransactionId();
...
トランザクションは次のラウンドトリップまではサーバー上で実際に開始されていませんが、getTransactionId()
では、Oracle JDBC Thinドライバで生成されたGTRIDの値が返されます。
38.2.3 セッションレス・トランザクションの中断
アクティブなセッションレス・トランザクションを中断します。
38.2.4 セッションレス・トランザクションの再開
中断したセッションレス・トランザクションを再開します。
セッションレス・トランザクションが、それを再開するリクエストを送信するときに中断状態であった場合は、これによってそのトランザクションが再開されます。セッションレス・トランザクションは、トランザクションの再開をリクエストしたインスタンス上で再開されます。セッションレス・トランザクションが再開されると、それがアクティブ状態になります。
セッションにおいてトランザクションを再開するリクエストを送信したときに、そのセッションで別のセッションレス・トランザクションがすでにアクティブになっている場合は、Oracle Databaseによって、まずそのトランザクションの中断が試みられた後に、再開操作が実行されます。
resumeTransaction()
ではデータベースに対するラウンドトリップは実行されないため、これは非同期コールです。かわりに、Oracle JDBC Thinドライバにより、Oracle Databaseへの次のラウンドトリップの実行時に、セッションレス・トランザクションを再開するリクエストが送信されます。トランザクションは、サーバーからそのコールが正常に返された場合のみ再開されます。
38.2.5 例
この項では、セッションレス・トランザクション機能を使用するように既存のアプリケーション・コードを変更する例を示します。
セッションレス・トランザクションを使用しない既存のサンプル・コード
アプリケーションで、開始するトランザクションの処理中にセッションのロックを回避する必要があり、いくつかの更新を加えてから、他のサービスに複数回コールを発行する場合について考えてみましょう。他のサービスから結果を取得した後は、トランザクションの処理を続行します。セッションレス・トランザクションを使用する場合に必要となる変更内容の比較のための参考として、コード例を次に示します。次のコードでは、セッションレス・トランザクションを使用しないアプリケーションの実装例を示します。
PoolDataSource ds;
Connection conn = ds.getConnection();
conn.setAutoCommit(false);
// update database
// Fetch some data from other services(takes a while)
// do more updates on the database
conn.commit();
conn.close();
セッションレス・トランザクションを使用するための最適化されたサンプル・コード
次のサンプル・コードでは、セッションレス・トランザクションを使用するための最適化されたサンプル・コードを提供します。oracle.jdbc
パッケージのOracleConnection
インタフェースにあるJDBC APIを使用してセッションレス・トランザクションを管理するには、次のサンプル・コードで示すように、接続オブジェクトをOracleConnection
にキャストする必要があります。
import oracle.jdbc.*;
PoolDataSource ds;
// GTRID is the unique identifier for a session.
byte[] gtrid;
// Acquire a session on instance 1.
Connection conn = ds.getConnection();
conn.setAutoCommit(false);
// Start a sessionless transaction with a unique identifier on instance 1
gtrid = (OracleConnection(conn)).startTransaction();
// Update database
(OracleConnection(conn)).conn.suspend();
conn.close();
// Fetch some data from other services, which takes a while
Connection conn2 = ds.getConnection();
conn2.setAutoCommit(false);
// Resume the sessionless transaction using the unique identifier,
// that you had defined earlier, on instance 2.
(OracleConnection(conn2)).resumeTransaction(gtrid);
// do more updates on the database
conn2.commit();
conn2.close();
38.3 既存のXA APIによるセッションレス・トランザクションの管理
この項では、既存のXAResource
インタフェースを使用してセッションレス・トランザクションを管理する方法について説明します。
セッションレス・トランザクションは、XAトランザクション用に使用されるAPIと互換性があります。Oracle JDBC ThinドライバでXA APIを使用してセッションレス・トランザクションを処理する必要がある場合は、oracle.jdbc.XAThroughSessionlessTransactions
システム・プロパティをtrue
に設定します。ドライバにより、トランザクション・マネージャによって提供されたXIDが、セッションレス・トランザクションの一意の識別子であるGTRIDに変換されます。デフォルトでは、oracle.jdbc.XAThroughSessionlessTransactions
はfalse
に設定されます。
制限事項:
- セッションレス・トランザクションを使用できるのは、アプリケーションで、1つのサーバーまたはRACで実行されている単一のOracle Databaseに接続する場合のみです。
- セッションレス・トランザクションに、他のリソース・マネージャ(別のデータベースなど)を関連付けることはできません。
XA APIを使用してセッションレス・トランザクションを管理する場合は、アプリケーションを実行する前に、コマンドラインを使用して次のシステム・プロパティ値を設定します。
既存のアプリケーション・コードでXAトランザクションが使用されておりXAResource
インタフェースが実装されている場合は、同じコードを使用してセッションレス・トランザクションを管理できます。oracle.jdbc.XAThroughSessionlessTransactions
プロパティ値を設定すると、次の表で説明するように、XAResource
インタフェースにあるメソッドの動作が変更され、トランザクションがセッションレス・トランザクションとして処理されます。このようにして、既存のアプリケーションのコードを大幅に変更する必要なく、セッションレス・トランザクションのパフォーマンス改善によるメリットを得ることができます。
メソッド | 説明 |
---|---|
xaResource.start(xid, XAResource.TMNOFLAGS); |
セッションレス・トランザクションを開始します。 |
xaResource.start(xid, XAResource.TMRESUME); |
セッションレス・トランザクションを再開します。 |
(OracleXAResource).suspend(xid); |
セッションレス・トランザクションを中断します。 |
xaResource.end(xid1, XAResource.TMSUSPEND); |
セッションレス・トランザクションを中断します。 |
xaResource.end(xid2, XAResource.TMSUCCESS); |
セッションレス・トランザクションを中断します。 |
xaResource.setTransactionTimeout(seconds); |
トランザクション・タイムアウト値(秒)を設定します。 |
xaResource.commit(xid, true); |
セッションレス・トランザクションをコミットします。これは、まずトランザクションを再開してから、トランザクションをコミットします。 |
xaResource.rollback(xid); |
セッションレス・トランザクションをロールバックします。これは、まずトランザクションを再開してから、トランザクションをロールバックします。 |
xaResource.join(xid); |
セッションレス・トランザクションの場合、操作は実行されません。 |
xaResource.prepare(xid); |
セッションレス・トランザクションの場合、操作は実行されません。 |
xaResource.recover(XAResource.TMSTARTRSCAN);
|
XAリカバリは、セッションレス・トランザクションではサポートされていません。これにより、例外がスローされます。 |
xaResource.forget(xid); |
セッションレス・トランザクションの場合、操作は実行されません。 |
xaResource1.isSameRM(xaResource2); |
セッションレス・トランザクションの場合、操作は実行されません。 |
XAResource
インタフェースの詳細は、https://docs.oracle.com/javase/8/docs/api/javax/transaction/xa/XAResource.htmlを参照してください。
OracleConnection
インタフェースで定義されているJDBC APIを使用して、クライアント・アプリケーションでセッションレス・トランザクションを管理することもできます。「JDBC APIの使用によるセッションレス・トランザクションの管理」を参照してください。