Oracle® Fusion Middleware Oracle WebLogic Server Tuxedo Connectorプログラマーズ・ガイド 11g リリース1(10.3.3) B61627-01 |
|
前 |
次 |
以下の節では、グローバル・トランザクションの概要とそれらをアプリケーションで定義および管理する方法について説明します。
グローバル・トランザクションは、2つ以上のリソース・マネージャのある作業、および1つの論理単位として扱われる2つ以上の物理サイトにまたがる作業を実行するトランザクションです。グローバル・トランザクションは常に、次の4つのプロパティによって分類された特定のシーケンスの操作として扱われます。
原子性: すべての部分が正常に実行されるか、またはまったく影響しないかのいずれかです。
一貫性: 操作は、リソースを1つの一貫性のある状態から別の一貫性のある状態へと正確に変換するよう実行されます。
隔離性: 同じトランザクションの他のプロセスがそのデータにアクセス可能であっても、中間結果は他のトランザクションにアクセスできません。
持続性: 完了したシーケンスのすべての結果は、いかなる障害によっても変更されません。
Oracle WebLogic Tuxedo Connectorは、トランザクションの管理にJava Transaction API (JTA)を使用します。
JTAには、3つのタイプのトランザクション・インタフェースがあります。
Transaction
TransactionManager
UserTransaction
Transaction
インタフェースは、ターゲットとなるTransactionオブジェクトのトランザクションに対して実行される操作を許可します。トランザクション・オブジェクトは、作成された各グローバル・トランザクションに対応して作成されます。Transaction
インタフェースは、リソースの取得、登録の同期、およびトランザクション完了操作やステータス問合せ操作を実行するために使用します。
TransactionManager
インタフェースによって、アプリケーション・サーバーはアプリケーションのかわりにトランザクション境界区分のトランザクション・マネージャと通信できるようになります。TransactionManager
インタフェースは、コンテナ管理のEJBコンポーネントのかわりにトランザクション・マネージャと通信するために使用します。
トランザクションは、クライアントまたはサーバー・プロセスのいずれかで定義できます。トランザクションは、3つの部分で構成されます。3つの部分とは、開始ポイント、トランザクション・モードのプログラム文、および終了ポイントです。
トランザクションを明示的に定義するには、begin()
メソッドを呼び出します。呼出しを行う同じプロセスである開始プロセスは、commit()
、setRollbackOnly()
またはrollback()
を呼び出すことによって終了を行うプロセスにもなる必要があります。トランザクション・デリミタ間で呼び出されるサービス・サブルーチンは、現在のトランザクションの一部となります。
注意: setTransactionTimeout() をあまり大きい値に設定すると、システム検出やエラーのレポートが遅延します。タイムアウト値は、適切な時間内でサービス・リクエストへのレスポンスを行ったり、ネットワーク障害などの問題が発生したトランザクションを終了したりするために使用します。本番環境では、システム・ロードおよびデータベース競合によって起こると予想される遅延に対応するよう、タイムアウト値を調整します。 |
トランザクションは、begin()
の呼出しによって開始されます。タイムアウト値を指定するには、begin()
文の前にsetTransactionTimeout(int seconds)
文を指定します。
Oracle Tuxedoにトランザクションを伝播するには、次の操作を実行する必要があります。
JNDIで、TuxedoConnectionFactoryオブジェクトをルックアップします。
getTuxedoConnection()を使用して、TuxedoConnectionオブジェクトを取得します。
トランザクションは、commit()
、rollback()
、またはsetRollbackOnly()
の呼出しによって終了されます。commit()
が正常に復帰すると、現在のトランザクションでリソースに対して行われた変更はすべて永続的なものとなります。commit()
が正常に実行されるには、次の2つの条件が満たされている必要があります。
呼出しプロセスは、begin()
でトランザクションを開始した同じプロセスでなければなりません。
呼出しプロセスに、未処理のトランザクション応答が存在してはなりません。
いずれかの条件が真でない場合、この呼出しは失敗し、例外がスローされます。
setRollbackOnly()
およびrollback()
は、異常が発生したことを示し、すべての記述子を元の状態にロールバックする場合に使用します。
トランザクションをロールバックする前に何らかの処理やクリーンアップが必要な場合は、setRollbackOnly()
を使用します。
トランザクションをロールバックする前に何の処理もクリーンアップも不要な場合は、rollback()
を使用します。
トランザクション・モード中は、トランザクションを正常に完了させるために特定のルールに従う必要があります。トランザクション・モード中に注意すべき基本的なルールは、次のとおりです。
begin()
でトランザクションを開始した後で、TuxedoConnectionオブジェクトを使用して、Oracle Tuxedoにトランザクションを伝播する必要があります。
tpterm()はオブジェクトへの接続を終了し、このオブジェクトでは今後操作を行わないようにします。
同じトランザクションの参加コンポーネントであるプロセスは、それらのリクエストへの応答を要求する必要があります。
応答を必要としないリクエストは、tpacall()のflagsパラメータがTPNOREPLYに設定されている場合のみ実行できます。
サービスは、commit()
を呼び出す前にすべての非同期トランザクション応答を取得する必要があります。
開始プロセスは、begin()
を呼び出す前にすべての非同期トランザクション応答を取得する必要があります。
取り出す必要のある非同期応答には、トランザクションの非参加コンポーネントから期待される応答(つまり応答ではなくトランザクションを抑制するtpacall()で行われたリクエストに対して期待される応答)が含まれます。
トランザクションがタイムアウトされず、「中止のみ」にマーク付けされている場合は、通信の結果として実行された処理がトランザクションのロールバック後に永続化するよう、以後の通信をTPNOTRANフラグを設定して実行する必要があります。
トランザクションがタイムアウトされた場合は次のとおりです。
タイムアウトされた呼出しの記述子は無効となり、それ以後の記述子の参照には、TPEBADDESCが返されます。
未処理の記述子のtpgetrply()またはtprecv()の以後の呼出しは、tperrono
をTPETIMEに設定することによってグローバルな状態のトランザクション・タイムアウトを返します。
TPNOREPLY|
TPNOBLOCK|
TPNOTRANに設定されたtpacall()のflagsパラメータで非同期呼出しを行うことができます。
タイムアウト以外の理由でトランザクションが「中止のみ」にマーク付けされると、tpgetrply()の呼出しは、その呼出しのローカルな状態を示すものをすべて返します。つまり、ローカルな状態を示す成功コードまたはエラー・コードのいずれかを返すことができます。
tpgetrply()で返信を取り込むために使用された記述子は無効になり、それ以後の参照ではTPEBADDESCが返されます。
tpsend()またはtprecv()でエラー状態を報告するために使用された記述子は無効になり、それ以後の参照ではTPEV_DISCONIMMが返されます。
トランザクションが中止されると、未処理のすべてのトランザクション呼出し記述子(TPNOTRANフラグなしで実行)が停滞状態となり、以後それらに対する参照にはTPEBADDESCが返されます。
Oracle WebLogic Tuxedo Connectorでは、ロード・バランシング時に、特定のトランザクションIDの呼び出しすべてが、特定のサーバー・インスタンスにルーティングされるわけではありません。ロード・バランシングは呼出し単位で行われます。
次に、トランザクションのサンプル・コードを示します。
例5-1 サンプル・トランザクション・コード
public class TransactionSampleBean implements SessionBean { ..... public int transaction_sample () { int ret = 0; try { javax.naming.Context myContext = new InitialContext(); TransactionManager tm = (javax.transaction.TransactionManager) myContext.lookup("javax.transaction.TransactionManager"); // Begin Transaction tm.begin (); TuxedoConnectionFactory tuxConFactory = (TuxedoConnectionFactory) ctxt.lookup("tuxedo.services.TuxedoConnection"); // You could do a local JDBC/XA-database operation here // which will be part of this transaction. ..... // NOTE 1: Get the Tuxedo Connection only after // you begin the transaction if you want the // Tuxedo call to be part of the transaction! // NOTE 2: If you get the Tuxedo Connection before // the transaction was started, all calls made from // that Tuxedo Connection are out of scope of the // transaction. TuxedoConnection myTux = tuxConFactory.getTuxedoConnection(); // Do a tpcall. This tpcall is part of the transaction. TypedString depositData = new TypedString("somecharacters,5000.00"); Reply depositReply = myTux.tpcall("DEPOSIT", depositData, 0); // You could also do tpcalls which are not part of // transaction (For example, Logging all attempted // operations etc.) by setting the TPNOTRAN Flag! TypedString logData = new TypedString("DEPOSIT:somecharacters,5000.00"); Reply logReply = myTux.tpcall("LOGTRAN", logData, ApplicationToMonitorInterface.TPNOTRAN); // Done with the Tuxedo Connection. Do tpterm. myTux.tpterm (); // Commit Transaction... tm.commit (); // NOTE: The TuxedoConnection object which has been // used in this transaction, can be used after the // transaction only if TPNOTRAN flag is set. } catch (NamingException ne) { System.out.println ("ERROR: Naming Exception looking up JNDI: " + ne); ret = -1; } catch (RollbackException re) { System.out.println("ERROR: TRANSACTION ROLLED BACK: " + re); ret = 0; } catch (TPException te) { System.out.println("ERROR: tpcall failed: TpException: " + te); ret = -1; } catch (Exception e) { log ("ERROR: Exception: " + e); ret = -1; } return ret; }