このエントリーは 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 PROCESSLISTでMySQL側の状態を確認すると、実際のコネクション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 と異なる動きをしているように見えるのですが、よくよく調べてみると、違いました。
なんと、SQL が SELECT 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 で確認しました