背景
GraphQLでN+1になってないかを確認したいときに、スロークエリだけでなく全てのクエリログを見たくなったのでその設定方法を説明します。
- Dockerコンテナの中に直接入って見る方法
- Dockerログに吐き出す方法
の2通りで説明します。
環境
設定方法
まずは直接コンテナに入って見る方法です。
MySQLの設定
ローカルもしくはDockerコンテナ内でmysqlにログインして次のクエリを投げると設定を確認できます。
mysql> show variables like 'general_log%'; +------------------+---------------------------------+ | Variable_name | Value | +------------------+---------------------------------+ | general_log | OFF | | general_log_file | /var/lib/mysql/cfadc6a5faf3.log | +------------------+---------------------------------+
general_log
がON
になっていないとクエリログは出ないのでONにします。
mysql> set global general_log = on; mysql> show variables like 'general_log%'; +------------------+---------------------------------+ | Variable_name | Value | +------------------+---------------------------------+ | general_log | ON | | general_log_file | /var/lib/mysql/cfadc6a5faf3.log | +------------------+---------------------------------+
以上で設定はOKです。
確認
後はコンテナに入り、general_log_file
をtailすればクエリログを見ることができます。
$ tail -f /var/lib/mysql/cfadc6a5faf3.log 2023-11-30T01:21:20.370746Z 38 Connect root@192.168.65.1 on mydb using TCP/IP 2023-11-30T01:21:20.371718Z 38 Query SELECT @@socket, @@max_allowed_packet, @@wait_timeout 2023-11-30T01:21:20.374743Z 38 Prepare SELECT `mydb`.`User`.`id`, `mydb`.`User`.`email`, `mydb`.`User`.`name` FROM `mydb`.`User` WHERE 1=1 ORDER BY `mydb`.`User`.`id` ASC LIMIT ? OFFSET ? 2023-11-30T01:21:20.375434Z 38 Execute SELECT `mydb`.`User`.`id`, `mydb`.`User`.`email`, `mydb`.`User`.`name` FROM `mydb`.`User` WHERE 1=1 ORDER BY `mydb`.`User`.`id` ASC LIMIT 100 OFFSET 0 2023-11-30T01:21:20.376700Z 38 Prepare SELECT `mydb`.`Post`.`id`, `mydb`.`Post`.`authorId` FROM `mydb`.`Post` WHERE `mydb`.`Post`.`authorId` IN (?) 2023-11-30T01:21:20.377051Z 38 Execute SELECT `mydb`.`Post`.`id`, `mydb`.`Post`.`authorId` FROM `mydb`.`Post` WHERE `mydb`.`Post`.`authorId` IN (1) 2023-11-30T01:21:34.027736Z 14 Query select * from User
ログファイルの場所を変更したい場合
デフォルトだとランダムな文字列のファイル名になっているので、固定したファイルに吐き出したい場合は次のように設定します。
mysql> set global general_log_file = '/tmp/mysql.log'; mysql> show variables like 'general_log%'; +------------------+----------------+ | Variable_name | Value | +------------------+----------------+ | general_log | ON | | general_log_file | /tmp/mysql.log | +------------------+----------------+
Dockerログに直接吐き出す方法
次はdockerの標準出力ログに吐き出す方法です。
- docker run
- docker-compose
の2通りで解説します。
docker run
docker runにおけるCOMMAND
を次のようにいじります。
$ docker run -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD="mypass" \ mysql \ bash -c 'touch /tmp/mysql.log && tail -f /tmp/mysql.log & /usr/local/bin/docker-entrypoint.sh mysqld --datadir=/var/lib/mysql --user=root --general-log=true --general-log-file=/tmp/mysql.log'
general-log-file
に/dev/stdout
が指定できたらシンプルにできて理想ですが、現在はエラーが出ます(以前はできたようです)。
docker-compose
docker-composeの場合は次のようなyamlになります。
version: "3.9" services: mysql: image: arm64v8/mysql:8 restart: always command: > bash -c ' touch /tmp/mysql.log && tail -f /tmp/mysql.log & /usr/local/bin/docker-entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/tmp/mysql.log ' ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: mypass MYSQL_DATABASE: mydb
その他
localhostでアクセスするとコケる
host名をlocalhost
でアクセスしようとすると、
$ mysql --host=localhost -u root -p
次のようにエラーになりました。
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
mysqlはlocalhostを利用した接続に際してはUNIXドメインソケットを使おうと試みるため、127.0.0.1
としてTCPコネクションにする必要があるようです。
$ mysql --host=127.0.0.1 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 39 Server version: 8.2.0 MySQL Community Server - GPL Copyright (c) 2000, 2023, 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>