GA

2025/12/15

最近のmysqlコマンドラインクライアントの変更を見てみる

この記事は MySQL - Qiita Advent Calendar 2025 の15日目の記事です。

昨日は @meijik さんの 君はMySQL RP を知っているか?! でした。


ここ最近(?) 小さな mysqlコマンドラインクライアント への変更が入っているのでそれを紹介します。

MySQLサーバー ( mysqld ) の機能ではないので、接続先のバージョンがいくつであっても変わりません。クライアントのバージョン依存です。

コメントが勝手に消えなくなった

実は mysql コマンドラインクライアントには「SQLの中のコメントを消してからMySQLサーバに送信する」機能がありました。バージョン指定のためのコメントやオプティマイザヒントは消さないようになっています。純粋なコメントです。

以下は各バージョンの mysql から MySQL 8.4.7のサーバに対して SELECT 'Hello' /* ,World/;' を送信しようとしているところです( <<< で標準入力に入るので、 echo .. | mysql .. と同じ実行の仕方です)


$ /usr/mysql/5.7.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SELECT 'Hello' /* ,World */;"

Hello

Hello

$ /usr/mysql/8.0.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SELECT 'Hello' /* ,World */;"

Hello

Hello

$ /usr/mysql/8.4.7/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SELECT 'Hello' /* ,World */;"

Hello

Hello

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SELECT 'Hello' /* ,World */;"

Hello

Hello

ジェネラルログを確認するとこんな感じになります。


2025-12-15T09:04:30.826100-00:00           17 Connect   root@localhost on  using Socket

2025-12-15T09:04:30.829805-00:00           17 Query     select @@version_comment limit 1

2025-12-15T09:04:30.834689-00:00           17 Query     SELECT 'Hello'

2025-12-15T09:04:30.834788-00:00           17 Quit

2025-12-15T09:04:33.468778-00:00           18 Connect   root@localhost on  using Socket

2025-12-15T09:04:33.472739-00:00           18 Query     select @@version_comment limit 1

2025-12-15T09:04:33.478144-00:00           18 Query     SELECT 'Hello'

2025-12-15T09:04:33.478406-00:00           18 Quit

2025-12-15T09:04:36.309772-00:00           19 Connect   root@localhost on  using Socket

2025-12-15T09:04:36.312713-00:00           19 Query     select @@version_comment limit 1

2025-12-15T09:04:36.319830-00:00           19 Query     SELECT 'Hello' /* ,World */

2025-12-15T09:04:36.321674-00:00           19 Quit

2025-12-15T09:04:38.924431-00:00           20 Connect   root@localhost on  using Socket

2025-12-15T09:04:38.928317-00:00           20 Query     select @@version_comment limit 1

2025-12-15T09:04:38.935416-00:00           20 Query     SELECT 'Hello' /* ,World */

2025-12-15T09:04:38.935519-00:00           20 Quit

上から5.7, 8.0, 8.4, 9.5なので8.4の時点で勝手にコメントをストリップしなくなりました。

昔からずっと —comments というオプションで制御できたんですが、8.0とそれ以前はこれのデフォルトがOFF, 8.4とそれ以降はONに変わったという感じです。

/* .. */ で実験していますが、 --# も消えます。お試しあれ(?)
以前の動作に戻すなら --skip-comments です。

デフォルトでは \G で縦表示できなくなった

SHOW ENGINE INNODB STATUS\GSHOW REPLICA STATUS\G はよく縦表示に用いるんじゃないかと思いますが、この \Gmysql コマンドラインクライアントの独自記法で、その他のクライアントやアプリケーションから使うときに \G とかつけるとシンタックスエラーになります。

-e や標準入力からSQLを受け取った時の mysql コマンドラインクライアントは今までこの \G をデフォルト(あるいは設定不能)で常に解釈していたのが、9.x のどこかで解釈しない方がデフォルトになりました。

$ /usr/mysql/5.7.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SHOW ENGINE INNODB STATUS\G" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/8.0.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SHOW ENGINE INNODB STATUS\G" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/8.4.7/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SHOW ENGINE INNODB STATUS\G" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "SHOW ENGINE INNODB STATUS\G" | head -2
ERROR at line 1: Unknown command '\G'.

↑9.5のクライアントだけエラーになっています。

なおこれは非対話モードにだけ効く変更なので、対話モードの動作には変わりありません。9.5のクライアントで同じオプションでも、対話モードなら↓のように表示ができます。

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 31
Server version: 8.4.7 Source distribution

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
=====================================
2025-12-15 09:21:22 139964134168320 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 12 seconds

..

ちなみに俺は昔から -E を使うのに慣れているのであまりこの変更の影響を受けません。

-E は引数を取らない、 psqlで言うところの -x みたいに振る舞うオプションです。 -e とセットで使う時に -eE と書くとエラーになります( -e の引数が 'E' という扱いになってしまう) -Ee で並べる(もしくは -E -e と離したり別のオプションを挟んでみたりする)必要があります。

$ /usr/mysql/5.7.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock -E <<< "SHOW ENGINE INNODB STATUS" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/8.0.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock -E <<< "SHOW ENGINE INNODB STATUS" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/8.4.7/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock -E <<< "SHOW ENGINE INNODB STATUS" | head -2
*************************** 1. row ***************************
  Type: InnoDB

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock -E <<< "SHOW ENGINE INNODB STATUS" | head -2
*************************** 1. row ***************************
  Type: InnoDB

-E はずっと昔からあるのでこれを使っていると9.xでの変更に気が付かない可能性があります。なお、以前と同じ動作にするには —commands です。

この動作変更は非互換としてバグ報告されており、デフォルトをもとに戻してほしい場合はこのバグレポートで応援することができます。

MySQL Bugs: #118819: Vertical (\G) doesn't work in MySQL 9.4.0


$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock --commands <<< "SHOW ENGINE INNODB STATUS\G" | head -2
*************************** 1. row ***************************
  Type: InnoDB

8.4の地味なバグの修正

少なくともMySQL 8.4.7の mysql コマンドラインクライアントにある地味なバグが直っています。非対話モードで use にセミコロンを1個余計につけるとエラーになります。

$ /usr/mysql/5.7.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "use d1;;"

$ /usr/mysql/8.0.44/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "use d1;;"

$ /usr/mysql/8.4.7/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "use d1;;"
ERROR at line 1: USE must be followed by a database name

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock <<< "use d1;;"

対話モードでも、他のバージョンとはエラーが違います。
8.4以外のバージョンでは↓のように

$ /usr/mysql/9.5.0/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock

mysql> use d1;;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
ERROR:
No query specified

use d1; が解釈された後に本文なしの ; が来たと解釈して、Database changed の後に No query specified のエラーになります(エラーエラー言ってますが、これはサーバーサイドエラーではなく mysqlコマンドラインクライアント内で独自にエラー です)

8.4のコマンドラインクライアントでは

$ /usr/mysql/8.4.7/bin/mysql --no-defaults -uroot -S /usr/mysql/8.4.7/data/mysql.sock

mysql> use d1;;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
ERROR:
USE must be followed by a database name

エラーが USE must be followed by a database name に変わってました。 use d1; を解釈した後に use ; と解釈しなおしたような気配がします。

これはこの記事を書くために git log を眺めていて気が付いただけです。バグなのでそのうち直ると思いますし直らなくても特に困る人はいなさそう。。

History for client/mysql.cc - mysql/mysql-server · GitHub

明日は @wsigma21 さんです!

0 件のコメント :

コメントを投稿