Lapis Lazuli

technical blog for web developer

【DB】DB負荷はフラグメンテーションを疑え

最近インフラDevOpsしかやってないので今回もそっち方面のネタで・・・

DBが高負荷になってサービスのパフォーマンスが著しく落ちるというのは、Webサービスを運用しているとよくある事だと思います。

Webサーバーがボトルネックになることもあるのですが、大概DBなんですよね。
AWSだったらRDBがスケールしないので、スケールしたサーバー側のアクセスに耐えられなくなるわけです。

こうなったときはメトリクスやプロセスなどをみて、重いクエリが無いかどうか、根本的原因をまず探りにいくのがスタンダードなやり方だと思います。
サブクエリとか重いですし、巨大なテーブルを参照してたりとかですね。

しかし今週経験した障害は違ってました。
フラグメンテーションを起こしていたのです。
MySQLデフォルトのストレージエンジンであるInnoDBフラグメンテーションが起きます。これはディスク上の空きが虫食いのように穴だらけで存在している状態のことです。
これが進むとI/Oパフォーマンスが著しく劣化します。
障害が起きたときも、徐々に負荷が増すのではなく一気に上がってサービスが止まっていたのは、まさに上記の劣化からです。

確認方法

対処は最適化をしたらいいのですが、まずinfomation_schemaのdata_freeを見てどれだか未使用領域があるかを確認します。

SELECT table_schema, table_name, data_free, table_rows FROM infomation_schema.tables WHERE table_name = {対象テーブル};

結果がtable_rowsの割にdata_freeがやたら桁が多かったら断片化が起こっている可能性大です。

対処方法

ALTER TABLE テーブル名 ENGINE INNODB;

この1文で最適化完了です。再度確認するとdata_freeが0になっているかと。

結論

やっぱりDB原因で障害起きた時、データベースのアーキテクチャに関する知見がないと対処が難しいなと思いました。
こういうエンジンに起因する箇所ってRDBがマネージドでよしなにやってくれてるイメージでしたが、そう簡単にはいかないようです。
ちなみに頻繁にDELETEを繰り返すと起きるので、インデックス貼ってある、あまり動きのないテーブルは起きにくいです。