グローバル・トランザクションとは、複数のリソース・マネージャを使用し、複数のサーバー上で行われる複数の操作を1つの論理単位として処理できるようにするメカニズムです。
プロセスがトランザクション・モードになると、サーバーにリクエストされたサービスが現在のトランザクションにかわって処理されます。呼び出されてトランザクションに参加したサービスは、「トランザクションの参加リソース」と呼ばれます。参加リソースから返される値によって、トランザクションの結果が変わる場合があります。
グローバル・トランザクションは複数のローカル・トランザクションから構成され、各トランザクションは同じリソース・マネージャにアクセスします。リソース・マネージャは、同時実行性制御とデータ更新の原子性を実現します。ローカル・トランザクションでは、アクセスが正常に終了するか、または全体が失敗します。つまり、一部だけが成功することはありません。
1つのトランザクションに参加可能なサーバー・グループは最大16個です。
Oracle Tuxedoシステムでは、グローバル・トランザクションが参加しているリソース・マネージャと共に管理され、原子性、一貫性、独立性、および持続性という特徴を持つ特定シーケンスの操作として処理されます。つまり、グローバル・トランザクションは、以下のような特徴を持つ論理的な作業単位と言えます。
Oracle Tuxedoシステムでは、個々のグローバル・トランザクションのステータスがトラッキングされ、そのトランザクションをコミットするかロールバックするかが決定されます。
グローバル・トランザクションを開始するには、次のシグネチャを使用してTPBEGIN(3cbl)ルーチンを呼び出します。
*
01 TPTRXDEF-REC.
COPY TPTRXDEF.
*
01 TPSTATUS-REC.
COPY TPSTATUS.
*
CALL "TPBEGIN" USING TPTRXDEF-REC TPSTATUS-REC.
表9-1は、TPTRXDEF-REC
データ構造体のフィールドを示しています。
TPBEGIN
は、どのプロセスからも呼び出すことができます。ただし、既にトランザクション・モードになっているプロセスからは呼び出すことはできません。トランザクション・モードでTPBEGIN
が呼び出されると、プロトコル・エラーになって呼出しが失敗し、TP-STATUS
にTPEPROTO
が設定されます。プロセスがトランザクション・モードの場合でも、この失敗はトランザクションには影響しません。
次のサンプル・コードは、グローバル・トランザクションの定義方法を簡単に示しています。
. . .
MOVE 0 TO T-OUT.
CALL "TPBEGIN" USING
TPTRXDEF-REC
TPSTATUS-REC.
IF NOT TPOK
error processing
. . .
program statements
. . .
CALL "TPCOMMIT" USING
TPTRXDEF-REC
TPSTATUS-REC.
IF NOT TPOK
error processing
次のサンプル・コードは、未処理の応答に起因するエラーの発生を示しています。
. . .
MOVE "BUY" TO SERVICE-NAME.
SET TPBLOCK TO TRUE.
SET TPNOTRAN TO TRUE.
SET TPREPLY TO TRUE.
SET TPNOTIME TO TRUE.
SET TPSIGRSTRT TO TRUE.
CALL "TPACALL" USING
TPSVCDEF-REC
TPTYPE-REC
BUY-REC
TPSTATUS-REC.
IF NOT TPOK
error processing
. . .
MOVE 0 TO T-OUT.
CALL "TPBEGIN" USING
TPTRXDEF-REC
TPSTATUS-REC.
vIF NOT TPOK
error processing
* ERROR TP-STATUS is set to TPEPROTO
. . .
program statements
. . .
SET TPBLOCK TO TRUE.
SET TPNOTRAN TO TRUE.
SET TPCHANGE TO TRUE.
SET TPNOTIME TO TRUE.
SET TPSIGRSTRT TO TRUE.
SET TPGETANY TO TRUE.
CALL "TPGETRPLY" USING
TPSVCDEF-REC
TPTYPE-REC
WK-AREA
TPSTATUS-REC.
IF NOT TPOK
error processing
トランザクションがタイムアウトになった場合、TPCOMMIT
を呼び出すとトランザクションが中断します。その結果、TPCOMMIT
が失敗し、TP-STATUS
にTPEABORT
が設定されます。
次のサンプル・コードは、トランザクションのタイムアウトを確認する方法を示しています。T-OUT
の値が30秒に設定されていることに注目してください。
. . .
MOVE 30 TO T-OUT.
CALL "TPBEGIN" USING TPTRXDEF-REC TPSTATUS-REC.
IF NOT TPOK
MOVE "Failed to BEGIN a transaction" TO LOG-REC-TEXT.
MOVE 29 to LOG-REC-LEN
CALL "USERLOG" USING
LOG-REC-TEXT
LOG-REC-LEN
TPSTATUS-REC
CALL "TPTERM" USING
TPSTATUS-REC
PERFORM A-999-EXIT.
. . .
communication CALL statements
. . .
IF TPETIME
CALL "TPABORT" USING
TPTRXDEF-REC
TPSTATUS-REC
IF NOT TPOK
error processing
ELSE
CALL "TPCOMMIT" USING
TPTRXDEF-REC
TPSTATUS-REC
IF NOT TPOK
error processing
注: | トランザクション・モードのプロセスで、TPNOTRAN を設定して通信呼出しを行うと、呼び出されたサービスは現在のトランザクションに参加できません。サービス・リクエストの成功や失敗は、トランザクションの結果に影響しません。トランザクションは、サービスがトランザクションに参加しているかどうかには関係なく、そのサービスから応答が返されるのを待つ間にタイムアウトになる場合もあります。TPNOTRAN フラグの影響の詳細は、『C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング』の「エラーの管理」を参照してください。 |
次のサンプル・コードは、トランザクションの定義方法を示しています。
DATA DIVISION.
WORKING-STORAGE SECTION.
*
01 TPTYPE-REC.
COPY TPTYPE.
*
01 TPSTATUS-REC.
COPY TPSTATUS.
*
01 TPINFDEF-REC.
COPY TPINFDEF.
*
01 TPSVCDEF-REC.
COPY TPSVCDEF.
*
01 TPTRXDEF-REC.
COPY TPTRXDEF.
*
01 LOG-REC PIC X(30) VALUE " ".
01 LOG-REC-LEN PIC S9(9) COMP-5.
*
01 USR-DATA-REC PIC X(16).
*
01 AUDV-REC.
05 AUDV-BRANCH-ID PIC S9(9) COMP-5.
05 AUDV-BALANCE PIC S9(9) COMP-5.
05 AUDV-ERRMSG PIC X(60).
*
PROCEDURE DIVISION.
*
A-000.
. . .
* Get Command Line Options set Variables (Q-BRANCH)
MOVE SPACES TO USRNAME.
MOVE SPACES TO CLTNAME.
MOVE SPACES TO PASSWD.
MOVE SPACES TO GRPNAME.
CALL "TPINITIALIZE" USING TPINFDEF-REC
USR-DATA-REC
TPSTATUS-REC.
IF NOT TPOK
MOVE "Failed to join application" TO LOG-REC
MOVE 26 TO LOG-REC-LEN
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC
PERFORM A-999-EXIT.
* Start global transaction
MOVE 30 TO T-OUT.
CALL "TPBEGIN" USING TPTRXDEF-REC TPSTATUS-REC.
IF NOT TPOK
MOVE 29 to LOG-REC-LEN
MOVE "Failed to begin a transaction" TO LOG-REC
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC
PERFORM DO-TPTERM.
* Set up record
MOVE Q-BRANCH TO AUDV-BRANCH-ID.
MOVE ZEROS TO AUDV-BALANCE.
MOVE SPACES TO AUDV-ERRMSG.
* Set up TPCALL records
MOVE "GETBALANCE" TO SERVICE-NAME.
MOVE "VIEW" TO REC-TYPE.
MOVE LENGTH OF AUDV-REC TO LEN.
SET TPBLOCK TO TRUE.
SET TPTRAN IN TPSVCDEF-REC TO TRUE.
SET TPNOTIME TO TRUE.
SET TPSIGRSTRT TO TRUE.
SET TPCHANGE TO TRUE.
*
CALL "TPCALL" USING TPSVCDEF-REC
TPTYPE-REC
AUDV-REC
TPTYPE-REC
AUDV-REC
TPSTATUS-REC.
IF NOT TPOK
MOVE 19 to LOG-REC-LEN
MOVE "Service call failed" TO LOG-REC
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC
PERFORM DO-TPABORT
PERFORM DO-TPTERM.
* Commit global transaction
CALL "TPCOMMIT" USING TPTRXDEF-REC
TPSTATUS-REC
IF NOT TPOK
MOVE 16 to LOG-REC-LEN
MOVE "Failed to commit" TO LOG-REC
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC
PERFORM DO-TPTERM.
* Show results only when transaction has completed successfully
DISPLAY "BRANCH=" Q-BRANCH.
DISPLAY "BALANCE=" AUDV-BALANCE.
PERFORM DO-TPTERM.
* Abort the transaction
DO-TPABORT.
CALL "TPABORT" USING TPTRXDEF-REC
TPSTATUS-REC
IF NOT TPOK
MOVE 26 to LOG-REC-LEN
MOVE "Failed to abort transaction" TO LOG-REC
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC.
* Leave the application
DO-TPTERM.
CALL "TPTERM" USING TPSTATUS-REC.
IF NOT TPOK
MOVE 27 to LOG-REC-LEN
MOVE "Failed to leave application" TO LOG-REC
CALL "USERLOG" USING LOG-REC
LOG-REC-LEN
TPSTATUS-REC.
EXIT PROGRAM.
*
A-999-EXIT.
*
EXIT PROGRAM.
グローバル・トランザクションを終了するには、TPCOMMIT(3cbl)を呼び出して現在のトランザクションをコミットするか、またはTPABORT(3cbl)を呼び出して処理を中断して、すべての操作をロールバックします。
注: | TPCALL 、TPACALL 、またはTPCONNECT を呼び出すときに明示的にTPNOTRAN が設定されている場合、呼び出されたサービスによって実行される操作は、トランザクションに含まれません。つまり、このようなサービスによって実行される操作は、TPABORT ルーチンを呼び出したときにロールバックされません。 |
TPCOMMIT(3cbl)ルーチンは、現在のトランザクションをコミットします。TPCOMMIT
から正常に制御が戻ると、現在のトランザクションの結果としてリソースに加えられた変更は永続的なものとなります。
TPCOMMIT
ルーチンの呼出しには、次のシグネチャを使用します。
*
01 TPTRXDEF-REC.
COPY TPTRXDEF.
*
01 TPSTATUS-REC.
COPY TPSTATUS.
*
CALL "TPCOMMIT" USING TPTRXDEF-REC TPSTATUS-REC.
TPTRXDEF-REC
構造体については、「トランザクションの開始」を参照してください。
TPCOMMIT
を正常に実行するには、次の条件を満たしていることが必要です。
最初の条件を満たしていない場合、呼出しは失敗し、プロトコル・エラーを示すTPEPROTO
がTP-STATUS
に設定されます。2番目または3番目の条件を満たしていない場合、呼出しは失敗し、トランザクションがロールバックされたことを示すTPEABORT
がTP-STATUS
に設定されます。トランザクションに未処理の応答があるときにTPCOMMIT
がイニシエータによって呼び出されると、トランザクションは中断され、トランザクションに関連する応答記述子が無効になります。参加リソースがTPCOMMIT
またはTPABORT
を呼び出しても、トランザクションには影響しません。
サービス呼出しでTPFAIL
が戻されるか、またはサービス・エラーが発生すると、トランザクションはロールバックのみの状態になります。ロールバックのみのトランザクションに対してTPCOMMIT
が呼び出されると、このルーチンはトランザクションを取り消し、-1を戻してTP-STATUS
にTPEABORT
を設定します。すでにタイムアウトになっているトランザクションに対してTPCOMMIT
を呼び出した場合も同じ結果になり、TPCOMMIT
は-1を戻してTP-STATUS
にTPEABORT
が設定されます。トランザクション・エラーの詳細は、『C言語を使用したOracle Tuxedo ATMIアプリケーションのプログラミング』の「エラーの管理」を参照してください。
TPCOMMIT
ルーチンが呼び出されると、2フェーズ・コミット・プロトコルによる通信が開始されます。このプロトコルは、その名前が示すように、次の2段階の処理に分かれています。
トランザクションのイニシエータがTPCOMMIT
ルーチンを呼び出すと、コミット・シーケンスが開始されます。指定されたコーディネータ・グループ内のOracle Tuxedo TMSサーバー・プロセスは、コミット・プロトコルの最初のフェーズを実行する各参加リソース・グループのTMSと通信を行います。次に、各グループのTMSは、そのグループのリソース・マネージャ(RM)に、トランザクション・マネージャとRM間の通信用に定義されているXAプロトコルを使用してコミットするように指示します。RMは、安定記憶域にコミット・シーケンスの前後のトランザクションの状態を書き込み、TMSに成功か失敗かを通知します。その後、TMSはトランザクション・コーディネータのTMSにレスポンスを渡します。
トランザクション・コーディネータのTMSは、すべてのグループから成功の通知を受け取ると、トランザクションのコミット中であることをログに記録し、第2フェーズのコミット通知をすべての参加リソース・グループに送信します。その後、各グループのRMはトランザクションの更新を完了します。
トランザクション・コーディネータのTMSが、グループから第1フェーズのコミットの失敗の通知を受けた場合、またはグループからの応答の受信に失敗した場合、各RMにロールバック通知を送信し、RMはすべてのトランザクション更新を以前の状態に戻します。これにより、TPCOMMIT
は失敗し、TP-STATUS
にTPEABORT
が設定されます。
1つのトランザクションに複数のグループが関係している場合、TPCOMMIT
が正常に制御を戻すための条件として、次のいずれかを指定できます。
この2つの条件のいずれかを指定するには、構成ファイルのRESOURCES
セクションのCMTRET
パラメータに、次のいずれかの値を設定します。
デフォルトでは、CMTRET
はCOMPLETE
に設定されます。
ほとんどの場合、グローバル・トランザクションのすべての参加リソースが第1フェーズの正常終了を記録した場合、第2フェーズも正常終了します。CMTRET
にLOGGED
を設定すると、TCOMMIT
の呼出しから制御が多少早く戻るようになります。ただし、参加リソースが、コミットの決定と矛盾する方法で、トランザクションの担当部分をヒューリスティックで終了する危険性があります。
このようなリスクを負うべきかどうかの選択は、アプリケーションの性質に左右されます。たとえば、財務アプリケーションなど正確さが要求されるアプリケーションでは、すべての参加リソースが2フェーズ・コミットを完了するまでは、制御を戻さないようにします。時間的な条件を重視するアプリケーションでは、正確さを犠牲にしても実行速度を上げます。
TPABORT (3cbl)ルーチンを使用すると、異常な状態を通知して、明示的にトランザクションを中断できます。この関数は、トランザクションの応答に未処理のものがあると、その呼出し記述子を無効にします。その場合、トランザクションで行われた変更はリソースには適用されません。TPABORT
ルーチンの呼出しには、次のシグネチャを使用します。
*
01 TPTRXDEF-REC.
COPY TPTRXDEF.
*
01 TPSTATUS-REC.
COPY TPSTATUS.
*
CALL "TPABORT" USING TPTRXDEF-REC TPSTATUS-REC.
TPTRXDEF-REC
構造体については、「トランザクションの開始」を参照してください。
図9-1は、グローバル・トランザクションを行う階層構造の会話型接続を示しています。
TPBEGIN
とTPCONNECT
を呼び出して、トランザクション・モードで接続を開始します。TPEV_SVCSUCC
またはTPEV_SVCFAIL
)を示す応答を階層構造を通じてトランザクションを開始したプロセスに送信します。この例では、トランザクションを開始したプロセスはクライアント(プロセスA)です。従属サービスは、応答の送信が終了すると、つまり未処理の応答がなくなると、TPRETURN
を呼び出します。 次のサンプル・コードでは、クライアントはREPORT
サービスへの同期呼出し(24行目)を行います。次に、通信呼出しで返される可能性があるエラーを調べて(30 - 42行目)、参加リソースの失敗を確認します。
01 . . .
02 CALL "TPINITIALIZE" USING TPINFDEF-REC
03 USR-DATA-REC
04 TPSTATUS-REC.
05 IF NOT TPOK
06 error message,
07 EXIT PROGRAM .
08 MOVE 30 TO T-OUT.
09 CALL "TPBEGIN" USING TPTRXDEF-REC TPSTATUS-REC.
10 IF NOT TPOK
11 error message,
12 PERFORM DO-TPTERM.
13 * Set up record
14 MOVE "REPORT=accrcv DBNAME=accounts" TP-RECORD.
15 MOVE 27 TO LEN.
16 MOVE "REPORTS" TO SERVICE-NAME.
17 MOVE "STRING" TO REC-TYPE.
18 SET TPBLOCK TO TRUE.
19 SET TPTRAN IN TPSVCDEF-REC TO TRUE.
20 SET TPNOTIME TO TRUE.
21 SET TPSIGRSTRT TO TRUE.
22 SET TPCHANGE TO TRUE.
23 *
24 CALL "TPCALL" USING TPSVCDEF-REC
25 TPTYPE-REC
26 TP-RECORD
27 TPTYPE-REC
28 TP-RECORD
29 TPSTATUS-REC.
30 IF TPOK
31 PERFORM DO-TPCOMMIT
32 PERFORM DO-TPTERM.
33 * Check return status
34 IF TPESVCERR
35 DISPLAY "REPORT service's TPRETURN encountered problems"
36 ELSE IF TPESVCFAIL
37 DISPLAY "REPORT service FAILED with return code=" APPL-RETURN-CODE
38 ELSE IF TPEOTYPE
39 DISPLAY "REPORT service's reply is not of any known REC-TYPE"
40 *
41 PERFORM DO-TPABORT
42 PERFORM DO-TPTERM.
43 * Commit global transaction
44 DO-TPCOMMIT.
45 CALL "TPCOMMIT" USING TPTRXDEF-REC
46 TPSTATUS-REC
47 IF NOT TPOK
48 error message
49 * Abort the transaction
50 DO-TPABORT.
51 CALL "TPABORT" USING TPTRXDEF-REC
52 TPSTATUS-REC
53 IF NOT TPOK
54 error message
55 * Leave the application
56 DO-TPTERM.
57 CALL "TPTERM" USING TPSTATUS-REC.
58 IF NOT TPOK
59 error message
60 EXIT PROGRAM.
アプリケーションでは、次のいずれかの方法でグローバル・トランザクションを開始できます。
構成ファイルのシステム・パラメータAUTOTRAN
を設定すると、サービス・ルーチンがトランザクション・モードになります。AUTOTRAN
にY
を設定すると、別のプロセスからリクエストを受信したときに、サービス・サブルーチン内でトランザクションが自動的に開始されます。
暗黙的にトランザクションを定義する場合は、以下の規則に従います。
AUTOTRAN
がトランザクションを開始するように設定されていると、プロセスが別のプロセスのサービスをリクエストしたときにトランザクションが開始されます。TPNOTRAN
が設定されているかどうかを確認します。 TPNOTRAN
が設定されていない場合、呼び出されたプロセスは伝達の規則によってトランザクション・モードになります。システムによってAUTOTRAN
パラメータは確認されません。
TPTRN-FLAG IN TPSVCDEF-REC
にTPNOTRAN
が設定されている場合、呼び出されたプロセスによって実行されるサービスは、現在のトランザクションに含まれません。つまり、「伝達の規則」は適用されません。システムによってAUTOTRAN
パラメータが確認されます。
注: | サービスは自動的にトランザクション・モードにできるので、TPNOTRAN フラグが設定されたサービスから、AUTOTRAN パラメータが設定されたサービスを呼び出すことができます。そのようなサービスが別のサービスをリクエストした場合、サービスのデータ構造体のメンバーは問合せに対してTPTRAN を返します。たとえば、TPNOTRAN | TPNOREPLY を設定して呼出しを行い、サービスが呼び出されたときに(そのサービスによって)トランザクションが自動的に開始された場合、データ構造体は、TPTRAN | TPNOREPLY に設定されます。 |
アプリケーション・プログラマがXA準拠のサーバー・グループのサービスをコーディングする場合、グループのリソース・マネージャを介して操作を行うようにするのが一般的です。通常、サービスは1つのトランザクション内ですべての操作を行います。それに対して、TPNOTRAN
の通信設定でサービスを呼び出すと、データベース操作の実行時に予期しない結果を受け取る場合があります。
予測不能な動作を防ぐには、XA準拠のリソース・マネージャに関連付けられているグループのサービスが、常にトランザクション・モードで呼び出されるようにアプリケーションを設計します。または、構成ファイルのAUTOTRAN
にY
を設定します。また、サービス・コードの早い段階で、トランザクション・レベルを確認します。
特定のエラー条件を回避したり正しく解釈するには、プロセスがトランザクション・モードかどうかを確認することが大切です。たとえば、すでにトランザクション・モードになっているプロセスがTPBEGIN
を呼び出すとエラーになります。そのようなプロセスがTPBEGIN
を呼び出すと、呼出しは失敗し、TP-STATUS
にTPEPROTO
が設定されて、呼出し側がすでにトランザクションに参加しているにもかかわらず呼び出されたことが示されます。トランザクションに影響はありません。
サービス・サブルーチンがトランザクション・モードかどうかを確認した後で、TPBEGIN
を呼び出すようにアプリケーションを設計できます。次のいずれかの方法で、トランザクション・レベルを確認できます。
TPTRAN
に設定されていると、サービスはトランザクション・モードになります。 TPGETLEV
ルーチンの呼出しには、次のシグネチャを使用します。
01 TPTRXLEV-REC.
COPY TPTRXLEV.
01 TPSTATUS-REC.
COPY TPSTATUS.
CALL "TPGETLEV" USING TPTRXLEV-REC TPSTATUS-REC.
TPGETLEV
は、呼出し側がトランザクション・モードになっていない場合はTP-NOT-IN-TRAN
を返し、トランザクション・モードになっている場合はTP-IN-TRAN
を返します。
次のサンプル・コードは、TPGETLEV
ルーチン(3行目)を使用して、トランザクション・レベルを確認する方法を示しています。プロセスがトランザクション・モードになっていない場合、アプリケーションでトランザクションを開始します(5行目)。TPBEGIN
が失敗した場合、メッセージがステータス行に返され(9行目)、TPRETURN
のAPPL-CODE IN TPSVCRET-REC
にAPL-RETURN-CODE IN TPSTATUS-REC
で取得できるコードが設定されます(1行目と11行目)。
. . . Application defined codes
001 77 BEG-FAILED PIC S9(9) VALUE 3.
. . .
002 PROCEDURE DIVISION.
. . .
003 CALL "TPGETLEV" USING TPTRCLEV-REC
TPSTATUS-REC.
004 IF NOT TPOK
error processing EXIT PROGRAM
005 IF TP-NOT-IN-TRAN
006 MOVE 30 TO T-OUT.
007 CALL "TPBEGIN" USING
TPTRXDEF-REC
TPSTATUS-REC.
008 IF NOT TPOK
009 MOVE "Attempt to TPBEGIN within service failed"
TO USER-MESSAGE.
010 SET TPFAIL TO TRUE.
011 MOVE BEG-FAILED TO APPL-CODE.
012 COPY TPRETURN REPLACING
013 DATA-REC BY USER-MESSAGE.
. . .
AUTOTRAN
にY
が設定されている場合、トランザクション・ルーチンのTPBEGIN
、TPCOMMIT
、TPABORT
を明示的に呼び出す必要はありません。その結果、トランザクション・レベルを確認するオーバーヘッドを減らすことができます。また、TRANTIME
パラメータを設定して、タイムアウト間隔を指定することもできます。タイムアウト間隔は、サービスに対するトランザクションが開始されてからの経過時間です。また、トランザクションが完了しなかった場合は、トランザクションがロールバックされるまでの時間です。
たとえば、前述のコードのOPEN_ACCT
サービスを変更するとします。現在のコードでは、OPEN_ACCT
にトランザクションが明示的に定義され、そのトランザクションの有無を確認しています。これらの処理のオーバーヘッドを減らすには、そのコードを削除します。その場合、OPEN_ACCT
は常にトランザクション・モードで呼び出す必要があります。この要件を指定するには、構成ファイルのAUTOTRAN
とTRANTIME
システム・パラメータを有効にします。
AUTOTRAN
構成パラメータの説明。 TRANTIME
構成パラメータ