|
グローバル トランザクションとは、複数のリソース マネージャを使用し、複数のサーバ上で行われる複数の操作を 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.
次の表は、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.
IF NOT TPOK
error processing
* ERROR TP-STATUS に 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 アプリケーションのプログラミング』の「エラーの管理」を参照してください。 |
次のサンプル コードは、トランザクションの定義方法を示しています。
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.
. . .
* コマンドライン オプションを取得します。変数 (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.
* グローバル トランザクションを開始します。
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.
* レコードを設定します。
MOVE Q-BRANCH TO AUDV-BRANCH-ID.
MOVE ZEROS TO AUDV-BALANCE.
MOVE SPACES TO AUDV-ERRMSG.
* TPCALL レコードを設定します。
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.
* グローバル トランザクションをコミットします。
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.
* トランザクションが成功した場合のみ、結果を表示します。
DISPLAY "BRANCH=" Q-BRANCH.
DISPLAY "BALANCE=" AUDV-BALANCE.
PERFORM DO-TPTERM.
* トランザクションをアボートします。
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.
* アプリケーションを分離します。
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 アプリケーションのプログラミング』の「エラーの管理」を参照してください。
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 構造体については、「トランザクションの開始」を参照してください。
次の図は、グローバル トランザクションを行う階層構造の会話型接続を示しています。
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 * レコードを設定します。
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 * 戻り値を確認します。
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 * グローバル トランザクションをコミットします。
44 DO-TPCOMMIT.
45 CALL "TPCOMMIT" USING TPTRXDEF-REC
46 TPSTATUS-REC
47 IF NOT TPOK
48 error message
49 * トランザクションをアボートします。
50 DO-TPABORT.
51 CALL "TPABORT" USING TPTRXDEF-REC
52 TPSTATUS-REC
53 IF NOT TPOK
54 error message
55 * アプリケーションを分離します。
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 コンフィグレーション パラメータ
|