RDS(MySQL)のストレージ領域の肥大化


概要

RDS(MySQL)を運用していて、ストレージ領域が肥大化することがあったのでその対応を共有します。

環境

エンジン:MySQL
エンジンバージョン:5.7.19

結論

まずは、結論から。
MySQLを再起動するとストレージ領域が解放されます。

事象

MySQL(リードレプリカ)のストレージが150GBあり、
DBサイズが60GBだったにも関わらず、ストレージの残容量が1GB近くになっていました。

原因

MySQLのテンポラリーテーブルが肥大化していました。

MySQLには、クエリ実行時にメモリ上に収まりきらなかったデータ(tmp_table_size以上)をInnoDBテーブルとしてテンポラリテーブル(ibtmp1) に書き出します。tmp_table_size以下であればMEMORYテーブルとしてメモリ上に作成されるようです。

このテンポラリーテーブルは、MySQL 5.7.6以からストレージエンジンがInnoDBになったようなんですが、厄介なのは、このテーブルはMySQLを再起動しないと確保したストレージ領域を解放しないのです。

ちなみにMySQL 5.7.5以前は、テンポラリーテーブルのストレージエンジンはMyISAMだったようで、テンポラリーテーブルがディスクを使い切り、クエリがabortされるとストレージ容量は元に戻る仕様?だったようです。
参考:https://yoku0825.blogspot.com/2015/04/mysql-576.html

テンポラリテーブルについてはこちらの解説が分かりやすかったです。

対応

こちらを拝見すると、テンポラリーテーブルのサイズを制限することは可能なんですが、RDS(MySQL)だとパラメータ変更はできませんでした。

つまり、現状だとDBの再起動するしかなさそうです。
こちらにもさらっと記載があります。

MySQL 5.7 以降では、一時テーブル (ibtmp1) が過剰なストレージ領域を使用すると、領域を解放するために、DB インスタンスを再起動します。

別の手段として(お金がかかってしまいますが)、RDS(MySQL)のストレージの自動拡張機能がサポートされたみたいなのでそちらを設定しても良いですね。
https://dev.classmethod.jp/cloud/aws/rds-storage-auto-scaling/

まとめ

ibtmp1のサイズはどこかで見れないんですかね?
RDS(MySQL)のストレージ容量はちゃんと監視しましょう。