MySQL - スロークエリログを記録する

MySQL を使ったシステムの運用中に「特定の処理を行った場合だけ異常に時間が掛かる」なんて言う時には、たいてい実行しているクエリが重かったりする訳です。

そして、その原因となったクエリを調べる際に有効なのがスロークエリログ。

クエリの実行に一定時間以上掛かった場合、そのクエリを記録してくれます。

が、明示的に有効にしていないと記録されていなかったり、そもそも稼働中のシステムで有効にする際にはどうするんだっけ?ってなったので、その辺りを纏めてみます。

では、まず簡単にスロークエリを記録するための設定から。

はじめに my.cnf に下記の設定を追加します。

slow_query_log = 1
slow_query_log_file = /path/to/slow_query_log_file

設定の反映するために MySQL サービスを再起動します。

service mysqld restart

設定の確認は以下のクエリで出来ます。

mysql > SHOW VARIABLES LIKE 'slow_query%';
+---------------------+-------------------------------+
| Variable_name       | Value                         |
+---------------------+-------------------------------+
| slow_query_log      | ON                            |
| slow_query_log_file | /path/to/slow_query_log_file  |
+---------------------+-------------------------------+

正常に反映されている場合は上記のように表示されます。


で、ここまでは良いのですが、運用中のシステムで停止できないサーバー、例えばマスターDB とかの場合、上記の様にサービスの再起動はできません。

ならば、再読み込みを行なったらどうかというと・・・

service mysqld reload

この場合、slow_query_log の設定は反映されません。

mysql > SHOW VARIABLES LIKE 'slow_query%';
+---------------------+---------------------------------+
| Variable_name       | Value                           |
+---------------------+---------------------------------+
| slow_query_log      | OFF                             |
| slow_query_log_file | /var/run/mysqld/mysqld-slow.log |
+---------------------+---------------------------------+

ではどうするか?

そんな時には SET GLOBAL で設定すると良いようです。

具体的には以下の様にクエリを実行するだけ。

SET GLOBAL slow_query_log = 1;
SET GLOBAL slow_query_log_file = '/path/to/slow_query_log_file';

これで設定が反映され slow_query_log が記録去るようになります。

mysql > SHOW VARIABLES LIKE 'slow_query%';
+---------------------+-------------------------------+
| Variable_name       | Value                         |
+---------------------+-------------------------------+
| slow_query_log      | ON                            |
| slow_query_log_file | /path/to/slow_query_log_file  |
+---------------------+-------------------------------+

ちなみに、この時に slow_query_log_file に指定されたパスに対して mysqld の実行ユーザーが書き込み権限を持っていないとエラーになるので注意が必要です。

mysql> SET GLOBAL slow_query_log_file = '/path/to/slow_query_log_file';
ERROR 1231 (42000): Variable 'slow_query_log_file' can't be set to the value of '/path/to/slow_query_log_file'

当然、my.cnf に設定を追加しておかないと MySQL を再起動した際に設定が無効になってしまうのですが、逆に言えば一時的にスロークエリのログを取りたい場合などは my.cnf を変更するのではなくて SET GLOBAL を使って ON/OFF を切り替えたほうが早いかも知れませんね。

っと言う感じですが、クエリのチューニングを考えると MySQL って何かなぁ・・・って毎回思います。

「エンジニアの腕の見せ所」っと言われたら確かにそうなのかも知れませんが、そのくらい自分で何とかしろよ・・・って思ってしまったり。。。