この方法では,DBMSへのアクセスは一つのDBMSを対象にトランザクション制御を行う方法と同じで,トランザクション制御の部分でTPBroker for C++が提供するOTS機能を使用します。
OTS機能はRed Hat Linux版では使用できません。
複数のDBMSを対象にトランザクション制御を行う場合の動作概要を図2-1に示します。TPBrokerのトランザクション制御では, X/Openで規定されたDTPモデルに準拠し,ユーザアプリケーションをアプリケーションプログラム(AP),DBMSをリソースマネジャ(RM),トランザクション制御を行うTPBrokerをトランザクションマネジャ(TM)と呼びます。
図2-1 複数のDBMSを対象にトランザクション制御を行う場合の動作概要
複数DBMSに対してトランザクション制御する場合(③)は,TPBrokerのメソッドを使ってトランザクションの開始・決着を記述し,その間のDBMSへのアクセス(④)はDABroker for C++のメソッドを使います。このときDABroker for C++のメソッドの延長でDABrokerがトランザクション識別子を取得し,SQLへ付加してDBMSへアクセスします。つまり,DABroker for C++のメソッドを使用するCORBAオブジェクトは別々であっても,トランザクション識別子が引き継がれるような仕組みになっています。
次に図2-1の丸付き数字の順に,必要になる準備,アプリケーションの処理手続きなどを説明します。TPBrokerのコマンドの詳細についてはTPBrokerのマニュアル「トランザクショナル分散オブジェクト基盤TPBrokerユーザーズガイド」を参照してください。
TPBrokerの機能(コマンドなど)を使用してリソースマネジャ(DBMS)のXAインタフェースを利用するために必要な情報をTPBrokerのシステム定義へ設定します。
TPBrokerのシステム定義には,システム環境定義やプロセス監視定義があります。DBMSごとに固有な情報なので,使用するDBMSのドキュメントを参照して登録してください。
例えば,システム環境定義の中のリソースマネジャ定義では,X/Openの規格に従った,オープン文字列,クローズ文字列,環境変数などDBMSで解釈される情報を設定します。設定にはTPBrokerのtskeycreate,tsdefvalueコマンドを使います。
アプリケーションで使用するリソースマネジャ(DBMS)をトランザクションマネジャへTPBrokerのtslnkrmコマンドを使って登録します。登録方法には,動的登録と静的登録があります。
アプリケーションでは,TPBrokerが提供するメソッドを使ってトランザクションの開始と決着を記述します。このトランザクションのことをTPBrokerではグローバルトランザクションと呼んでいます。
グローバルトランザクションの開始と決着はTPBrokerが提供する次のメソッドを使います。
# | 処理 | 使用するTPBroker提供のメソッド |
---|---|---|
1 | 開始 | CosTransactions::Current::begin()メソッド |
2 | 決着(コミット) | CosTransactions::Current::commit()メソッド |
3 | 決着(ロールバック) | CosTransactions::Current::rollback()メソッド |
DBMSへのアクセスは,一つのDBMSを対象にトランザクション制御を行う方法と同様ですが,オブジェクトの生成方法が一部変わります。詳細は次の個所を参照してください。
この指定によって,そのオブジェクト,すなわちDBMSへのアクセスはグローバルトランザクションの制御対象になるわけです。指定しない場合は対象からはずれるので,DABrokerが提供しているトランザクション用のメソッド(DBTransaction)を使って制御します。
作成したアプリケーションのリンケージの際に,次の三つのオブジェクトファイルを付け加えてください。
グローバルトランザクションの開始によってトランザクションの識別子が付与され,アプリケーションとDBMSの間でのアクセスは同じトランザクションの識別子で管理されます。コミットによって該当する識別子を対象にXAインタフェースを使ってトランザクションマネジャとDBMSの間で2相コミットプロトコルが実行されます。
////////////////////////////////////////////////////////////
/// TPBrokerによるトランザクション制御(簡易版)
#include "tsport_c.hh"
#include "tpcosots_c.hh"
#include "dbbroker.h"
DBRDatabase *pDB1
DBRDatabase *pDB2
int main(int argc,char* argv[])
{
pDB1 = NULL;
pDB2 = NULL;
try
{
CORBA::ORB_var orb=CORBA::ORB_init(argc,argv);
CORBA::BOA_var boa=orb->BOA_init(argc,argv);
CORBA::Object_var obj=orb->resolve_initial_referrences
("TransactionCurrent");
CosTransactions::Current_var current=
CosTransactions::Current::_narrow(obj);
current->begin(); // グローバルトランザクションの開始
try
{
pDB1 = new DBRDatabase(DRV_TYPE_ORACLE7,"XA");
pDB1->Connect("orauser", "orapw1", "ORA1");
pDB1->ExecuteDirect("INSERT INTO SAMPLETABLE
VALUES(1,'ABC')");
pDB2 = new DBRDatabase(DRV_TYPE_ORACLE7,"XA");
pDB2->Connect("orauser2", "orapw2", "ORA2");
pDB2->ExecuteDirect("INSERT INTO SAMPLETABLE2
VALUES(2,'DEF')");
current->commit(1);
// グローバルトランザクションのコミット
pDB1->Close();
pDB2->Close();
}
catch (DBSQLCA& ca)
{
current->rollback();
// グローバルトランザクションのコミット
// エラー処理
}
}
catch(CORBA::SystemExecution se)
{
// エラー処理
}
if(pDB1)
delete pDB1;
if(pDB2)
delete pDB2;
return();
}
///////////////////////////////////////////////////////////
/// TPBrokerによるトランザクション制御(詳細版)
#include "tsport_c.hh"
#include "tpcosots_c.hh"
#include "dbbroker.h"
DBDriverManager * pDrvMan;
int main(int argc, char* argv[])
{
pDrvMan = NULL;
try
{
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
CORBA::Object_var obj = orb->resolve_initial_references
("TransactionCurrent");;
CosTransactions::Current_var current =
CosTransactions::Current::_narrow(obj);
current->begin(); // グローバルトランザクションの開始
try
{
pDrvMan = new DBDriverManager;
pDrvMan->InitializeMessage();
// OTS機能を使用したトランザクション制御の使用
DBDriver* pDriver =
pDrvMan->Driver(DRV_TYPE_ORACLE7,"XA");
DBConnection* pConnect1 = pDriver->Connect
("Sample1", "orauser1", "orapw1", "ORA1");
DBConnection* pConnect2 = pDriver->Connect
("Sample2", "orauser2" , "orapw2","ORA2");
pConnect1->ExecuteDirect
("INSERT INTO SAMPLETABLE VALUES (1,'ABC')");
pConnect2->ExecuteDirect
("INSERT INTO SAMPLETABLE VALUES (2,'DEF')");
current->commit(1); // トランザクションのコミット
pConnect1->Close();
pConnect2->Close();
}
catch (DBSQLCA& ca)
{
current->rollback();
// トランザクションのロールバック
//エラー処理
}
}
catch (CORBA::SystemException se)
{
//エラー処理
}
if(pDrvMan)
delete pDrvMan;
return 0;
}
DBStatementオブジェクト,DBPreparedStatementオブジェクト,DBCallableStatementオブジェクトについては,複数のサーバメソッド間で共有しないようにしてください。同じRMに対する操作であっても,異なるスレッドで起動されたメソッドでは正常に動作しません。あるメソッドで生成したDBStatementオブジェクト(DBPreparedStatementオブジェクト,DBCallableStatementオブジェクト)はそのメソッド内で削除するようにしてください。