mita2 database life

主にMySQLに関するメモです

ProxySQL を使うと CONNECTION_ID() が MySQLと 異なる値を示す?

このエントリーは MySQL - Qiita Advent Calendar 2025 - Qiita の 10日目 のエントリーです。 昨日は @himura467 さんの 令和七年冬、DBD::mysql の quote メソッドを読む - ひむ日記 でした。


MySQL の Connection ID のおさらい

MySQLでは、クライアントから接続があるたびに、そのセッション(接続)を一意に識別するためのIDが割り当てられます。

Connection IDは、主に以下の方法で確認できます。

  • CONNECTION_ID() 関数

現在のセッションのIDを取得します。

mysql> SELECT CONNECTION_ID();
+-----------------+
| CONNECTION_ID() |
+-----------------+
|             132 |
+-----------------+
1 row in set (0.00 sec)
  • mysql コマンドのバナー

mysql コマンドで接続すると表示されるバナー中の Your MySQL connection id is 〜 でも確認できます。

$ mysql -h 127.0.0.1 -P 3306 -uroot 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 132
Server version: 8.0.44 MySQL Community Server - GPL
  • SHOW PROCESSLIST

Id 列で、他のセッションの Connection ID を確認することも出来ます。

mysql> SHOW PROCESSLIST;
+-----+-----------------+-----------------+<snip>-+------------------+
| Id  | User            | Host            |<snip> | Info             |
+-----+-----------------+-----------------+<snip>-+------------------+
|   6 | system user     |                 |<snip> | NULL             |
|   7 | event_scheduler | localhost       |<snip> | NULL             |
|  10 | system user     |                 |<snip> | NULL             |
|  11 | system user     |                 |<snip> | NULL             |
|  12 | system user     |                 |<snip> | NULL             |
|  13 | system user     |                 |<snip> | NULL             |
| 101 | root            | 127.0.0.1:43448 |<snip> | NULL             |
| 118 | root            | 127.0.0.1:43282 |<snip> | NULL             |
| 132 | root            | 127.0.0.1:60344 |<snip> | SHOW PROCESSLIST |
+-----+-----------------+-----------------+<snip>-+------------------+
9 rows in set, 1 warning (0.00 sec)

このConnection IDは、主にサーバー側での管理やトラブルシューティングに使用されます。

  • 接続をKILLする
  • EXPLAIN FOR CONNECTION XXX で実行中のクエリの実行計画を確認する

ProxySQL経由でCONNECTION_ID()の挙動

ProxySQL を経由した場合、SELECT CONNECTION_ID() が 「ProxySQL が独自に生成したコネクションID」になってしまいます*1。 以下の例では、SELECT CONNECTION_ID()7 を返していますが、SHOW PROCESSLISTMySQL側の状態を確認すると、実際のコネクションIDは 118 です。

mysql> SELECT CONNECTION_ID();
+-----------------+
| CONNECTION_ID() |
+-----------------+
|               7 |
+-----------------+
1 row in set (0.00 sec)

mysql> SHOW PROCESSLIST;
+-----+-----------------+-----------------+<snip>-+------------------+
| Id  | User            | Host            |<snip> | Info             |
+-----+-----------------+-----------------+<snip>-+------------------+
|   6 | system user     |                 |<snip> | NULL             |
|   7 | event_scheduler | localhost       |<snip> | NULL             |
|  10 | system user     |                 |<snip> | NULL             |
|  11 | system user     |                 |<snip> | NULL             |
|  12 | system user     |                 |<snip> | NULL             |
|  13 | system user     |                 |<snip> | NULL             |
| 101 | root            | 127.0.0.1:43448 |<snip> | NULL             |
| 118 | root            | 127.0.0.1:43282 |<snip> | SHOW PROCESSLIST |
| 132 | root            | 127.0.0.1:60344 |<snip> | NULL             |
+-----+-----------------+-----------------+<snip>-+------------------+
9 rows in set, 1 warning (0.00 sec)

なお、この挙動は ProxySQL の multiplexing を OFF にしていても起こります。

CONNECTION_ID() 関数の結果が置き換えられいる・・・わけではない

CONNECTION_ID() 関数が MySQL と異なる動きをしているように見えるのですが、よくよく調べてみると、違いました。 なんと、SQLSELECT CONNECTION_ID() と完全一致したときのみ、 ProxySQL の ID を返すような挙動になっていました。

以下の例では「AS〜」を付けただけで、MySQLの Connection ID が取得できていることがわかります。

mysql> SELECT CONNECTION_ID();
+-----------------+
| CONNECTION_ID() |
+-----------------+
|               9 |
+-----------------+
1 row in set (0.00 sec)

mysql> SELECT CONNECTION_ID() AS cid;
+-----+
| cid |
+-----+
| 118 |
+-----+
1 row in set (0.00 sec)

CONNECTION_ID<スペース>() でも MySQL の Connection ID になります。

mysql> SELECT CONNECTION_ID ();
+------------------+
| CONNECTION_ID () |
+------------------+
|              118 |
+------------------+
1 row in set (0.00 sec)

もちろん、INSERT 文でも正しく MySQL の Connection ID になります。

mysql> INSERT INTO t VALUES(CONNECTION_ID());
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM t;
+------+
| a    |
+------+
|  118 |
+------+
1 row in set (0.00 sec)

SELECT CONNECTION_ID() だけであれば、アプリへの影響がなさそうで安心しました。しかし、謎な仕様...


明日は hmatsu47 さんです!

*1: ProxySQL 3.0.3 で確認しました