データベース - MySQL - ログの出力・ローテーション

 
1. 概要
2. ログ出力用のディレクトリ作成
3. /usr/local/etc/mysql/my.cnf 編集
4. ログローテーション

1. 概要

 ここでの、ログの出力およびローテーションの話は、FreeBSD 11.2 RELEASE 上のバージョン 5.7 での話です。

> mysql --version
mysql  Ver 14.14 Distrib 5.7.24, for FreeBSD11.2 (amd64) using  EditLine wrapper
 他のプラットフォームやバージョンでは、コンフィグレーションファイルの場所や書式が異なったりしますのでご注意ください。  以下のサイトを参考にさせていただきました。
MySQL における4つのログファイルの設定と確認方法 | サービス | プロエンジニア」
「MySQL のログに出力されるタイムスタンプがおかしい件 - 小さな星がほらひとつ
 デフォルトではどうもログは本体と同じく

/var/db/mysql
 にあるようで、設定していない状態で見ると

/var/db/mysql/ホスト名-slow.log
/var/db/mysql/ホスト名.ドメイン名.err
 ってファイルにそれぞれ、スローログ・エラーログってのが出力されているようです。  どんだけ太るかわからんし、ログは /var/log にまとめたいのだ。

2. ログ出力用のディレクトリ作成

 先にディレクトリと空ファイルを作成しておかないと、MySQL のサーバを再起動してもこけたりします。

mkdir -pv /var/log/mysql
touch /var/log/mysql/mysql-err.log
touch /var/log/mysql/mysql-sql.log
touch /var/log/mysql/mysql-slow.log
chown -Rv mysql:mysql /var/log/mysql

3. /usr/local/etc/mysql/my.cnf 編集

 コンフィグレーションファイルを編集します。

[mysqld]	←	のセクションに以下を追加

log_timestamps		= SYSTEM

#	エラーログ
log_error			="/var/log/mysql/mysql-err.log"
log_warnings		= 1

#	クエリーログ
general_log			= 1
general_log_file	= "/var/log/mysql/mysql-sql.log"
log_output			= FILE

#	スロークエリーログ
slow_query_log		= 1
slow_query_log_file	= "/var/log/mysql/mysql-slow.log"
log_queries_not_using_indexes
log_slow_admin_statements
 log_timestamps は、設定しないとログが UTC で出力されてしまうので、日時がわかりにくいのです。  日本では JST で。  エラーログ。  いわゆるエラーログですな、ワーニングも出そうと思います。  クエリーログというのは、クエリーを発行する都度に出力するらしい。  スロークエリーログ。  遅いクエリーやインデックスを使っていないクエリーについて出力するらしい。  ここでいったん、コンフィグレーションファイルの書き間違いがないことを確認して、再起動します。

/usr/local/libexec/mysqld --verbose --help > /dev/null
service mysql-server restart
 ログが出力され始めます。

> ls -l /var/log/mysql/
total 12K
-rw-r--r-- 1 mysql mysql 610 Dec 18 15:16 mysql-err.log
-rw-r--r-- 1 mysql mysql 519 Dec 18 15:41 mysql-slow.log
-rw-r--r-- 1 mysql mysql 879 Dec 18 15:41 mysql-sql.log

4. ログローテーション

 前項で出力先を変えたログですが・・・。  もちろん、データベースの構成や運用で相当違ってくるのは当然です。  アクセス頻度の高いデータベースであれば、クエリーログなんか出してたらすぐにディスクがいっぱいになるかと思います。  わたしの環境では

/var/log/mysql/mysql-err.log	←	少し、めったに増えない
/var/log/mysql/mysql-slow.log	←	まあまあ、案外多いのでびっくりしています
/var/log/mysql/mysql-sql.log	←	ほぼ予想通り、大量に増えます
 とりあえず、ログローテーションを書いて思い通りにならないことがあったので調べたら。  「MySQL - ログローテート [fl8 Wiki]」に納得のいく記事がありました。  mysql ではログのファイルをローテーションさせても mysqladmin flush-logs というコマンドを発行しないと前のログファイルに書き続けるという apache よりさらに面倒な仕掛けがあるようです。  newsyslog.conf でプロセスの再起動はできてもコマンドを発行する仕掛けはないので、ローテーションさせると同時に cron でコマンドを発行するしかないようです。  そうなれば、サイズによるローテーションはできないなぁ・・・。悩ましい。  とりあえず、毎日1時にローテーションさせて、7世代(1週間)管理するようにします。

/usr/local/etc/newsyslog.conf.d/mysql.conf
 を作成して、以下のように記述。

# logfilename          [owner:group]    mode count size when  flags [/pid_file] [sig_num]
/var/log/mysql/*.log    mysql:mysql     644  7     *    @T01  BG
 それで crontab に「/usr/local/bin/mysqladmin -u root -pパスワード flush-logs」ってコマンドを発行するようにしていたら・・・。  いつの頃からか

mysqladmin: [Warning] Using a password on the command line interface can be insecure.
 てなエラーになって機能しないようになっていました。  「パスワードを指定して mysql コマンドを実行すると表示されるワーニングを回避 - Qiita」を参考にさせていただいて回避策がわかりました。  とりあえず、MySQL のいつだかのバージョン以降、平文のコマンドにパスワードを記述してはいけないそうなのです。  そんで

/ファイルパス/root.cnf
 というファイルを作成して、以下を記述します。

[client]
user		= root
password	= root のパスワード
 でこれを利用して実行するシェルスクリプトを作成(実行権限をつけるのを忘れないように)

/スクリプトパス/mysql-log-update.sh
 下記のように記述します。

#!/bin/sh -x

/usr/local/bin/mysqladmin --defaults-extra-file=/ファイルパス/root.cnf flush-logs
 次に

/etc/crontab
 に以下の記述を追加。

#minute hour mday month wday who  command
0       1    *    *     *    root /スクリプトパス/mysql-log-update.sh
 これでローテーションも機能するようになりました。  ローテーションのタイミングについては、様子を見て調整しようかと思います。