ここでは、TimesTenに実装されているJavaトランザクションAPI(JTA)について説明します。
TimesTenに実装されているJava JTAインタフェースは、Javaアプリケーション、アプリケーション・サーバーおよびトランザクション・マネージャを有効化して、分散トランザクション処理(DTP)環境でTimesTenリソース・マネージャを使用することを目的にしています。TimesTenのこの実装はOracle WebLogic Serverで使用するためにサポートされています。
この章では、TimesTenにおけるJTAの実装に固有の情報を説明します。また、次のドキュメントもあわせて参照してください。
JTAおよびJDBCのドキュメントは、次の場所から利用可能です。
WebLogicのドキュメントは、次の場所から利用可能です。
http://www.oracle.com/technetwork/middleware/weblogic/documentation
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トランザクション・マネージャの両方に、障害発生時に準備された状態でアクティブだったトランザクション・ブランチに関する一貫性のあるビューが含まれています。
障害発生または予期しない終了の後にデータベースがディスクからロードされてリカバリが行われると、準備されたもののコミットされていないグローバル・トランザクションが保留中(インダウト)の状態のままになります。すべてのインダウト・トランザクションが解決されるまで、通常の処理は行えません。
接続およびリカバリが完了すると、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ユーティリティの-HCommitまたは-HAbortオプションを使用して、個々のトランザクション・ブランチを個別にコミットまたは強制終了できます。ただし、これらのttXactAdminオプションにはADMIN権限が必要であることに注意してください。『Oracle TimesTen In-Memory Databaseリファレンス』のttXactAdminに関する項を参照してください。
TimesTenのJTA実装は、JTA仕様の規定に準拠したAPIを提供します。TimesTenのJTAはJDK 1.4以上のバージョンで動作します。
この項では、JTA APIの使用に関する次の内容について説明します。
WebLogicでTimesTen DSNを登録する方法、TimesTenのアプリケーション・サーバーの構成およびオブジェクトリレーショナル・マッピングのフレームワークに関する情報については、TimesTenクイック・スタートを参照してください。「Configuration and Setup」の「Java EE and OR Mapping」をクリックしてください。
TimesTen JDBCおよびXA実装は、次のパッケージから利用可能です。
com.timesten.jdbc.*; com.timesten.jdbc.xa.*;
アプリケーションは、次の標準パッケージもインポートする必要があります。
import java.sql.*; import javax.sql.*; import javax.transaction.xa.*;
XAデータ・ソースへの接続は、XADataSourceオブジェクトを経由して確立されます。TimesTenXADataSourceインスタンスを接続ファクトリとして使用して、データベースにXAConnectionオブジェクトを作成できます。TimesTenXADataSourceはjavax.sql.XADataSourceインタフェースを実装します。
TimesTenXADataSourceインスタンスを新規に作成したら、setUrl()メソッドを使用して、データベースを指定します。
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データ・ソース・オブジェクトの作成
この例では、dsn1およびdsn2という名前のデータベース用にTimesTenXADataSourceのインスタンスを2つ作成します。次に、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.」が表示されます。