Y-Ken Studio

新しもの好きのデータエンジニアが四方山話をお届けします。

MySQLサーバのディスク容量減少アラートが飛んできた!ってときにどう対処するか

MySQLサーバで希に遭遇するディスク残量障害事例と共に紹介します。

こちらは、以下エントリよりネタをパクりましたインスパイアしました。すみません。

今回紹介する対処パターン

今回は4つの方法を紹介します。

  1. 不要なデータベース/テーブルを削除
  2. スロークエリログ/クエリログを削除
  3. バイナリログを削除
  4. どれのパターンにも属さないレアなシチュエーション

不要なデータベース/テーブルを削除

あまりそういうケースは無いとは思いますが、
DROP DATABASE foo;DROP TABLE foo;で削除します。

スロークエリログ/クエリログを削除

du -sch /*コマンドでも分かりますが、MySQLと分かっているのならば次のように、ログの出力先を確認しても良いと思います。

> show variables like '%log_file';
+---------------------+-----------------------------+
| Variable_name       | Value                       |
+---------------------+-----------------------------+
| general_log_file    | /var/log/mysqld-general.log |
| slow_query_log_file | /var/log/mysqld-slow.log    |
+---------------------+-----------------------------+

次に、対象のファイルの容量を確認してみましょう。

$ ls -alh /var/log/mysqld-*
-rw-r--r-- 1 mysql root  53M  Jul 19 20:01 2013 /var/log/mysqld-general.log
-rw-r--r-- 1 mysql root  20G  Jul 30 11:43 2013 /var/log/mysqld-slow.log

1つめがクエリログ、2つめがスロークエリログです。
容量が20GBと大変大きいので、スロークエリログを空にしてみましょう。 rootユーザであれば:> /path/to/fileが使えるのですが、sudoを使う場合は次のように実行します。

# スロークエリログを空にする
$ sudo sh -c ":> /var/log/mysqld-slow.log"

追記:空にするという荒技を使わずにログファイルの手動ローテートを行う方法についてはMySQLスローログの手動ローテート | b.l0g.jpのページが参考になります。

以上で空き容量を確保することが出来ました。
この対処療法で安心せず、自動ログローテートの設定を行っておくと良いですね!

バイナリログを削除

もし明らかに不要であると断定できるならば、大まかにこの流れで対応します。

  • PURGE MASTER LOGS BEFORE '2013-07-30 15:00:00';的な感じで応急処置
  • バイナリログの保存期間や、そもそも記録するかを含めて根本対策を検討

詳細は、以下記事が参考になります。

どれのパターンにも属さないレアなシチュエーション

  • df -hを見る限り、何かが容量を逼迫している
  • du -sch /*で見ると/var/lib/mysql/は確かに多いが、かといって影響の出るレベルでは無い
  • lsofで見ると、mysqldがテンポラリテーブルのファイルを掴んでいる

以上から、テンポラリテーブルのファイルが原因と分かります。

lsof結果サンプル

以下のように(deleted)というファイルが大量にあるならば、それが怪しいです。

$ sudo lsof | grep mysql | grep deleted
mysqld    13618     mysql    6u      REG              253,0            0   16384003 /tmp/***** (deleted)
mysqld    13618     mysql    7u      REG              253,0         1030   16384004 /tmp/***** (deleted)
mysqld    13618     mysql    8u      REG              253,0          135   16384006 /tmp/***** (deleted)
mysqld    13618     mysql    9u      REG              253,0            0   16384007 /tmp/***** (deleted)
mysqld    13618     mysql   35u      REG              253,0         1378   16384008 /tmp/***** (deleted)

以下略

対処法

日中にダウンしても良いDBで希に遭遇している現象という事もあり、とりあえずmysqld再起動で解決しています。
ただこれの正しい対処法、誰かご存じでしたら教えて下さい。 もしかしたら、FLUSH TABLES もしくは mysqladmin flush-tablesで解決出来るのかもしれませんが、まだ試していません。