MySQLのバイナリログを管理する手順|binlog_expire_logs_secondsでの自動削除とPURGE BINARY LOGSの使い方

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > MySQLのバイナリログを管理する手順|binlog_expire_logs_secondsでの自動削除とPURGE BINARY LOGSの使い方
「MySQLを運用していたら /var/lib/mysql 配下がいつの間にかディスクをほぼ埋め尽くしている」「binlog.000xxx というファイルが大量に溜まって容量が足りなくなった」

そんな経験を持つLinuxサーバー管理者は少なくありません。バイナリログはMySQLのデータ変更履歴を記録する重要なファイルですが、適切に管理しないと数GB、場合によっては数十GBに膨れ上がり、最終的にはMySQLが書き込みを停止してしまいます。

この記事では、MySQLのバイナリログの仕組みから自動削除の設定(binlog_expire_logs_seconds)と手動削除(PURGE BINARY LOGS)の実践的な手順を、RHEL 9.4 / MySQL 8.0.36環境で動作確認しながら解説します。

この記事のポイント

・binlog_expire_logs_secondsで古いバイナリログを自動削除できる
・PURGE BINARY LOGSで今すぐ手動削除する方法も解説
・レプリケーション中は削除前にSHOW REPLICA STATUSで確認が必須
・SHOW BINARY LOGSでサイズと本数を把握してから操作する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

MySQLのバイナリログとは

MySQLのバイナリログ(binary log)は、データベースに対する変更操作(INSERT・UPDATE・DELETE・DDLなど)をバイナリ形式で記録したファイルです。主に以下の2つの用途で使われます。

レプリケーション:ソースサーバーのバイナリログをレプリカが読み取り、同じ変更を再実行することでデータを同期します。
ポイントインタイムリカバリ(PITR):定期バックアップ(mysqldump等)を復元した後、バイナリログを再生することで障害直前の状態までデータを戻せます。

バイナリログは有効にしておくと確かに便利ですが、データ更新が多い本番環境では1日に数百MB~数GBのバイナリログが生成されます。定期的に削除しなければデータディレクトリがあっという間に満杯になります。

バイナリログの有効状態と一覧を確認する

1. バイナリログが有効かどうかを確認する

まずMySQLに接続してバイナリログの有効状態を確認します。

mysql -u root -p mysql> SHOW VARIABLES LIKE 'log_bin';

RHEL 9.4 / MySQL 8.0.36での実行結果です。

+---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | ON | +---------------+-------+ 1 row in set (0.00 sec)

ValueON であればバイナリログは有効です。OFF の場合は /etc/my.cnf[mysqld] セクションに log_bin = /var/lib/mysql/binlog を追加してMySQLを再起動してください。

スタンドアロン構成でレプリケーションもPITRも不要であれば、skip_log_bin(MySQL 8.0以降)を指定して無効化するのも選択肢の1つです。無効化するとファイルが生成されないため、ディスク管理の手間が不要になります。

2. バイナリログの一覧とサイズを確認する

現在存在するバイナリログの一覧とファイルサイズを確認します。

mysql> SHOW BINARY LOGS;

+---------------+-----------+-----------+ | Log_name | File_size | Encrypted | +---------------+-----------+-----------+ | binlog.000021 | 1073 | No | | binlog.000022 | 1048576 | No | | binlog.000023 | 1048576 | No | | binlog.000024 | 524288 | No | | binlog.000025 | 156 | No | +---------------+-----------+-----------+ 5 rows in set (0.00 sec)

File_size の単位はバイトです。OSコマンドでデータディレクトリ全体の使用量を確認することもできます。

# バイナリログファイルの合計サイズを確認する du -sh /var/lib/mysql/binlog.* # データディレクトリ全体の使用量を確認する df -h /var/lib/mysql

現在書き込み中のファイル(位置情報)は次のコマンドで確認します。このファイルは削除できません。

mysql> SHOW MASTER STATUS\G

*************************** 1. row *************************** File: binlog.000025 Position: 156 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: 1 row in set, 1 warning (0.00 sec)

File 列が現在書き込み中のファイルです。PURGE BINARY LOGS はこのファイルより前のファイルのみ対象になるため、実行中のファイルを誤って消す心配はありません。

バイナリログの自動削除を設定する

1. MySQL 8.0以降:binlog_expire_logs_secondsで保持期間を設定する

MySQL 8.0以降では、binlog_expire_logs_seconds(秒単位)でバイナリログの保持期間を設定します。デフォルトは2592000秒(30日)です。

mysql> SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

+----------------------------+---------+ | Variable_name | Value | +----------------------------+---------+ | binlog_expire_logs_seconds | 2592000 | +----------------------------+---------+ 1 row in set (0.01 sec)

保持期間を7日(604800秒)に変更する場合は、/etc/my.cnf[mysqld] セクションに以下を追加します。

[mysqld] binlog_expire_logs_seconds = 604800

設定ファイルを変更後にMySQLを再起動すれば恒久的に反映されます。

systemctl restart mysqld

再起動せずに即時反映したい場合は SET GLOBAL を使います。ただし、MySQLを再起動すると設定ファイルの値に戻るため、my.cnf への記載も必ず合わせて行ってください。

mysql> SET GLOBAL binlog_expire_logs_seconds = 604800; Query OK, 0 rows affected (0.00 sec)

2. MySQL 5.7以前:expire_logs_daysの設定

MySQL 5.7以前では binlog_expire_logs_seconds は存在せず、代わりに expire_logs_days(日単位)を使います。MySQL 8.0では非推奨ですが後方互換として動作します(両方を設定した場合は binlog_expire_logs_seconds が優先されます)。

# MySQL 5.7以前の設定例(/etc/my.cnf) [mysqld] expire_logs_days = 7

3. 自動削除のタイミングについて

自動削除は以下のタイミングでトリガーされます。

MySQLの起動時:サービス起動時に保持期間を超えたファイルを自動的に削除します。
バイナリログのローテーション時:現在のファイルが max_binlog_size(デフォルト1GB)を超えて新しいファイルに切り替わる際に削除します。

更新量が少ないサーバーではローテーションが発生しないため、自動削除もかかりにくくなります。その場合は次節の手動削除を使います。

バイナリログを手動で削除する(PURGE BINARY LOGS)

1. 削除前にレプリケーション状態を確認する

レプリケーションを組んでいる場合、レプリカがまだ参照中のバイナリログを削除するとレプリカが壊れます。必ず削除前に確認してください。

# ソースサーバーでレプリカの読み取り位置を確認する(MySQL 8.0以降) mysql> SHOW REPLICA STATUS\G # MySQL 5.7以前の構文 mysql> SHOW SLAVE STATUS\G

出力の Relay_Master_Log_FileExec_Master_Log_Pos でレプリカが現在どのバイナリログのどの位置まで実行済みかを確認できます。この位置より前のファイルのみ削除してください。

スタンドアロン構成(レプリケーションなし)の場合はこの確認は不要です。

2. 日付を指定して削除する

指定した日付より前のバイナリログをまとめて削除するには PURGE BINARY LOGS BEFORE を使います。

# 7日前より前のバイナリログを削除する mysql> PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY); Query OK, 0 rows affected (0.03 sec)

削除後に SHOW BINARY LOGS で一覧を確認してみます。

mysql> SHOW BINARY LOGS; +---------------+-----------+-----------+ | Log_name | File_size | Encrypted | +---------------+-----------+-----------+ | binlog.000024 | 524288 | No | | binlog.000025 | 156 | No | +---------------+-----------+-----------+ 2 rows in set (0.00 sec)

古いファイルが削除されました。

3. ファイル名を指定して削除する

指定したファイル名より前のバイナリログを削除するには PURGE BINARY LOGS TO を使います。

# binlog.000024 より前のファイルをすべて削除する mysql> PURGE BINARY LOGS TO 'binlog.000024'; Query OK, 0 rows affected (0.01 sec)

binlog.000024 自身は残り、それより前の番号のファイルが削除されます。

【注意】 現在書き込み中のファイル(SHOW MASTER STATUSFile 列)は削除できません。削除しようとしても自動的にスキップされます。

バイナリログがディスクを圧迫するのを防ぐ運用設計

運用上の観点から、以下のポイントを押さえておきましょう。

保持期間は7日が現実的:本番DB環境では mysqldump によるフルバックアップを毎日取得し、PITRが必要な場合はその日のバイナリログを参照します。7日分あれば十分なケースがほとんどです。デフォルトの30日保持は多くの環境で過剰です。
max_binlog_sizeを意識する:デフォルトの1GBのままでも問題ありませんが、1ファイルあたりのサイズが大きすぎるとローテーションが発生せず自動削除もかかりにくくなります。更新量に合わせて256MBなどに調整するケースもあります。
cronでのrm直接削除は厳禁:MySQLが管理するバイナリログをOSコマンドで直接 rm すると、インデックスファイル(binlog.index)との不整合が発生してMySQLが起動できなくなることがあります。削除には必ず PURGE BINARY LOGS を使ってください。
データディレクトリを監視する:df -h /var/lib/mysql を定期的に確認するか、ZabbixやNagiosなどの監視ツールで使用率が80%を超えたらアラートを出す設定を入れておきましょう。

トラブルシュート

「Out of space」でMySQLが停止した場合の緊急対処

ディスクが100%になるとMySQLは書き込みを停止し、「ERROR 28 (HY000): Out of space error writing '...'」が発生するようになります。

緊急対処の手順は以下のとおりです。

ステップ1:MySQLが起動していれば PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 1 DAY) を実行して古いバイナリログを即時削除します。
ステップ2:MySQLが起動しない場合は、一時的に他のファイル(古いログ等)を別の場所に退避してディスク空きを作り、MySQLを起動してからPURGEを実行します。
ステップ3:対処後は binlog_expire_logs_seconds の設定を見直し、再発を防ぐ設定に変更してください。

binlog_expire_logs_secondsを設定しても削除されない場合

更新量が少なくバイナリログのローテーションが発生しないと、自動削除もなかなか実行されません。

この場合は FLUSH BINARY LOGS でローテーションを強制してから、PURGE BINARY LOGS を実行することで削除できます。

# 現在のバイナリログを強制的にローテーションする mysql> FLUSH BINARY LOGS; Query OK, 0 rows affected (0.01 sec) # その後、期限切れファイルを削除する mysql> PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY); Query OK, 0 rows affected (0.00 sec)

「ERROR: Could not find log file」が出る場合

binlog.index に記録されているファイル名とディスク上の実ファイルが食い違っている状態です。PURGE BINARY LOGS を使わずに rm で直接削除したときに起こります。

修正するにはインデックスファイルを直接編集して存在しないファイル名の行を削除するか、MySQLを停止して --skip-log-bin オプション付きで一時起動し、インデックスを再構築します。このトラブルを避けるためにも、バイナリログの削除は必ず PURGE BINARY LOGS コマンドで行うことを徹底してください。

まとめ

MySQLのバイナリログ管理で押さえておくべき操作をまとめます。
やりたいこと コマンド・設定
バイナリログの有効確認 SHOW VARIABLES LIKE 'log_bin'
バイナリログの一覧とサイズ確認 SHOW BINARY LOGS
現在書き込み中のファイル確認 SHOW MASTER STATUS
自動削除の保持期間設定(秒) binlog_expire_logs_seconds = 604800(/etc/my.cnf)
日付を指定して手動削除 PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY)
ファイル名を指定して手動削除 PURGE BINARY LOGS TO 'binlog.000024'
バイナリログを強制ローテーション FLUSH BINARY LOGS
バイナリログはMySQLの重要な機能ですが、適切な保持期間を設定しておかないとディスクを静かに食い尽くします。今すぐ SHOW VARIABLES LIKE 'binlog_expire_logs_seconds' で現在の設定を確認して、本番環境に合った値に調整してみてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアがMySQLのバイナリログ管理を含むサーバー運用の実践スキルを教えます。
Linux Master Pro Seminar の詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。