Aurora MySQLでINDEX追加しようとしたら、ローカルストレージが枯渇して失敗した話
メディア統括本部 サービスリライアビリティグループ(SRG)の鬼海 雄太(@fat47)です。
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。
本記事は、Aurora MySQL Version2の環境でALTERのオンラインDDL(INPLACE)でINDEX追加を実行したところ、RDSインスタンスのローカルストレージが枯渇して失敗したという事象についてまとめている記事です。
オンラインDDLでINDEX追加しかしエラーでALTER実行失敗なぜ失敗するのか対応策インスタンスサイズを上げてローカルストレージの容量を大きくするALTER TABLE実行時のアルゴリズムをALGOITHM=COPYに指定RDS B/G Deployments機能を使ってGreenクラスタにだけALGOITHM=COPYでINDEX追加終わりに
オンラインDDLでINDEX追加
Aurora MySQL Version2で稼働している環境で、ある巨大なテーブルにINDEX追加を実行しました。
セカンダリインデックス追加はオンラインDDL(ALGORITHM=INPLACE)での実行が可能なため、書き込みをロックせずにALTERの実行ができます。
しかしエラーでALTER実行失敗
しかし、実行中しばらく待っていると完了せずに以下のエラーメッセージが表示されました。
RDSインスタンスのエラーログを確認してみると、下記のように出力されています。
容量が足りないというエラーが出ています。
なぜ失敗するのか
AuroraのDBデータを保存するためのクラスターボリュームは、自動的に128TiBまでサイズ拡張されていきます。
しかし、今回ディスク容量が不足しているのはクラスターボリュームではなく、RDSインスタンスが持つ「ローカルストレージ」という領域です。
これはRDSインスタンスサイズごとに容量が固定されているストレージ領域になります。
上記ドキュメントより表を一部引用します。
DB instance class | Maximum temporary/local storage available (GiB) |
db.r6g.8xlarge | 640 |
db.r6g.4xlarge | 320 |
db.r6g.2xlarge | 160 |
db.r6g.xlarge | 80 |
db.r6g.large | 32 |
今回実行した環境はdb.r6g.largeになるので、ローカルストレージサイズは32GiBとなります。
実行したときのCloudWatchのメトリクスから「FreeLocalStorage」を確認してみます。
すると、0にある程度近づいたタイミングでエラーになっていたことがわかりました。
※ALTERを2回実行したため、このメトリクスでは0に近づくタイミングが2回表示されています。
オンラインDDLのALGORITHM=INPLACEでのセカンダリインデックスの作成では、DDL実行中に操作されたDMLを記録するログファイルや、
ソートファイルなどの一時的なファイルが作成されます。この一時的なファイルがローカルストレージを使用しており、この容量足りなくなったためクエリーがエラーとなったようでした。
対応策
3つの対応方法が考えられます。
- インスタンスサイズを上げてローカルストレージの容量を大きくする
- ALTER TABLE実行時のアルゴリズムをALGOITHM=COPYに指定
- RDS B/G Deployments機能を使ってGreenクラスタにだけALGOITHM=COPYでINDEX追加
インスタンスサイズを上げてローカルストレージの容量を大きくする
今回はこちらの方法で対応しました。
db.r6g.largeから一つ上げて、db.r6g.xlargeに変更したことでローカルストレージの容量が80GiBとなりました。
その環境で再度同じALTERを実行したところ、ローカルストレージが枯渇することなく実行完了することができました。
ALTER TABLE実行時のアルゴリズムをALGOITHM=COPYに指定
ALGOITHM=COPYを実行するとローカルストレージの枯渇が回避できます。
しかし、実行完了までテーブルロックがかかるので、同時に更新のDMLを受け付けることができません。
システムをメンテナンスモードにいれるなどして、他の更新クエリが停止しても問題ない状況にする必要があるので今回は見送りました。
RDS B/G Deployments機能を使ってGreenクラスタにだけALGOITHM=COPYでINDEX追加
上記の方法を、RDS Blue/Green Deployments機能をつかって作成したGreenクラスタに実行してからB/Gを切り替える方法です。
この場合Greenクラスタにはサービスからのデータ参照がないので、実行完了までテーブルロックがかかっていても問題ありません。
ただ注意すべきこととして、B/G切り替えの際に1分程度のダウンタイムが生じます。
終わりに
Aurora MySQLの仕様による制限でオンラインDDLが失敗することがあります。
ローカルストレージの制約を熟知し、うまく付き合っていくことが必要です。
SRG では一緒に働く仲間を募集しています。
ご興味ありましたらぜひこちらからご連絡ください。