InnoDB
ストレージ エンジンでは、XA トランザクションがサポートされています。MySQL XA インプリメンテーションは X/Open CAE ドキュメント
Distributed Transaction Processing:XA 仕様 に基づいています。この文書はオープン グループによって出版されていて、http://www.opengroup.org/public/pubs/catalog/c193.htm で入手可能です。現在の XA インプリメンテーションの制限については、 項D.5. 「XA トランザクションの規制」 で説明されています。
クライアント側には、特別な事は何も要求されません。MySQL サーバへの XA インターフェースは、XA
キーワードで始まる SQL ステートメントで構成されています。MySQL クライアント プログラムは、SQL ステートメントを送り、XA ステートメント
インターフェースの動作を理解する事が可能である必要があります。それらは最近のクライアント ライブラリに違反してリンクされる必要はありません。古いクライアント
ライブラリもまた機能します。
現在、MySQL コネクタの中では、MySQL コネクタ/J 5.0.0 が XA ディレクトリをサポートします。 (XA SQL ステートメント インターフェースを扱うクラス インターフェースを利用して)
XA は分散型のトランザクションをサポートします。それは、複数の別々のトランザクション リソースを、グローバル トランザクションに参加させる事ができる能力です。トランザクション リソースは RDBMS である事が多いのですが、別の種類である可能性もあります。
グローバル トランザクションは、それら自身の中でトランザクションのアクションをいくつか含んでいますが、それらは全て、グループとして成功するか、グループとしてロールバックされる必要があります。要するに、これは複数の
ACID トランザクションが、ACID 特性を持つグローバル操作のコンポーネントとして一斉に実行されるように ACID 特性を 「1レベル上げる」 という事です。(しかし、分散型のトランザクションには、ACID 特性を達成する為に、SERIALIZABLE
分離レベルを利用しなければいけません。非分散型のトランザクションには REPEATABLE READ
の利用で十分ですが、分散型のトランザクションに対しては十分では有りません。)
分散型トランザクションのいくつかの例
アプリケーションは、メッセージ サービスと RDBMS を合体させる統合ツールとして機能します。アプリケーションは、メッセージの送信、検索、さらにトランザクションのデータベースも巻き込んで処理を行うトランザクションが、全て確実にグローバル トランザクションの中で行われるようにします。これを 「トランザクションの電子メール」 だと考える事ができます。
アプリケーションは、複数のサーバを含むアクションが、各サーバに対する別々のローカル トランザクションではなく、グローバル トランザクションの一部として発生する、MySQL サーバやオラクル サーバ(または複合 MySQL サーバ)のような、異なるデータベースを含むアクションを実行します。
銀行は、RDBMS 内に口座情報を保持し、現金自動支払機(ATM)を通してお金を配布、受け取りします。ATM のアクションは口座に正確に反映されなければいけませんが、これは RDBMS だけでは行えません。グローバル トランザクション マネージャーが、金融取引全体の整合性を保障する為に、現金 ATM とデータベース リソースを統合します。
グローバル トランザクションを利用するアプリケーションは、1つ、または複数のリソース マネージャと、1つのトランザクション マネージャを含んでいます。
リソース マネージャ(RM)はトランザクションのリソースにアクセスを供給します。データベース サーバはリソース マネージャの1つです。RM によって管理されたトランザクションをコミットしたり、ロールバックしたりする事が可能なはずです。
トランザクション マネージャ(TM)はグローバル トランザクションの一部であるトランザクションを調整します。これは、これらの各トランザクションを扱う RM と通信します。グローバル トランザクション内の各トランザクションは、グローバル トランザクションの 「ブランチ」 です。グローバル トランザクションと、それらのブランチは、後ほど紹介される名づけスキームによって識別されます。
XA MySQL の MySQL インプリメンテーションは、MySQL サーバがグローバル トランザクション内で XA トランザクションを扱うリソース マネージャとして機能する事を可能にします。MySQL サーバに接続するクライアントプログラムは、トランザクション マネージャとして機能します。
グローバル トランザクションを実行するには、どのコンポネントが関係しているかを知り、それらをそれぞれ、コミットまたはロールバックできる時にポイントまで持ってくる事が必要です。 各コンポネントがそれぞれの能力についてどのようなレポートをするかによって、それらは全て1つのアトミック グループとしてコミット、またはロールバックしなければいけません。 それは、全てのコンポネントがコミットするか、または全てのコンポネントがロールバックするという事です。グローバル トランザクションを管理するには、コンポネントか、接続ネットワークが失敗する可能性があるという事を考慮に入れておく事が必要です。
グローバル トランザクションを実行するプロセスは、二相コミットを利用します。(2PC)これは、グローバル トランザクションのブランチによって行われるアクションが実行された後に起こります。
第一段階で、全てのブランチが準備されます。それは、TM からコミットの準備の命令が出るという事です。通常、これはブランチが管理する各 RM が、安定したストレージの中にブランチの為のアクションを記録するという事を意味します。ブランチは、それらが利用可能かどうかを指示し、その結果は第二段階に利用されます。
第二段階では、TM が RM にロールバックを行うかどうかの指示を出します。もし全てのブランチの準備が整った時それらがコミットが可能だという連絡を出せは、それら全てにコミットの指示が出されます。もしブランチの準備が整った時にどれか1つでもコミットが不可能であるという連絡があれば、全てのブランチにロールバックの指示が出されます。
場合によっては、グローバル トランザクションは単相コミットを利用します。(1PC)例えば、トランザクション マネージャがたった1つのトランザクション リソースで成り立っているグローバル トランザクションを見つけたら(それを単一ブランチといいます)、そのリソースには準備とコミットを同時にするように指示が出されます。
MySQL 内で XA トランザクションを行うには、次のステートメントを利用してください。
XA {START|BEGIN}xid
[JOIN|RESUME] XA ENDxid
[SUSPEND [FOR MIGRATE]] XA PREPARExid
XA COMMITxid
[ONE PHASE] XA ROLLBACKxid
XA RECOVER
XA START
に対しては、JOIN
と RESUME
条項はサポートされていません。
XA END
に対しては、SUSPEND [FOR MIGRATE]
条項はサポートされていません。
各 XA ステートメントは XA
キーワードで始まり、それらのほとんどが xid
値を必要とします。xid
は XA トランザクション識別子です。それは、ステートメントがどのトランザクションに適応するのか指示します。 xid
値はクライアントから提供されるか、MySQL サーバから発生します。xid
値は1つから3つの部分を持っています。
xid
:gtrid
[,bqual
[,formatID
]]
gtrid
はグローバル トランザクション識別子、bqual
はブランチ修飾子、そして formatID
は gtrid
と bqual
値によって利用されるフォーマットを識別する数値です。構文によって指示されているように、bqual
と formatID
は任意です。デフォルトの bqual
値は、指示されていない限り ''
です。デフォルトの formatID
値は、指示されていない限り1です。
gtrid
と bqual
は文字列直定数である必要があり、それぞれが最長64バイトです(文字数ではない)。gtrid
と bqual
の指定方法は、いくつかあります。引用された文字列('ab'
)、16進数列 (0x6162
、X'ab'
)、またはビット値(b'nnnn'
)を利用する事ができます。
formatID
は符号無しの整数です。
gtrid
と bqual
値は、MySQL サーバに内在する XA サポート ルーチンによって、バイトで解釈されます。 しかし、XA ステートメントを含む SQL ステートメントが解析されると、サーバはいくつかの特定の文字セットと共に機能します。安全の為に、
gtrid
と bqual
を16進数列として書いてください。
xid
値は一般的にトランザクション マネージャによって生成されます。ある TM によって生成された値は、別の TM によって生成された値とは異なります。規定の
TM は XA RECOVER
ステートメントによって返された値のリスト内にある、それ自身の xid
値を識別できなければいけません。
XA START xid
は、規定の xid
値を利用して XA トランザクションをスタートします。各 XA トランザクションは固有の xid
値を持つ必要があるので、その値は同時に XA トランザクションによって利用されてはいけません。一意性は gtrid
と bqual
値を利用して評価されます。XA トランザクションに続く全ての XA ステートメントは、XA START
ステートメント内で規定されているように、同じ xid
値を利用して指定されなければいけません。もし、それらのステートメントのどれかを利用しながら、既存 XA トランザクションに対応しない xid
値を指定すると、エラーが起こります。
ひとつ、または複数の XA トランザクションは同じグローバル トランザクションの一部になる事ができます。規定のグローバル トランザクション内の全ての
XA トランザクションは、xid
値内で同じ gtrid
値を利用しなければいけません。この理由により、規定の XA トランザクションがどのグローバル トランザクションの一部であるかをはっきりさせる為に、gtrid
値はグローバルに一意である必要があります。xid
値の bqual
部は、グローバル トランザクションの中で、各 XA トランザクションに対して異なっている必要があります。(bqual
値が異なっている必要があるという要求は、現在の MySQL XA インプリメンテーションの制限です。これは XA 仕様の一部ではありません。)
XA RECOVER
ステートメントは、PREPARED
状態にある MySQL サーバ上の XA トランザクションに情報を返します。(詳しくは 項2. 「XA トランザクションの状態」 をご確認ください。)アウトプットは、どのクライアントがスタートしたかに関わらず、サーバ上の XA トランザクションなどの行を含みます。
XA RECOVER
アウトプット行はこのような形になります。('abc'
、'def'
、そして 7
部分で成り立っている xid
値の例):
mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+--------+
| 7 | 3 | 3 | abcdef |
+----------+--------------+--------------+--------+
アウトプット カラムは次の意味を持っています。
formatID
はトランザクション xid
の formatID
部です。
gtrid_length
は xid
の gtrid
部の、バイトでの長さです。
bqual_length
は xid
の bqual
部の、バイトでの長さです。
data
は xid
の gtrid
と bqual
部の連結です。
次の状態での XA トランザクションの進歩
XA トランザクションをスタートさせる為に XA START
を利用し、それを ACTIVE
な状態にして下さい。
ACTIVE
XA トランザクションには、トランザクションを形成する SQL ステートメントを発行し、それから XA END
ステートメントを発行してください。XA END
はトランザクションを IDLE
の状態にします。
IDLE
XA トランザクションには、XA PREPARE
ステートメントか XA COMMIT ... ONE PHASE
ステートメントのどちらかを発行できます。ONE PHASE
ステートメント:
XA PREPARE
はトランザクションを
PREPARED
の状態にします。
この時点の XA RECOVER
ステートメントは、XA RECOVER
が PREPARED
な状態にある全ての XA トランザクションをリストにする為、そのアウトプットの中にトランザクションの xid
値を含みます。
XA COMMIT ... ONE PHASE
はトランザクションを準備し、コミットします。xid
値は、トランザクションが終了する為 XA RECOVER
によってリストされません。
PREPARED
XA トランザクションに対して、トランザクションをコミットし、終了させる為に XA COMMIT
ステートメントを発行するか、またはトランザクションをロールバックして終了させる為に XA ROLLBACK
を発行できます。
ここに、行をテーブルにグローバル トランザクションの一部として挿入するシンプルな XA トランザクションの例があります。
mysql>XA START 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec) mysql>XA END 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec) mysql>XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)
既存のクライアント接続のコンテキストの中で、XA トランザクションとローカル トランザクション(非 XA)は、お互いに 排他的です。例えば、もし
XA トランザクションを始める為に XA START
が発行されたら、XA トランザクションがコミットされるかロールバックされるまで、ローカル トランザクションはスタートできません。逆に、もしローカル
トランザクションが START TRANSACTION
でスタートされたら、トランザクションがコミットされるかロールバックされるまで、XA トランザクションは利用できません。
もしXA トランザクションが ACTIVE
な状態であれば、暗黙的なコミットを引き起こすステートメントの発行はできないという事に注意してください。XA トランザクションをロールバックする事はできないので、これはXA
規約に違反するという事になります。もしこのようなステートメントを実行しようとすると、次のようなエラーが発生します。
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
ステートメントが上記のどの注意事項に当てはまるのかは、項 「暗黙のコミットを引き起こすステートメント」 でリストアップされています。