お仕事の所でのお話。
発端
社内で運用が開始されて1年ほど経ったシステムを他の担当社員から引き継ぎました。
その際、DBサーバの容量が不穏なことに気づきました。1TBのSSDの7割ほどが使われている…。
とはいえ、容量が横ばいなら問題ではありません。
しかしそのシステムは1日に数GBずつ増えていっていたので、このままでは持って3-4ヶ月です。
さて困った。
環境
- OS:CentOS7
- DB:MySQL
- SSD:約1TB(使用約700GB、日々2−4GB増加中)
これがMASTER-SLAVEの2台構成になっていて、SSDの使用率はどちらもほぼ同じです。
事象確認
何はともあれ、幾つかアタリをつけて調べ始めます。
MySQLのデータが増加している
まずはMySQLのデータそのものの量の増加を疑いました。
これがあまりに増えていたらSSDの増設を急いで行う必要があります。
この確認は以下のSQLを実行しました。
SELECT table_schema, sum(data_length) /1024/1024/1024 AS GB
FROM information_schema.tables
GROUP BY table_schema
ORDER BY sum(data_length+index_length) DESC;
しかし全スキーマを合わせても容量は20GBに満たないくらい。
自動で取られるDB dumpも大体それくらいの容量なので、全く余裕があることが分かりました。
ログファイルが圧迫している
ここで言うログは、大きくOSのログかMySQLのログかによります。
OSのログであることはほぼ考えていませんでした。
同じOSを積んだ他のサーバは容量が小さく、何らかの異常が発生していても冗長構成の両方というのも変。
ということでMySQLのログを疑いました。
スロークエリログが爆発しているのだとしたら閾値やログ保存日数の見直し。
バイナリログだとしたらローテートの日数を短く取らないとダメか?
スロークエリの確認
SHOW GLOBAL VARIABLES like 'slow_query_log';
slow_query_logはOFF。
スロークエリを全く取っていないのも疑問ですが、容量圧迫問題についてスロークエリの疑いは晴れました。
バイナリログの確認
SHOW GLOBAL VARIABLES like 'expire_logs_days';
なんとexpire_logs_days=0、つまりログがローテートされていない?
バイナリログが保存されている場所が/mnt/disks/mysql/data/
とのことなので、以下で確認。
$ ll /mnt/disks/mysql/data/
すると出るわ出るわ、1年前からのバイナリログがゴロゴロ…。
1ファイルが1GBちょっとで、その数600超。
対応
上までの調査でバイナリログが今回の犯人であることは分かりました。
しかしバイナリログを一気に全部削除してしまうと、マスターとスレーブでレプリケーションが取れない可能性があります。
念のため、以下のSQLで同期に大きな遅れがないかを確認。
マスター・スレーブともにほぼ同時に実行して、ログファイルとポジションに差が大きくないかを確認。
SHOW MASTER STATUS;
確認した所、遅れも1分以内なので問題なし。
まずはサーバに負荷をかけないため、以下のSQLを実行して徐々にログファイルを消しました。
PURGE MASTER LOGS TO 'mysql-bin.XXXXXX';
SSDだし、一気に消しても負荷はそんなに大きいとは思わないのですが、念の為。
ある程度消し終わったら以下のSQLを実行し、ローテーションを設定。
7日間以上経ったログを削除するよう設定、日数が変わったことを確認します。
※正確には、ログローテート時に7日以上前のログを削除。実行後すぐ削除される訳ではない。
SET GLOBAL expire_logs_days = 7;
SHOW GLOBAL VARIABLES like 'expire_logs_days';
最後にログが切り替わった段階で設定日数より前のログが削除されていることを確認し、作業終了です。