[前回] MySQL vs. TiDB-分散トランザクションの比較検証(3): MySQL内部XA
はじめに
MySQL XAの検証を続けます。
今回は、XAの注意事項と制約の観点から検証を行います。
XAトランザクションの注意事項と制約
注意1: XAトランザクションとローカル(非XA)トランザクションの関係
特定クライアント接続のコンテキスト内で、XAトランザクションとローカル(非XA)トランザクションは相互に排他的です。
-
XA START
を使用しXAトランザクションを開始した場合、コミットまたはロールバックされるまで、ローカルトランザクションを開始できない -
START TRANSACTION
を使用しローカルトランザクションを開始した場合、コミットまたはロールバックされるまで XAステートメントを使用できない
実際、検証してみます
検証環境と事前準備は、以下をご参照ください。
検証環境
操作用端末を二つ開きます。
- 端末1
- 端末2
端末1から
- mysqlコマンドでMySQL接続し、データベース指定
$ mysql -u user -p
mysql> USE test;
- XAトランザクションを開始
myxa
は、XAトランザクションの一意識別子
mysql> XA START 'myxa';
- 同じセッションからローカルトランザクションを開始
mysql> START TRANSACTION;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
案の定、ローカルトランザクションを開始できません。
- 1行INSERT
mysql> INSERT INTO theater VALUES (4, 'NO');
-
XA END
実行し、トランザクションをIDLE状態に
mysql> XA END 'myxa';
- 再度、同じセッションからローカルトランザクションを開始
mysql> START TRANSACTION;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
XAトランザクションがIDLE状態になっても、ローカルトランザクションは開始できません。
-
XA PREPARE
実行し、トランザクションを準備
mysql> XA PREPARE 'myxa';
- 再度、同じセッションからローカルトランザクションを開始
mysql> START TRANSACTION;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
XAトランザクションがPREPARED状態でも、ローカルトランザクションは開始できません。
-
XA COMMIT
実行し、PREPARED状態のトランザクションをコミット
mysql> XA COMMIT 'myxa';
- 再度、同じセッションからローカルトランザクションを開始
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
XAトランザクションがコミットされたため、ローカルトランザクションを開始できました。
- 1行INSERT
mysql> INSERT INTO theater VALUES (5, 'NO');
このままの状態で、端末2を開きます。
端末2から
- mysqlコマンドでMySQL接続し、データベース指定
$ mysql -u user -p
mysql> USE test;
- XAトランザクションを開始
myxa
は、XAトランザクションの一意識別子
mysql> XA START 'myxa';
- 1行INSERT
mysql> INSERT INTO theater VALUES (6, 'NO');
-
XA END
実行し、トランザクションをIDLE状態に
mysql> XA END 'myxa';
-
XA PREPARE
実行し、トランザクションを準備
mysql> XA PREPARE 'myxa';
-
XA COMMIT
実行し、PREPARED状態のトランザクションをコミット
mysql> XA COMMIT 'myxa';
端末1のセッションで、ローカルトランザクションが開始状態でも、
端末2の別セッションからは、XAトランザクションを問題なく実行できました。
注意2: XAトランザクションがACTIVE状態の場合、暗黙的にコミットが発行されるステートメントを実行できない
- 暗黙的にコミットが発行されるステートメントにより、現在セッションでアクティブなすべてのトランザクションが暗黙的に終了される
- XA規約に違反し、XAトランザクションをロールバックできなくなるため、以下のエラーが発生する
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed
when global transaction is in the ACTIVE state
- 注意事項に該当する、暗黙的にコミットが発行されるステートメント
- データベースオブジェクトを定義または変更するデータ定義言語(DDL)ステートメント
- MySQLデータベース内のテーブルを暗黙的に使用または変更するステートメント
- トランザクション制御およびロックステートメント
- データロードステートメント
- 管理ステートメント
- レプリケーション制御ステートメント
※ 引用元: https://dev.mysql.com/doc/refman/8.0/ja/implicit-commit.html
実際、検証してみます
端末を開きます
- mysqlコマンドでMySQL接続し、データベース指定
$ mysql -u user -p
mysql> USE test;
- XAトランザクションを開始
myxa
は、XAトランザクションの一意識別子
mysql> XA START 'myxa';
- 1行INSERT
mysql> INSERT INTO theater VALUES (7, 'NO');
XAトランザクションがACTIVE状態の場合、
INSERT文は問題なく実行できます。
- 暗黙的にコミットが発行される
TRUNCATE TABLE
を実行
mysql> TRUNCATE TABLE theater;
ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
XAトランザクションがACTIVE状態の場合、
暗黙的にコミットが発行されるステートメントは失敗します。
制約: XAトランザクションは、InnoDBストレージエンジンのみ使用可能
- 外部XAの場合
- MySQLサーバーがリソースマネージャーとして機能
- クライアントプログラムがトランザクションマネージャーとして機能
- 内部XAの場合
- MySQLサーバー内のストレージエンジンがリソースマネージャーとして機能
- MySQLサーバー自体がトランザクションマネージャーとして機能
- 内部XAをサポート可能かは、個々のストレージエンジンの機能により制限される
- 内部XAは、複数のストレージエンジンが関与するXAトランザクション処理に必要
- 内部XAの実装で、ストレージエンジンがテーブルハンドラレベルでの2フェーズコミットをサポートしている必要があり
- これを満たすのはInnoDBのみ
結局、今まで検証したのは内部XAでした。
- ストレージエンジンInnoDBがリソースマネージャーとして機能
- MySQLサーバーがトランザクションマネージャーとして機能
おわりに
次回から、外部XAを検証してみます。
お楽しみに。