MySQL vs. TiDB-分散トランザクションの比較検証(4): MySQL内部XA(続)

##### [前回] [MySQL vs. TiDB-分散トランザクションの比較検証(3): MySQL内部XA](https://qiita.com/mingchun_zhao/items/12008d82af315c2cd163)

## はじめに

MySQL XAの検証を続けます。
今回は、XAの注意事項と制約の観点から検証を行います。

## XAトランザクションの注意事項と制約

### 注意1: XAトランザクションとローカル(非XA)トランザクションの関係

特定クライアント接続のコンテキスト内で、XAトランザクションとローカル(非XA)トランザクションは相互に排他的です。

- `XA START`を使用しXAトランザクションを開始した場合、コミットまたはロールバックされるまで、ローカルトランザクションを開始できない
- `START TRANSACTION`を使用しローカルトランザクションを開始した場合、コミットまたはロールバックされるまで XAステートメントを使用できない

#### 実際、検証してみます

検証環境と事前準備は、以下をご参照ください。
[検証環境](https://qiita.com/mingchun_zhao/items/803bd99181974f63f4ce#%E6%A4%9C%E8%A8%BC%E7%92%B0%E5%A2%83)

操作用端末を二つ開きます。

- 端末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を検証してみます。
お楽しみに。

##### [次回] [MySQL vs. TiDB-分散トランザクションの比較検証(5): TiDBの基本](https://qiita.com/mingchun_zhao/items/be53b1f63b8967fcbe40)