MySQLのログローテーションについて、改めて動作を整理してみました。
今回は特に SIGUSR1
シグナルと、バイナリログ(binlog)の扱いについてご説明します。
バイナリログのローテーションと削除の仕組みのおさらい
バイナリログ(binlog)は、一定サイズを超えると自動的に新しいファイルにローテーションされます。
このサイズの上限は、max_binlog_size で制御されており、デフォルトでは 1GB です。
例えば、以下のように設定されている場合:
1 |
max_binlog_size = 256M |
この場合、1ファイルあたりのバイナリログサイズが約256MBを超えた時点で、新しい binlog ファイル(例:mysql-bin.000002)が作成されます。
ローテートされたバイナリログの保管期間は、expire_logs_days
または binlog_expire_logs_seconds
によって制御されます。ただし、期限が過ぎたログが即座に削除されるわけではありません。
削除が実行されるタイミングは以下の通りです:
- mysqld の起動(または再起動)
FLUSH LOGS
またはFLUSH BINARY LOGS
の実行mysqladmin flush-logs
の実行PURGE BINARY LOGS
の明示的な実行
📚 MySQL公式ドキュメント – binlog_expire_logs_seconds
📚 MySQL公式ドキュメント – PURGE BINARY LOGS
したがって、ログローテーション設定が有効になっておらず、mysqld を長期間再起動しない場合、バイナリログは残り続けます(これについての改善された動作は後述します)。
ログローテーションの初期設定について
MySQL を RPM パッケージでインストールすると、/etc/logrotate.d/mysql
にログローテーション設定がプリセットされています。バージョンによって内容は多少異なるものの、以下のような内容が含まれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#/var/log/mysqld.log { # create 640 mysql mysql # notifempty # daily # rotate 5 # missingok # compress # postrotate # if test -x /usr/bin/mysqladmin && \ # /usr/bin/mysqladmin ping &>/dev/null # then # /usr/bin/mysqladmin flush-logs # fi # endscript #} |
この設定では、mysqladmin flush-logs
(= FLUSH LOGS
)によって以下のログファイルが再オープンされます:
- バイナリログ(binlog)
- エラーログ
- スロークエリログ
- 一般ログ
- ストレージエンジンログ(例:InnoDB REDO)
- リレーログ
この処理の結果、logrotate により新しいログファイルが生成されていれば、切り替わり、古いファイルが圧縮・保管されます。
上記設定では、/var/log/mysqld.logは古いファイルはリネームして保管され、新しい/var/log/mysqld.logが作成され、再オープンによって切り替わります。
スロークエリログ、一般ログは、設定に含まれていないため、再オープンはされますがローテーションはされません。
バイナリログ、ストレージエンジンログ、リレーログについては、再オープン時にMySQLによって必要に応じてローテーションされます。
mysqladminコマンドの認証と課題
/usr/bin/mysqladmin
を使って flush-logs
を実行するには、mysqld に対する認証情報が必要です。
プリセットの logrotate 設定ファイルでは、この認証情報が明示されていません。
このような場合、MySQLはOSユーザと同じ名前のユーザで接続するため、 root
ユーザが通常使用されます。
root
ユーザにパスワードがかかっていなければ、ローテートは成功しますが、本番環境では推奨されません。
対応方法は以下の通りです:
mysqladmin -u <user> -p<password>
のように認証情報をコマンドに付与mysql_config_editor
を使い、ログインパスに資格情報を保存(推奨)/etc/my.cnf
や~/.my.cnf
に[mysqladmin]
セクションを追加
1 2 3 |
[mysqladmin] user = logrotate password = MySecurePass!!! |
ただし、平文でパスワードを保存する点、設定の手間がかかる点など、実運用ではやや扱いにくさが残ります。
OSシグナルによるローテーション(SIGUSR1)
MySQL 8.0.19 以降では、UNIX シグナルを用いてログをローテートすることが可能になりました。特に SIGUSR1
によって、次のログが再オープンされます:
- エラーログ(error log)
- スロークエリログ(slow log)
- 一般ログ(general log)
1 |
kill -SIGUSR1 $(cat /var/lib/mysql/mysql.pid) |
この方法では、MySQLに対する認証情報の保持が不要になり、セキュアかつシンプルにログローテーションを実行できます。
📚 MySQL公式 – UNIX Signal Response
logrotate 設定の変更案
上記の SIGUSR1
を活用すれば、認証情報なしで安全にログローテーションを行えます。logrotate の設定例は以下の通りです:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/var/log/mysqld.log { create 640 mysql mysql notifempty daily rotate 5 missingok compress postrotate if test -x /usr/bin/mysqladmin && \ /usr/bin/mysqladmin ping &>/dev/null then kill -SIGUSR1 $(cat /var/lib/mysql/mysql.pid) fi endscript } |
この方法で、エラーログやスロークエリログのローテーションは対応可能です。
ただし、バイナリログは対象外のため、このシグナルの実装初期(8.0.19~)は、log_binが有効な環境ではやはり mysqladmin flush-logs
を使うことが一般的でした。
MySQL 8.0.29 以降の改善点:binlog 自動削除
MySQL 8.0.29 からは、以下の設定がデフォルトで有効になっています:
1 |
binlog_expire_logs_auto_purge = ON |
📚 MySQL公式 – binlog_expire_logs_auto_purge
この設定により、バイナリログの有効期限(binlog_expire_logs_seconds
)を超えたログは、自動的に削除されるようになりました。
そのため、SIGUSR1
を使ったローテーションだけでも、バイナリログが蓄積し続けるリスクは無くなりました。
バージョンごとの比較
MySQLバージョン | SIGUSR1でのログローテート | バイナリログ自動削除 | 備考 |
---|---|---|---|
8.0.19〜8.0.28 | error / slow / general のみ | ×(手動対応) | FLUSH LOGS などが必要 |
8.0.29以降 | error / slow / general のみ | ◯(自動削除あり) | SIGUSR1 で十分な場合が多い |
まとめ
MySQL におけるログローテーションは、バージョンによって挙動が異なります。
特に 8.0.29 以降は、SIGUSR1
による安全なログローテーションと、バイナリログの自動削除機能により、運用負荷が軽減されています。
従来のように mysqladmin
による認証情報の管理や、手動での FLUSH LOGS
を組み込む必要は少なくなりつつあり、今後の構成では SIGUSR1
の活用がより一般的になっていくと思われます。
必要に応じて、ログ削除ポリシーや保持期間の設定も合わせて見直しておくと安心です。