本番サーバーのMySQL容量が突然90%を超えた原因と対策を解説。バイナリログ・一時テーブル・スロークエリログの肥大化を特定し、自動削減設定で再発防止する実践ガイド。
こんな経験、ありませんか?
「アラートメールが来て確認したら、本番サーバーのディスク使用量が92%を超えていた」「MySQLが突然重くなり、アプリがタイムアウトを出し始めた」「原因を調べようとしたがどこから手をつければいいかわからない」
これは決して珍しいケースではありません。弊社が運用支援を行うクライアントの現場でも、年に数回は同様の緊急連絡が入ります。特に問題なのは、ディスク不足は静かに進行し、限界に達した瞬間にサービスが停止するという点です。容量が100%に達するとMySQLは書き込みを拒否し、Laravelアプリであれば SQLSTATE[HY000]: General error: 28 No space left on device というエラーを出して完全に機能停止します。
この記事では、MySQL容量肥大化の主な原因と、具体的な調査コマンド、そして再発を防ぐ自動削減設定まで、現場で実際に使っている手順をまとめて解説します。
あわせて読みたい
なぜMySQLのディスクは突然膨らむのか
主な肥大化の原因3つ
MySQLのディスク使用量が急増する原因は、大きく分けて以下の3つです。それぞれの特徴を理解しておくことが、原因特定の近道になります。
① バイナリログ(binlog)の蓄積 MySQL のレプリケーションやポイントインタイムリカバリのために記録されるバイナリログは、設定次第で無制限に積み上がります。デフォルト設定のままでは自動削除されないケースが多く、数GBのログが何十個も残っていることも珍しくありません。
② 一時テーブル(tmpdir)の肥大化 ORDER BY や GROUP BY を伴う複雑なクエリは、処理途中でディスク上に一時テーブルを作成します。大量データを扱うバッチ処理やレポート集計を実行した後に残骸が残ることがあります。
③ 各種ログファイルの増大
スロークエリログ、エラーログ、一般ログ(general log)は有効化したまま放置すると際限なく大きくなります。特に general_log を本番環境でONにしてデバッグしたまま戻し忘れるのは典型的な失敗パターンです。
まず現状を把握する:容量調査の手順
突然のアラートを受けたとき、最初にやるべきことは「どこが膨らんでいるか」の特定です。以下のコマンドを順番に実行していきます。
ステップ1:MySQLのデータディレクトリを確認
# MySQLのデータディレクトリを確認
mysql -u root -p -e "SHOW VARIABLES LIKE 'datadir';"
# 対象ディレクトリのサイズをフォルダ単位で確認
du -sh /var/lib/mysql/* | sort -rh | head -20
ステップ2:バイナリログの蓄積を確認
-- バイナリログ一覧と容量を確認
SHOW BINARY LOGS;
-- 例:出力イメージ
-- +------------------+-----------+
-- | Log_name | File_size |
-- +------------------+-----------+
-- | binlog.000123 | 1073741824| ← 1GBのファイルが大量に...
-- | binlog.000124 | 1073741824|
-- +------------------+-----------+
ステップ3:各種ログの有効状態を確認
-- スロークエリログと一般ログの状態を確認
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'general_log%';
SHOW VARIABLES LIKE 'log_error';
ここで general_log が ON になっていれば、即座にOFFにしてください。本番環境での常時有効化はアンチパターンです。
具体的な解決手順
バイナリログの即時クリーンアップ
あるECサイト(LaravelベースのカスタムCMS)を運用するクライアントでは、binlogが蓄積して18GBに達していました。レプリケーションを使っていない環境だったため、以下の手順で即座に解消できました。
-- 現在の安全なバイナリログ位置を確認してから削除
-- ※レプリケーション使用中の場合はスレーブの状態を先に確認すること
-- 特定日時より前のbinlogを削除
PURGE BINARY LOGS BEFORE '2025-06-01 00:00:00';
-- または特定ファイル名より前を削除
PURGE BINARY LOGS TO 'binlog.000150';
これだけで18GBが解放され、ディスク使用率が92%から58%まで低下しました。
my.cnfで自動削減を設定する(再発防止)
応急処置だけでは意味がありません。/etc/mysql/my.cnf(または /etc/my.cnf)に以下の設定を追加して再発を防ぎます。
[mysqld]
# バイナリログの自動削除(7日後)
binlog_expire_logs_seconds = 604800
# バイナリログの最大サイズ
max_binlog_size = 100M
# スロークエリログの設定
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
# 一般ログは本番ではOFF
general_log = OFF
# 一時テーブルのサイズ上限(デフォルト16MBから引き上げ)
tmp_table_size = 64M
max_heap_table_size = 64M
設定後はMySQLを再起動して反映させます。
sudo systemctl restart mysql
# 設定が反映されているか確認
mysql -u root -p -e "SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';"
スロークエリログのローテーション設定
スロークエリログは有効化しておくとクエリ改善に役立ちますが、放置すると数GBになります。logrotateで定期的にローテーションする設定を入れておきましょう。
# /etc/logrotate.d/mysql-slow を作成
sudo nano /etc/logrotate.d/mysql-slow
/var/log/mysql/slow.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
if test -x /usr/bin/mysqladmin && \
/usr/bin/mysqladmin ping &>/dev/null
then
/usr/bin/mysqladmin flush-logs
fi
endscript
}
よくある失敗パターンと対処法
現場で繰り返し見てきた失敗をまとめます。同じ轍を踏まないための参考にしてください。
対策前後の改善効果
前述のECサイトクライアントの事例を元に、実施した施策ごとの容量削減効果をまとめます。
合計で約25.8GBが解放され、ディスク使用率は92%から約45%まで低下。その後は自動削減設定が機能しているため、半年以上アラートは発生していません。
サーバー管理、丸ごとお任せください
サーバー保守・運用
監視・障害対応・パフォーマンス改善まで、安定稼働をサポートします
※ 通常1営業日以内にご返信します
まとめと次のステップ
MySQL容量の肥大化は「突然起きる」ように見えて、実際は静かに積み上がってきた結果です。定期的な監視と適切な自動削減設定を入れておくだけで、本番サービスの停止リスクを大幅に減らすことができます。
弊社では運用支援の中でサーバー監視・定期メンテナンスも承っています。「設定をやってみたが不安」「そもそも自分でやるより任せたい」という場合は、お気軽にご相談ください。