# グローバル一時テーブル

### 概要
+ この演習では、TiDBにおけるグローバル一時テーブルの使用方法を体験します。手順に従って、演習中は自動コミット機能をオフにします。

 <img src="./diagram/GlobalTemporaryTable_ja_001_20230519.png" width="50%" align="top"/>

### 注意
+ いくつかのステップでは、2つの異なるターミナルウィンドウでコマンドを入力する必要があります。2つのターミナルを起動し、演習の間ずっと開いておくと便利でしょう。
+ この演習で利用する、`IP`、`port`、`username`、`password`、`directory`などは、あなたの環境と異なる場合があります。
+ ターミナルウィンドウの"`$`"とはOSプロンプトです。
+ ターミナルウィンドウ内の "`tidb>`" または "`mysql>`" は、SQL コマンドプロンプトです。
+ これらの演習は、ノートパソコンなどの単一のマシン上で実行することができます。

### 前提条件
+ macOSまたはLinuxを使用していること。
+ [lab repository](https://github.com/pingcap/tidb-course-201-lab.git)をクローン済みであること。
+ 演習「テスト用にTiDBクラスタを作成する」を完了していること。

### 所要時間
+ この演習は約15分程度かかります。

### タスク
1. TiDBサーバーに接続します。
2. デモのスクリプトを確認して理解します。
3. グローバル一時テーブルを使用します。

### 手順
1. TiDB サーバーに接続します。

   + a) TiDB Playgroundクラスタのユーザーの場合。
     ```
     $ cd tidb-course-201-lab/scripts
     $ ./connect-4000.sh
     ...
     tidb:4000>
     ```

   + b) TiDB CloudのServerless Tierのユーザーの場合。
     ```
     $ cd tidb-course-201-lab/scripts
     $ ./connect-cloud.sh
     ...
     tidb:4000>
     ```

2. デモスクリプト `07-demo-global-temp-table.sql`を確認し、理解します。

     `Manual commit, the data is cleared` ステップでは、`test.temp2`の行がクリアされ、3回の試行でグローバル一時テーブルの作成を実施します。1回目は失敗し、2回目は成功し、3回目は失敗する予定です。そうなる理由はコメントを通じて説明しています。
     ```
     tidb:4000> SYSTEM cat 07-demo-global-temp-table.sql
     /* source 07-demo-global-temp-table.sql */

     /* Setup: Create a global temporary table */
     DROP TABLE IF EXISTS test.temp2, test.perm3;

     /* Create global temporary table attempt 1, fail with error code 1064 */
     CREATE GLOBAL TEMPORARY TABLE test.temp2 (id BIGINT);

     /* Create global temporary table attempt 2 */
     CREATE GLOBAL TEMPORARY TABLE test.temp2 (id BIGINT) ON COMMIT DELETE ROWS;

     /* Turn off autocommit for current session */
     SET @@autocommit = 'OFF';

     /* Insert data into the global temporary table */
     INSERT INTO test.temp2 VALUES (10);

     /* Query 1: Check the data in the global temporary table, expecting 10 */
     SELECT * FROM test.temp2;

     /* Manual commit, the data is cleared */
     COMMIT;

     /* Query 2: Check the data in the global temporary table again */
     SELECT * FROM test.temp2;

     /* Create a permanent table */
     CREATE TABLE test.perm3 (id BIGINT);

     /* Create global temporary table attempt 3, error code 1050 is expected */
     CREATE GLOBAL TEMPORARY TABLE test.perm3 (id BIGINT) ON COMMIT DELETE ROWS;
     ```

3. `07-demo-global-temp-table.sql`のデモスクリプトを実行して、結果を観察します（TiDB Playgroundクラスタ接続を例に使います）。

   ```sql
   SOURCE 07-demo-global-temp-table.sql
   ```
   ```
   tidb:4000> SOURCE 07-demo-global-temp-table.sql
   --------------
   DROP TABLE IF EXISTS test.temp2, test.perm3
   --------------

   Query OK, 0 rows affected, 2 warnings (0.01 sec)

   --------------
   CREATE GLOBAL TEMPORARY TABLE test.temp2 (id BIGINT)
   --------------

   ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 52 near ""GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together
   --------------
   CREATE GLOBAL TEMPORARY TABLE test.temp2 (id BIGINT) ON COMMIT DELETE ROWS
   --------------

   Query OK, 0 rows affected (0.75 sec)

   --------------
   SET @@autocommit = 'OFF'
   --------------

   Query OK, 0 rows affected (0.00 sec)

   --------------
   INSERT INTO test.temp2 VALUES (10)
   --------------

   Query OK, 1 row affected (0.00 sec)

   --------------
   SELECT * FROM test.temp2
   --------------

   +------+
   | id   |
   +------+
   |   10 |
   +------+
   1 row in set (0.00 sec)

   --------------
   COMMIT
   --------------

   Query OK, 0 rows affected (0.01 sec)

   --------------
   SELECT * FROM test.temp2
   --------------

   Empty set (0.00 sec)

   --------------
   CREATE TABLE test.perm3 (id BIGINT)
   --------------

   Query OK, 0 rows affected (0.54 sec)

   --------------
   CREATE GLOBAL TEMPORARY TABLE test.perm3 (id BIGINT) ON COMMIT DELETE ROWS
   --------------

   ERROR 1050 (42S01): Table 'test.perm3' already exists
   ```

4. `test.temp2`に1行挿入し、トランザクションをアクティブに保ち、テーブル内容を確認します。

   ```sql
   SET @@AUTOCOMMIT=OFF;
   INSERT INTO test.temp2 VALUES (1);
   SELECT * FROM test.temp2;
   ```
   ```
   tidb:4000> SET @@AUTOCOMMIT=OFF;
   --------------
   SET @@AUTOCOMMIT=OFF
   --------------

   Query OK, 0 rows affected (0.00 sec)

   tidb:4000> INSERT INTO test.temp2 VALUES (1);
   --------------
   INSERT INTO test.temp2 VALUES (1)
   --------------

   Query OK, 1 row affected (0.00 sec)

   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   +------+
   | id   |
   +------+
   |    1 |
   +------+
   1 row in set (0.00 sec)
   ```

5. 新しいターミナルウィンドウを開いて、ユーザー`root`でログインします。

   ```
   $ ./connect-4000.sh
   ```

6. グローバル一時テーブル`test.temp2`をクエリします。テーブルは存在し、空である必要があります。
   ```sql
   SELECT * FROM test.temp2;
   ```
   ```
   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   Empty set (0.00 sec)
   ```

7. `test.temp2`に1行を挿入し、トランザクションをアクティブに保ち、テーブルの内容を確認します。
   ```sql
   SET @@AUTOCOMMIT=OFF;
   INSERT INTO test.temp2 VALUES (2);
   SELECT * FROM test.temp2;
   ```
   ```
   tidb:4000> SET @@AUTOCOMMIT=OFF;
   --------------
   SET @@AUTOCOMMIT=OFF
   --------------

   Query OK, 0 rows affected (0.01 sec)

   tidb:4000> INSERT INTO test.temp2 VALUES (2);
   --------------
   INSERT INTO test.temp2 VALUES (2)
   --------------

   Query OK, 1 row affected (0.00 sec)

   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   +------+
   | id   |
   +------+
   |    2 |
   +------+
   1 row in set (0.00 sec)
   ```

8. トランザクションをコミットして、テーブルの内容を確認し、中身が空であることを確認します。
   ```sql
   COMMIT;
   SELECT * FROM test.temp2;
   ```
   ```
   tidb:4000> COMMIT;
   --------------
   COMMIT
   --------------

   Query OK, 0 rows affected (0.00 sec)

   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   Empty set (0.00 sec)
   ```

9. 最初のターミナルに戻って、クエリを実行し、コミットしてから再びクエリを実行します。その結果を観察します。
   ```sql
   SELECT * FROM test.temp2;
   COMMIT;
   SELECT * FROM test.temp2;
   ```
   ```
   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   +------+
   | id   |
   +------+
   |    1 |
   +------+
   1 row in set (0.01 sec)

   tidb:4000> COMMIT;
   --------------
   COMMIT
   --------------

   Query OK, 0 rows affected (0.00 sec)

   tidb:4000> SELECT * FROM test.temp2;
   --------------
   SELECT * FROM test.temp2
   --------------

   Empty set (0.00 sec)
   ```

## まとめ
ローカル一時テーブルとは異なり、グローバル一時テーブルのテーブル定義は永続テーブルと同じ名前空間にあり、すべてのセッションから見えます。ただし、グローバル一時テーブルのデータは現在のトランザクションのみに表示されます。つまり、トランザクションが終了すると、データは自動的にクリアされます。

## 演習終わり