ここでは、TimesTenに実装されているJavaトランザクションAPI(JTA)について説明します。
TimesTenに実装されているJava JTAインタフェースは、Javaアプリケーション、アプリケーション・サーバーおよびトランザクション・マネージャを有効化して、分散トランザクション処理(DTP)環境でTimesTenリソース・マネージャを使用することを目的にしています。 TimesTenのこの実装はOracle WebLogic Serverで使用するためにサポートされています。
この章では、TimesTenにおけるJTAの実装に固有の情報を説明します。また、次のドキュメントもあわせて参照してください。
JTAおよびJDBCのドキュメントは、次のSun Microsystems社のURLから利用可能です。
WebLogicのドキュメントは、次のURLから利用可能です。
TimesTen JTAは、X/Open XA標準のTimesTen実装の最初の部分であるため、ここでの説明の多くは基本的なXA機能に関することです。 『Oracle TimesTen In-Memory Database C開発者ガイド』のXAの分散トランザクション処理に関する項も参照してください。
この章の内容は次のとおりです。
重要:
|
この項では、次のXA概念の概要を簡単に説明します。
図4-1 にX/Open DTPモデルによって定義されるインタフェースを示します。
TXインタフェースとは、トランザクション・マネージャとの通信に使用するアプリケーションです。 この図はグローバル・トランザクションをトランザクション・マネージャに伝達するアプリケーションを示しています。 DTPモデルでは、トランザクション・マネージャは、各グローバル・トランザクションを複数のブランチに分割し、分割したグローバル・トランザクションを別々のリソース・マネージャのサービスに分散させます。 トランザクション・マネージャは、JTAインタフェースを使用して、各トランザクション・ブランチと適切なリソース・マネージャを調整します。
TimesTen JTAのコンテキストでは、リソース・マネージャは、TimesTenデータ・ストアのコレクションの場合と、JTAをサポートする他の商用データベースと組み合せたデータ・ストアのコレクションの場合があります。
TXおよびJTAインタフェースで提供されるグローバル・トランザクション制御は、ネイティブのJDBCインタフェースで提供されるローカル・トランザクション制御とは異なります。 一般に、ローカル・トランザクションおよびグローバル・トランザクションには別々の接続を使用することをお薦めします。 アプリケーションは、TimesTenリソース・マネージャの接続ハンドルを取得し、ローカル・トランザクションおよびグローバル・トランザクションの両方を同じ接続で開始することができます。
JTAの実装においてトランザクション・マネージャは、グローバル・トランザクションの分散したブランチを2フェーズ・コミット・プロトコルを使用してコミットします。
第1フェーズでは、トランザクション・マネージャは各リソース・マネージャに対してコミットを準備するように指示します。これは、グローバル・トランザクションの各ブランチがコミット可能であることを確認し、保証するためです。 リソース・マネージャが各ブランチをコミットできない場合、トランザクション・マネージャは、第2フェーズでトランザクション全体をロールバックします。
第2フェーズでは、トランザクション・マネージャは各リソース・マネージャにブランチをコミットするように指示しますが、第1フェーズで、コミット不能とレポートされた場合は、グローバル・トランザクションをロールバックするように指示します。
次の最適化された動作に注意してください。
グローバル・トランザクションに含まれるブランチが1つのみであるとトランザクション・マネージャが判断すると、第1フェーズはスキップし、第2フェーズでトランザクションをコミットします。
グローバル・トランザクション・ブランチが読取り専用で、トランザクション・ログ・レコードが生成されない場合、トランザクション・マネージャは第1フェーズでブランチをコミットし、第2フェーズをスキップします。
注意: トランザクション・マネージャは、すべてのブランチを正常にコミットしたときにかぎり、グローバル・トランザクションがコミットされたとみなします。 |
この項では、TimesTenでJTAを使用する際の次の考慮事項について説明します。
グローバル・トランザクションの一貫性を保証するには、TimesTen XAのトランザクション・ブランチが永続的である必要があります。 xa_prepare()
、xa_rollback()
およびxa_commit()
ファンクションのTimesTen実装では、DurableCommits
接続属性の設定値またはttDurableCommit
組込みプロシージャを使用したかどうかに関係なく、実行された処理をディスクに記録します。 障害からのリカバリが必要な場合は、リソース・マネージャおよびTimesTenトランザクション・マネージャの両方に、障害発生時に準備された状態でアクティブだったトランザクション・ブランチに関する一貫性のあるビューが含まれています。
トランザクションのロールバックに必要なトランザクション・ロギングは、XAで常に有効にされています。
障害または予期しない終了の後、リカバリのためにTimesTenデータ・ストアがディスクからロードされたとき、準備されたが、コミットされていないすべてのグローバル・トランザクションは保留中(インダウト)の状態のままです。 すべてのインダウト・トランザクションが解決されるまで、通常の処理は行えません。
接続およびリカバリが完了すると、TimesTenはインダウト・トランザクションを確認します。 インダウト・トランザクションがない場合は、処理を通常どおり実行します。 インダウト・トランザクションがあると、他の接続を作成することはできますが、インダウト・トランザクションが解決されるまでは、これらの接続でのすべての処理が事実上禁止されます。 他のすべてのJDBCのコールは次のエラーになります。
Error 11035 - "In-doubt transactions awaiting resolution in recovery must be resolved first"
インダウト・トランザクションのリストは、xa_recover()
のXA実装によって取得した後、XAでxa_commit()
、xa_rollback()
またはxa_forget()
を適切にコールすることによって処理できます。 すべてのインダウト・トランザクションが解消されると、処理が通常通り続行されます。
トランザクション・マネージャでは、接続後にまずxa_recover()
をコールする必要があるため、この方法はトランザクション・マネージャで厳密に制御された状態で動作するシステムに適しています。
トランザクション・マネージャを使用できない場合またはインダウト・トランザクションを解消できない場合は、ttXactAdmin
ユーティリティを使用して、個々のトランザクション・ブランチを個別にコミットするか、または強制終了します。 ただし、このようなttXactAdmin
による方法では、ADMIN権限が必要なことに注意してください。 『Oracle TimesTen In-Memory Databaseリファレンス』のttXactAdminに関する項を参照してください。
TimesTenのJTA実装は、Sun Microsystems社のJTA仕様の規定に準拠したAPIを提供します。 TimesTenのJTAはJDK 1.4以上のバージョンで動作します。
この項では、JTA APIの使用に関する次の内容について説明します。
注意: WebLogicでTimesTen DSNを登録する方法、TimesTenのアプリケーション・サーバーの構成およびオブジェクトリレーショナル・マッピングのフレームワークに関する情報については、次のURLで参照可能です。
|
TimesTen JDBCおよびXA実装は、次のパッケージから利用可能です。
com.timesten.jdbc.*; com.timesten.jdbc.xa.*;
アプリケーションは、次の標準パッケージもインポートする必要があります。
import java.sql.*; import javax.sql.*; import javax.transaction.xa.*;
XAデータ・ソースへの接続は、XADataSource
オブジェクトを経由して確立されます。 TimesTenXADataSource
インスタンスを接続ファクトリとして使用して、TimesTenデータ・ストアに新しいXAConnection
オブジェクトを作成できます。 TimesTenXADataSource
はjavax.sql.XADataSource
インタフェースを実装します。
TimesTenXADataSource
インスタンスを新規に作成したら、setUrl()
メソッドを使用して、TimesTenデータ・ストアを指定します。 URLは次のようになります。
直接接続の場合:
jdbc:timesten:direct:DSNname
クライアント接続の場合:
jdbc:timesten:client:DSNname
setUser()
メソッドおよびsetPassword()
メソッドを任意で使用して、特定のユーザーのIDおよびパスワードを設定することもできます。
例4-1 TimesTen XAデータ・ソース・オブジェクトの作成
この例では、TimesTenXADataSource
オブジェクトをファクトリとして使用して、新しいTimesTen XAデータ・ソース・オブジェクトを作成します。 次に、このTimesTenXADataSource
インスタンスに、TimesTen DSN(dsn1
)、ユーザー名(myName
)およびパスワード(myPasswd
)を識別するURLが設定されます。 次に、getXAConnection()
メソッドが、xaConn
という名前のオブジェクトへ接続を返すために使用されます。
TimesTenXADataSource xads = new TimesTenXADataSource(); xads.setUrl("jdbc:timesten:direct:dsn1"); xads.setUser("myName"); xads.setPassword("myPassword"); XAConnection xaConn = null; try { xaConn = xads.getXAConnection(); } catch (SQLException e){ e.printStackTrace(); return; }
XAデータ・ソース・オブジェクトに対して複数の接続を作成できます。 この例では、xaConn2
という名前で2つ目の接続を作成します。
XAConnection xaConn = null; XAConnection xaConn2 = null; try { xaConn = xads.getXAConnection(); xaConn2 = xads.getXAConnection(); }
例4-2 複数のTimesTen XAデータ・ソース・オブジェクトの作成
この例では、TimesTenXADataSource
の2つのインスタンスを、dsn1
およびdsn2
という名前のTimesTenデータ・ストアに作成します。 次に、dsn1
に1つの接続を作成し、dsn2
に2つの接続を作成します。
TimesTenXADataSource xads = new TimesTenXADataSource(); xads.setUrl("jdbc:timesten:direct:dsn1"); xads.setUser("myName"); xads.setPassword("myPassword"); XAConnection xaConn1 = null; XAConnection xaConn2 = null; XAConnection xaConn3 = null; try { xaConn1 = xads.getXAConnection(); // connect to dsn1 } catch (SQLException e){ e.printStackTrace(); return; } xads.setUrl("jdbc:timesten:direct:dsn2"); xads.setUser("myName"); xads.setPassword("myPassword"); try { xaConn2 = xads.getXAConnection(); // connect to dsn2 xaConn3 = xads.getXAConnection(); // connect to dsn2 } catch (SQLException e){ e.printStackTrace(); return; }
注意: XAConnection が確立されると、自動コミットはオフになります。 |
getXAConnection()
を使用して、XAConnection
オブジェクトを取得した後、XAConnection
メソッドgetXAResource()
を使用して、XAResource
オブジェクトを取得して、次にXAConnection
メソッドgetConnection()
を使用して、基礎となる接続のConnection
オブジェクトを取得できます。
例4-3 XAリソース・オブジェクトおよび接続の取得
//get an XAResource XAResource xaRes = null; try { xaRes = xaConn.getXAResource(); }catch (SQLException e){ e.printStackTrace(); return; } //get an underlying physical Connection Connection conn = null; try { conn = xaConn.getConnection(); }catch (SQLException e){ e.printStackTrace(); return; }
この時点で、同一の接続のconn
を、ローカル・トランザクションおよびグローバル・トランザクションの両方に使用できます。 ただし、次の点に注意してください。
グローバル・トランザクションを開始する前に、アクティブなローカル・トランザクションをコミットまたはロールバックする必要があります。 そうしないと、XAException
例外XAER_OUTSIDEが発生します。
ローカル・トランザクションを初期化する前に、アクティブなグローバル・トランザクションを終了する必要があります。そうしないと、SQLException
、「Illegal combination of local transaction and global (XA) transaction.」が表示されます。