## モジュール 3: 潜在的なランナウェイクエリの監視

+ モジュール2で学んだ通り、ランナウェイクエリとして特定されるまでには一定の時間がかかります。例えば、`EXEC_ELAPSED='10s'`と設定した場合、各ランナウェイクエリが特定されるまで最低10秒かかります。特定待ちのランナウェイクエリが多すぎると、システムリソースが枯渇する可能性があります。
+ `WATCH`機能を使うことで、TiDBはクエリの実行前にランナウェイクエリを特定できます。
+ `WATCH`機能のオプションには、`EXACT`（完全一致）、`SIMILAR`（SQLダイジェスト一致）、`PLAN`（プランダイジェスト一致）があります。

### 手順 1. リソースグループの再定義

+ 下記のクエリでリソースグループを再定義します。モジュール2のリソースグループと比べて、今回は`WATCH=SIMILAR`と`DURATION='100m'`が追加されています。これは、一度ランナウェイクエリとして特定されたクエリと同じSQLダイジェストを持つクエリは、100分間実行されることなくランナウェイクエリとして扱われることを意味します。

  ```sql
  ALTER RESOURCE GROUP rg1 QUERY_LIMIT=(PROCESSED_KEYS=100, ACTION=KILL, WATCH=SIMILAR DURATION='100m');
  ```

  ```sql
  SET RESOURCE GROUP `rg1`;
  SELECT CURRENT_RESOURCE_GROUP();
  ```

  ```output
  tidb:db1> SET RESOURCE GROUP `rg1`;
  Query OK, 0 rows affected (0.00 sec)

  tidb:db1> SELECT CURRENT_RESOURCE_GROUP();
  +--------------------------+
  | CURRENT_RESOURCE_GROUP() |
  +--------------------------+
  | rg1                      |
  +--------------------------+
  1 row in set (0.00 sec)
  ```

### 手順 2. クエリを生成する

  ```sql
  USE sbtest;
  SELECT
    CONCAT(
      'UPDATE sbtest1 SET k = ',
      k,
      ' WHERE c = ''',
      c,
      ''';'
    ) AS update_stmt
  FROM sbtest1
  WHERE id IN (1123127, 3852438, 5964556, 9475339);
  ```

  ```output
  +---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  | update_stmt                                                                                                                                                         |
  +---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  | UPDATE sbtest1 SET k = 5017151 WHERE c = '84493442613-55715520812-07466942581-87906122717-51164395568-98852954940-85704352045-80573166498-09592001496-94838080154'; |
  | UPDATE sbtest1 SET k = 4473488 WHERE c = '16343179582-65765105184-12762861962-64885861338-91163734747-54197012107-93125617766-13310713443-81881465217-52031359817'; |
  | UPDATE sbtest1 SET k = 5018359 WHERE c = '30686701254-95654597113-74779030530-51744141684-25702975952-73545252771-00587103499-70903471471-10016980123-39589338114'; |
  | UPDATE sbtest1 SET k = 4978938 WHERE c = '91059747631-65344828194-11158241479-43561595237-60087824823-10114555067-54188804463-85679024352-56990670474-10055950458'; |
  +---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  4 rows in set (0.00 sec)
  ```

### 手順 3. クエリを実行

+ ステップ2の出力結果から**最初のクエリ**を実行しましょう。
+ この手順では、1095654個のキーを処理するため、ランナウェイクエリとして分類されるクエリを実行します。
+ 今回は、クエリが実際に実行された後に中断されます。以降100分間、同じSQLダイジェストを持つクエリは実行されることなくランナウェイクエリとして扱われます。

  ```output
  ERROR 8253 (HY000): Query execution was interrupted, identified as runaway query [ProcessedKeys = 1095654(100)]
  ```

### 手順 4. 類似パターンのクエリを実行

+ この手順では、手順3と同じパターンですが、`c`の値を`abc0`に変更したクエリを実行します。この値はテーブルに存在しないはずです。
+ 実行結果は「runaway watch listにより隔離・中断された」となります。これは、手順3と同じSQLダイジェストを持つため、実行されることなく隔離されました。

  ```sql
  UPDATE sbtest1 SET k = 4751268 WHERE c = 'abc0';
  ```

  ```output
  ERROR 8254 (HY000): Quarantined and interrupted because of being in runaway watch list
  ```

### 手順 5. ランナウェイクエリのウォッチリストを確認

+ 次のコマンドでウォッチリストに登録されているクエリを確認します。
+ 結果から、リソースグループ`rg1`でSQLダイジェストが`a7a2fbb8a227456777fd6d3dd68dee4089cb05413ccac0f3731d2fa538a09dea`のクエリは、`2025-07-15 01:13:54`から`2025-07-15 02:53:54`の間、すべてKILLされることが分かります。

  ```sql
  SELECT * from information_schema.runaway_watches ORDER BY id\G
  ```

  ```output
  tidb:db1> SELECT * from information_schema.runaway_watches ORDER BY id\G
  *************************** 1. row ***************************
                   ID: 1
  RESOURCE_GROUP_NAME: rg1
           START_TIME: 2025-07-15 01:13:54
             END_TIME: 2025-07-15 02:53:54
                WATCH: Similar
           WATCH_TEXT: a7a2fbb8a227456777fd6d3dd68dee4089cb05413ccac0f3731d2fa538a09dea
               SOURCE: 10.90.2.141:4000
               ACTION: Kill
                 RULE: ProcessedKeys = 1095654(100)
  ```

### 手順 6. クエリを手動でWATCHリストに追加

+ 場合によっては、クエリを手動でウォッチリストに追加する必要があります。例えば`SELECT *`のような明らかにシステムに悪影響を与えるクエリです。

  ```sql
  QUERY WATCH ADD RESOURCE GROUP rg1 ACTION KILL SQL TEXT SIMILAR TO 'select * from sbtest1';
  ```

  ```output
  tidb:db1> QUERY WATCH ADD RESOURCE GROUP rg1 ACTION KILL SQL TEXT SIMILAR TO 'select * from sbtest1';
  +----------+
  | WATCH_ID |
  +----------+
  |        2 |
  +----------+
  1 row in set (0.00 sec)
  ```

### 手順 7. `SELECT *`クエリを実行

+ 出力から分かる通り、このクエリも隔離されてKILLされ、実行されません。

  ```sql
  SELECT * FROM sbtest1;
  ```

  ```output
  tidb:db1> SELECT * FROM sbtest1;
  ERROR 8254 (HY000): Quarantined and interrupted because of being in runaway watch list
  ```

### 手順 8. WATCHクエリリストを再確認

+ ランナウェイクエリのウォッチリストを再度確認すると、現在2つのクエリが登録されていることが分かります。

  ```sql
  SELECT * from information_schema.runaway_watches ORDER BY id\G
  ```

  ```output
  tidb:db1> SELECT * from information_schema.runaway_watches ORDER BY id\G
  *************************** 1. row ***************************
                  ID: 1
  RESOURCE_GROUP_NAME: rg1
          START_TIME: 2025-07-15 01:13:54
            END_TIME: 2025-07-15 02:53:54
                WATCH: Similar
          WATCH_TEXT: a7a2fbb8a227456777fd6d3dd68dee4089cb05413ccac0f3731d2fa538a09dea
              SOURCE: 10.90.2.141:4000
              ACTION: Kill
                RULE: ProcessedKeys = 1095654(100)
  *************************** 2. row ***************************
                   ID: 2
  RESOURCE_GROUP_NAME: rg1
           START_TIME: 2025-07-15 01:17:38
             END_TIME: UNLIMITED
                WATCH: Similar
           WATCH_TEXT: 35c978d76693ff8e8db1c5cb395ed9a09408c04deb295e4e78dbadedccd18fd6
               SOURCE: manual
               ACTION: Kill
                 RULE: None
  2 rows in set (0.00 sec)
  ```
