モヒカンメモ

髪色が定期的に変わることに定評のある(比較的)若者Webエンジニアの備忘録

MySQLに投げられたすべてのSQLクエリをロギングする

概要

クエリビルダやORMが生成するクエリを確認したいなどの理由で、MySQLに投げられたクエリを確認したくなることがある

そういうときは、MySQLのクエリログ (general_log) と言う設定をONにすることによって、すべてのクエリをログに吐かせることができる

dev.mysql.com

5.2.3 一般クエリーログ 一般クエリーログは、mysqld の実行内容の一般的な記録です。サーバーは、クライアントが接続または接続解除したときに情報をこのログに書き込み、クライアントから受け取った各 SQL ステートメントをログに記録します。一般クエリーログは、クライアント側でエラーが疑われるとき、クライアントが mysqld に送信した内容を正確に知りたい場合に非常に役立つことがあります。

やってみる

1. 現在の設定を確認する

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.16    |
+-----------+
1 row in set (0.00 sec)

mysql> show variables like 'general_log%';
+------------------+---------------------------------+
| Variable_name    | Value                           |
+------------------+---------------------------------+
| general_log      | OFF                             |
| general_log_file | /var/lib/mysql/3a9a8fa16e7a.log |
+------------------+---------------------------------+
2 rows in set (0.00 sec)

デフォルトではOFFになっている。この状態で クエリが投げられてもロギングされない

root@3a9a8fa16e7a:/# ls -alh /var/lib/mysql/3a9a8fa16e7a.log
ls: cannot access '/var/lib/mysql/3a9a8fa16e7a.log': No such file or directory

2. ONにしてみる

mysql> set global general_log = on;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation

このユーザには権限がなかったので、グローバル設定を書き換える権限のあるユーザでログインしなおして再チャレンジ

mysql> set global general_log = on;
Query OK, 0 rows affected (0.02 sec)

mysql> show variables like 'general_log%';
+------------------+---------------------------------+
| Variable_name    | Value                           |
+------------------+---------------------------------+
| general_log      | ON                              |
| general_log_file | /var/lib/mysql/3a9a8fa16e7a.log |
+------------------+---------------------------------+
2 rows in set (0.01 sec)

クエリログの設定をONにしたところ即座にログファイルが作られた

root@3a9a8fa16e7a:/# ls -alh /var/lib/mysql/3a9a8fa16e7a.log
-rw-r----- 1 root root 256  5月 25 17:17 /var/lib/mysql/3a9a8fa16e7a.log

3. ロギングされるか確かめる

適当にクエリを投げてみる

mysql> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.01 sec)
root@3a9a8fa16e7a:/# tail /var/lib/mysql/3a9a8fa16e7a.log
/usr/sbin/mysqld, Version: 8.0.16 (MySQL Community Server - GPL). started with:
Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock
Time                 Id Command    Argument
2019-05-25T08:17:19.278525Z    26 Query show variables like 'general_log%'
2019-05-25T08:18:11.802232Z    25 Query select 1

投げたクエリはちゃんとログファイルに書かれていた🎉

補足 (1)

本番環境でクエリログを取る場合、下記に注意すること

  • ログのぶんだけディスクを食うし、ディスクI/Oが増えるぶんパフォーマンスも劣化する
  • 機微情報を扱うクエリが投げられる場合、ログにも機微情報が乗るのでログファイルは慎重に扱う

補足 (2)

デフォルトではgeneral logはファイルに吐き出されるが、 log_output という変数を変更することで吐き出し先をテーブルに変更することもできる

mysql> set global log_output = "table";

log_output