この章では、TimesTenでのX/Open XA標準の実装について説明します。
TimesTenでのXAインタフェースの実装は、トランザクション・マネージャが分散トランザクション処理(DTP)環境で使用することを目的としています。 これらのインタフェースを使用して、TimesTenリソース・マネージャとともに動作するように、新しいトランザクション・マネージャを作成するか、Oracle Tuxedoなどの既存のトランザクション・マネージャを改良できます。
この章では、TimesTenでのXAの実装に固有の情報を示します。また、必要に応じて、次のドキュメントも参照してください。
X/Open CAE仕様の『Distributed Transaction Processing: The XA Specification』(The Open Group(http://www.opengroup.org
)発行)。
Tuxedoのマニュアル。次の場所から入手できます。
この章の内容は次のとおりです。
重要:
|
この項では、次のXA概念について概要について簡単に説明します。
図6-1に、X/Open DTPモデルによって定義されるインタフェースを示します。
TXインタフェースは、アプリケーションがトランザクション・マネージャとの通信に使用するインタフェースです。 図は、グローバル・トランザクションをトランザクション・マネージャに送信するアプリケーションを示しています。 DTPモデルでは、トランザクション・マネージャが、各グローバル・トランザクションを複数のブランチに分割し、それらを別々のリソース・マネージャに分散して処理します。 トランザクション・マネージャは、XAインタフェースを使用して、各トランザクション・ブランチと適切なリソース・マネージャを組み合せます。
TimesTen XAでは、リソース・マネージャは、TimesTenデータ・ストアで構成するか、またはXAをサポートする他の商用データベースとデータ・ストアを組み合せて構成することができます。
TXおよびXAインタフェースによって提供されるグローバル・トランザクションの制御は、ネイティブのODBCインタフェースによって提供されるローカル・トランザクションの制御とは異なります。通常は、ローカル・トランザクションとグローバル・トランザクションで別々の接続を維持することをお薦めします。アプリケーションは、TimesTenリソース・マネージャに対する接続ハンドルを取得して、同じ接続上でローカル・トランザクションおよびグローバル・トランザクションの両方を開始できます。 詳細は、「XA接続からODBCハンドルを取得するTimesTen tt_xa_context関数」を参照してください。
XAの実装では、トランザクション・マネージャは、2フェーズ・コミットのプロトコルを使用して、分散されたグローバル・トランザクションのブランチをコミットします。
第1フェーズでは、トランザクション・マネージャは、各リソース・マネージャに対してコミットを準備するように命令します。これは、グローバル・トランザクションの各ブランチがコミット可能であることを確認し、保証するためです。 リソース・マネージャでブランチをコミットできない場合、トランザクション・マネージャは第2フェーズでトランザクション全体をロールバックします。
第2フェーズでは、トランザクション・マネージャは、各リソース・マネージャにブランチをコミットするように命令します。また、第1フェーズでコミットできなかったことがリソース・マネージャにレポートされている場合は、グローバル・トランザクションをロールバックします。
次の最適化に注意してください。
トランザクション・マネージャは、グローバル・トランザクションに1つのブランチのみが含まれるように指定した場合、第1フェーズをスキップして、第2フェーズでトランザクションをコミットします。
グローバル・トランザクション・ブランチが読取り専用で、トランザクション・ログ・レコードが生成されない場合、トランザクション・マネージャは第1フェーズでそのブランチをコミットし、ブランチの第2フェーズをスキップします。
注意: トランザクション・マネージャでは、すべてのブランチが正常にコミットされた場合にのみ、グローバル・トランザクションがコミットされたと認識されます。 |
TimesTenでのXAの実装によって、『Distributed Transaction Processing: The XA Specification』で指定されているAPIと同じAPIが提供されます。 この項では、TimesTenでのXAの実装を使用する際に必要な前提知識について説明します。内容は次のとおりです。
グローバル・トランザクションの一貫性を保証するには、TimesTen XAのトランザクション・ブランチが永続的である必要があります。 xa_prepare()
、xa_rollback()
およびxa_commit()
関数のTimesTenの実装では、DurableCommits
接続属性の設定値またはttDurableCommit
組込みプロシージャを使用したかどうかに関係なく、実行された処理をディスクに記録します。 障害からのリカバリが必要な場合は、リソース・マネージャおよびTimesTenトランザクション・マネージャの両方に、障害発生時にアクティブ(準備された状態)であったトランザクション・ブランチに関する一貫性のあるビューが含まれます。
トランザクションのロールバックにはトランザクション・ロギングが必要であり、これは常にXAで有効になっています。
障害発生または予期しない終了の後にTimesTenデータ・ストアがディスクからロードされてリカバリが行われると、準備されたもののコミットされていないグローバル・トランザクションが保留中(インダウト)の状態のままになります。通常の処理は、すべてのインダウト・トランザクションの処理が解決されるまで有効になりません。
接続およびリカバリが完了すると、TimesTenは、インダウト・トランザクションを確認します。インダウト・トランザクションがない場合は、処理を通常どおり続行します。インダウト・トランザクションがある場合は、他の接続が作成されることもありますが、インダウト・トランザクションが解決されるまで、これらの接続でのすべての処理が事実上禁止されます。 他のすべてのODBCまたは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 XA関数の使用に関するいくつかの問題について説明します。独自のトランザクション・マネージャを作成する場合に必要となる情報です。
xa_open()
で使用されるxa_info
文字列は、次のようなSQLDriverConnect
で指定される文字列と同じ接続文字列である必要があります。
"DSN=DataStoreResource;UID=MyName"
XAでは、文字列の長さは256文字に制限されます。 xa.h
ヘッダー・ファイルのMAXINFOSIZEを参照してください。
xa_open()
関数は、XA接続をオープンするときに、自動的にAUTOCOMMITをOFFにします。
xa_open()
でオープンされている接続は、xa_close()
をコールしてクローズする必要があります。
注意: TimesTenデータ・ストアに接続するための権限は、CREATE SESSION権限を使用して、インスタンス管理者以外のすべてのユーザーに明示的に付与する必要があります。「接続のアクセス制御」を参照してください。 |
XAでは、XIDと呼ばれるトランザクションIDを使用してグローバル・トランザクションを一意に識別します。XIDは、トランザクションを処理するXA関数に必要なパラメータです。内部的に、TimesTenはXIDを独自のトランザクション識別子にマップします。
XA標準で定義されたXIDは、long
型として定義されたメンバー(formatID
、gtrid_length
、bqual_length
など)の一部を持ちます。 このため、32ビットのクライアント・アプリケーションで64ビットのサーバーに接続したり、64ビットのクライアント・アプリケーションで32ビットのサーバーに接続する場合に、問題が発生する可能性があることに注意してください。 これは、long
が32ビットのプラットフォームでは32ビットの整数になり、64ビットのプラットフォーム(64ビットのWindows以外)では64ビットの整数となるためです。したがって、TimesTenは、クライアントまたはサーバーのプラットフォームのタイプに関係なく、これらのXIDメンバーの最小有効32ビットのみを内部的に使用します。 TimesTenでは、32ビットの整数に適合しないXIDメンバーの値はサポートされません。
TimesTenには関数tt_xa_context()
があり、この関数を使用すると、xa_open()
でオープンされるXA接続に関連付けられているODBC接続ハンドルを取得できます。
構文
#include <tt_xa.h> int tt_xa_context(int *rmid, SQLHENV *henv, SQLHDBC *hdbc);
パラメータ
パラメータ | 型 | 説明 |
---|---|---|
rmid (入力) |
int | 指定したリソース・マネージャID(rmid )がNULL以外の場合、そのrmid の値に関連付けられているハンドルが関数によって返されます。
指定した |
henv (出力) |
SQLHENV | 現在のxa_open() コンテキストに関連付けられている環境ハンドル。 |
hdbc (出力) |
SQLHDBC | 現在のxa_open() コンテキストに関連付けられている接続ハンドル。 |
戻り値
0: 成功
1: rmid
が見つかりません
-1: 無効なパラメータです
例
次の例では、すでにTuxedoによってxa_open()
およびxa_start()
が使用され、データ・ストアへの接続がオープンし、トランザクションが開始しています。 さらに接続のODBC処理を続行するために、tt_xa_context()
関数を使用して、xa_open()
で割り当てられているSQLHENVおよびSQLHDBCハンドルを検出します。
例6-1 tt_xa_context()を使用したハンドルの検出
do_insert() { SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; /* retrieve the handles for the current connection */ tt_xa_context(NULL, &henv, &hdbc); /* now we can do our ODBC programming as usual */ SQLAllocStmt(hdbc, &hstmt); SQLExecDirect(hstmt, "insert into t1 values (1)", SQL_NTS); SQLFreeStmt(hstmt, SQL_DROP); }
この項では、xa_open()
でオープンされるXA接続に関連付けられているODBCハンドルを使用してODBC関数をコールする際に注意する必要があるTimesTenの問題について、いくつか説明します。
処理を簡素化し、矛盾の発生を回避するために、xa_open()
は、XA接続をオープンするときに、AUTOCOMMITを自動的にOFFにします。
その後、ローカル・トランザクション処理の実行中に、AUTOCOMMITをONまたはOFFにする場合がありますが、xa_start()
をコールしてグローバル・トランザクション・ブランチでの処理を開始する前には、OFFにする必要があります。AUTOCOMMITがONの場合、xa_start()
をコールすると次のエラーが返されます。
Error 11030 - "Autocommit must be turned off when working on global (XA) transactions"
xa_start()
をコールしてグローバル・トランザクション・ブランチでの処理を開始した後、xa_end()
をコールしてその処理を完了するまで、AUTOCOMMITをONにできない場合があります。 この場合、AUTOCOMMITをONにしようとすると、前述と同じエラーが発生します。
xa_start()
をコールしてグローバル・トランザクション・ブランチでの処理を開始した後、SQLTransact
を使用してローカルのCOMMITまたはROLLBACKを実行しようとすると、次のエラーが発生します。
Error 11031- "Illegal combination of local transaction and global (XA) transaction"
各リソース・マネージャは、xa.h
ヘッダー・ファイルにスイッチを定義します。ヘッダー・ファイルによって、トランザクション・マネージャはリソース・マネージャ内のXA関数にアクセスできます。トランザクション・マネージャでは、XAインタフェース関数を直接コールしません。かわりに、スイッチ表の関数をコールします。スイッチ表は、リソース・マネージャ内の該当する関数を指します。 これによって、アプリケーションを再コンパイルしなくても、リソース・マネージャを追加および削除できます。
TimesTenでのXAの実装では、XAスイッチxa_switch_t
の関数は、TimesTenスイッチtt_xa_switch
で定義されているそれぞれの関数を指します。
XA仕様によって定義されているxa_switch_t
構造体は次のとおりです。
/* * XA Switch Data Structure */ #define RMNAMESZ 32 /* length of resource manager name, */ /* including the null terminator */ #define MAXINFOSIZE 256 /* maximum size in bytes of xa_info strings, */ /* including the null terminator */ struct xa_switch_t { char name[RMNAMESZ]; /* name of resource manager */ long flags; /* resource manager specific options */ long version; /* must be 0 */ int (*xa_open_entry)(char *, int, long); /* xa_open function pointer */ int (*xa_close_entry)(char *, int, long); /* xa_close function pointer*/ int (*xa_start_entry)(XID *, int, long); /* xa_start function pointer */ int (*xa_end_entry)(XID *, int, long); /* xa_end function pointer */ int (*xa_rollback_entry)(XID *, int, long); /* xa_rollback function pointer */ int (*xa_prepare_entry)(XID *, int, long); /* xa_prepare function pointer */ int (*xa_commit_entry)(XID *, int, long); /* xa_commit function pointer */ int (*xa_recover_entry)(XID *, long, int, long); /* xa_recover function pointer*/ int (*xa_forget_entry)(XID *, int, long); /* xa_forget function pointer */ int (*xa_complete_entry)(int *, int *, int, long); /* xa_complete function pointer */ }; typedef struct xa_switch_t xa_switch_t; /* * Flag definitions for the RM switch */ #define TMNOFLAGS 0x00000000L /* no resource manager features selected */ #define TMREGISTER 0x00000001L /* resource manager dynamically registers */ #define TMNOMIGRATE 0x00000002L /* RM does not support association migration */ #define TMUSEASYNC 0x00000004L /* RM supports asynchronous operations */
tt_xa_switch
では、TimesTenリソース・マネージャで実装されている実際の関数に名前を付けます。 また、関連移行がサポートされていないことを明示的に示します。 なお、動的な登録と非同期の処理もサポートされません。
struct xa_switch_t tt_xa_switch = { "TimesTen", /* name of resource manager */ TMNOMIGRATE, /* RM does not support association migration */ 0, tt_xa_open, tt_xa_close, tt_xa_start, tt_xa_end, tt_xa_rollback, tt_xa_prepare, tt_xa_commit, tt_xa_recover, tt_xa_forget, tt_xa_complete };
XA仕様には、XAインタフェース・コールから返すことが可能な一連のエラーが含まれています。これらのエラーは、制限され、厳密に定義されています。 ODBC SQLError
関数は、XAで定義されたエラーを追加情報ととともに返します。
TimesTen XA関連のエラーは11000番から始まります。11002から11020のエラーは、XA標準で定義されたエラーと対応しています。
エラーの完全なリストは、『Oracle TimesTen In-Memory Databaseエラー・メッセージおよびSNMPトラップ』の「警告およびエラー」を参照してください。
この項では、XAをWindows ODBCドライバ・マネージャとともに使用する場合の問題点および手順について説明します。 (UNIX ODBCドライバ・マネージャについては対象としていません。)
ODBCドライバ・マネージャを介したXAサポートには特別な処理が必要です。次の2つの基本的な問題があります。
XAインタフェースは、定義済のODBCインタフェースには含まれていません。アプリケーションでXA記号が直接参照される場合は、すべての外部参照を解決するために、ドライバ・マネージャ・ライブラリのみとリンクすることはできません。
設計では、SQLConnect
またはSQLDriverConnect
をコールすると、接続時にドライバ・マネージャがロードするドライバ.dll
ファイルを決定します。XAは、xa_open()
を介して接続をオープンする必要があることを命令します。 ただし、接続処理中に.dll
がロードされるまで、適切なxa_open()
エントリ・ポイントを指定することはできません。
基本的に各XAの実装は独自のものであるため、通常、DBMSの移植性というドライバ・マネージャの目的はここでは適用できないことに注意してください。ドライバ・マネージャでXA対応のアプリケーションをサポートする主な利点は、TimesTen固有のアプリケーションをTimesTenの直接ドライバまたはTimesTenのClient/Serverドライバを使用して透過的に実行できることです。
Windowsインストールでは、TimesTenによってXA関数用に、ドライバ・マネージャの拡張ライブラリttxadm1121.dll
が提供されます。アプリケーションは、XAを直接コールすることができますが、拡張ライブラリにリンクする必要があります。
ttxadm1121.dll
ライブラリとリンクするには、リンク行のodbc32.lib
の前にttxadm1121.lib
を含める必要があります。次に例を示します。
# Link with the ODBC driver manager appldm.exe:appl.obj $(CC) /Feappldm.exe appl.obj ttxadm1121.lib odbc32.lib
注意: XAドライバ・マネージャの拡張機能は、32-bitのWindowsアプリケーションでのみ実装されます。 |
注意: TimesTen XAはOracle Tuxedoトランザクション・マネージャと連携して動作することが実証されていますが、TimesTenでのXAの実装範囲を超えるDTPソフトウェアの動作は保証されていません。 |
TimesTenリソース・マネージャを使用するようにTuxedoを構成するには、次のタスクを実行します。
注意: この項の例では、直接ドライバを使用します。 また、クライアント/サーバー・ライブラリまたはドライバ・マネージャ・ライブラリをXA拡張ライブラリとともに使用することもできます。 |
TimesTen XAリソース・マネージャをOracle Tuxedoシステムに統合するには、TimesTenリソース・マネージャ、TimesTenリソース・マネージャ・スイッチの名前(tt_xa_switch
)およびリソース・マネージャのライブラリの名前を示すように$TUXDIR/udataobj/RM
ファイルを更新します。
UNIXプラットフォームで、次の行を追加します。
TimesTen:tt_xa_switch:-Linstall_dir/lib -ltten
次に例を示します。
TimesTen:tt_xa_switch:-L/opt/TimesTen/giraffe/lib -ltten
Windowsプラットフォームで、次の行を追加します。
TimesTen;tt_xa_switch;install_dir\lib\ttdv1121.lib
次に例を示します。
TimesTen;tt_xa_switch;C:\TimesTen\giraffe\lib\ttdv1121.lib
注意: install_dir は、TimesTenホーム・ディレクトリのパスです。 |
buildtms
コマンドを使用して、TimesTenリソース・マネージャ用のトランザクション・マネージャ・サーバーを構築します。 その後、buildtms
で作成したTMS_TT
ファイルを$TUXDIR/bin
ディレクトリにコピーします。
UNIXプラットフォームでは、コマンドは次のようになります。
buildtms -o TMS_TT -r TimesTen -v cp TMS_TT $TUXDIR/bin
Windowsプラットフォームでは、コマンドは次のようになります。
buildtms -o TMS_TT -r TimesTen -v copy TMS_TT.exe %TUXDIR%\bin
TMSNAMEにbuildtms
コマンドで作成したTMS_TT
ファイルを指定します(前述の項を参照)。
TMSNAME=TMS_TT
各TimesTenリソース・マネージャについて、グループ名の後にLMID、GRPNOおよびOPENINFOパラメータが続く行を入力します。 OPENINFO文字列は、次のようになります。
OPENINFO="TimesTen:DSN=DSNname"
DSNname
は、TimesTenデータ・ストアの名前です。
Windowsでは、TuxedoサーバーはユーザーSYSTEMとして実行されることに注意してください。OPENINFO文字列にUID接続属性を追加して、接続のためのSYSTEM以外のユーザーを指定します。
OPENINFO="TimesTen:DSN=DSNname;UID=user"
どのTimesTenリソース・マネージャにもCLOSEINFOパラメータを指定しないでください。
例6-2に、GROUP1とGROUP2という2つのTimesTenリソース・マネージャの構成に使用するUBBCONFIGファイルの一部を示します。
例6-2 TimesTenリソース・マネージャの構成
*RESOURCES ... *MACHINES ... ENGSERV LMID=simple *GROUPS DEFAULT: TMSNAME=TMS_TT TMSCOUNT=2 GROUP1 LMID=simple GRPNO=1 OPENINFO="TimesTen:DSN=MyDSN1;UID=MyName" GROUP2 LMID=simple GRPNO=2 OPENINFO="TimesTen:DSN=MyDSN2;UID=MyName" *SERVERS DEFAULT: CLOPT="-A" simpserv1 SRVGRP=GROUP1 SRVID=1 simpserv2 SRVGRP=GROUP2 SRVID=2 *SERVICES TOUPPER TOLOWER
TimesTenヘッダー・ファイルを保持するinstall_dir
/include
ディレクトリを含めるようにCFLAGS環境変数を設定します。 その後、buildserver
コマンドを使用して、Oracle Tuxedo ATMIサーバー・ロード・モジュールを構成します。
UNIXプラットフォームで、次の行を入力します。
export CFLAGS=-Iinstall_dir/include
buildserver -o server -f server.c -r TimesTen -s SERVICE
Windowsプラットフォームで、次の行を入力します。
set CFLAGS=-Iinstall_dir\Include
buildserver -o server -f server.c -r TimesTen -s SERVICE
注意: install_dir は、TimesTenホーム・ディレクトリのパスです。 |
例6-3に、buildclient
コマンドを使用してクライアント・モジュール(simpcl
)を構成する方法と、buildserver
コマンドを使用して例6-2のUBBCONFIG
ファイルに記述されている2つのサーバー・モジュールを構成する方法の例を示します。