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 END xid [SUSPEND [FOR MIGRATE]]
XA PREPARE xid
XA COMMIT xid [ONE PHASE]
XA ROLLBACK xid
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
ステートメントが上記のどの注意事項に当てはまるのかは、項 「暗黙のコミットを引き起こすステートメント」 でリストアップされています。