0. はじめに
MySQL5.6よりオンラインDDL機能が導入され、その恩恵を受けている方も多いと思います。機能自体はとても便利な反面、詳細な動作をきちんと認識していないと思わぬ落とし穴に嵌ってしまうこともあります。今回はそんなオンラインDDLでの失敗談をお届けします。
オンラインDDLとは (MySQL :: MySQL 5.6 リファレンスマニュアル :: MySQL 用語集より)
DDL (主に ALTER TABLE) 操作中の InnoDB テーブルのパフォーマンス、並列性、および可用性を改善する機能
1. 何をやったか
本番稼働中のDB(Aurora MySQL)に対してDROP INDEXを行いました。
直近のインデックス追加の影響で、意図しないクエリの実行計画が変わりスロークエリが発生していたためです。
(メンテナンス状態でないときのALTER TABLEは怖すぎるので普段はしないですが、その時はサービスへの影響が大きかったので仕方なく対応を行いました。)
自分の認識では、INDEX操作はオンラインDDLのカバー範囲で、操作対象のテーブルはロックされることなくインデックスが削除されると思っていました。
2. 何が起きたか
Waiting for Table metadata lockが大量に発生し数分間AuroraへのSELECTその他のクエリが待機状態になり、その後Auroraのフェイルオーバーが発生しました。
フェイルオーバーにより一旦すべての接続が切断され通常通りの動作に復旧しました。
(この間サービスは使えなくなっていたと思われます、焦ってるうちにフェイルオーバーしました笑)
3. 何が起きたか(詳細)
もう少し詳しく説明をします。
-
オンラインDDLの仕様
今回のメインです。
オンラインDDLの仕様として、オンラインDDLの開始前、完了前にそれぞれ短時間ではあるものの排他的アクセスが必要というものがあります。
これによって以下3つのことが発生します。①進行中のトランザクションが完了(コミットorロールバック)するまでDDLが開始されない
②DDL開始~完了の間に開始されたトランザクションがすべて完了するまでDDLは完了できない
③DDLが完了するまでDMLはメタデータロック待ち状態になる少し長めのトランザクションが実行され、且つDMLが大量に流れるような環境では②③が発生しやすくオンラインDDLには向いていないと言えそうです。
-
Auroraのフェイルオーバー
結果的にこれに助けられました。
Auroraクラスター内で、リーダーインスタンスがライターインスタンスに昇格します。
フェイルオーバー自体のスピードはかなり速く、一度接続は切れましたがその後すぐに使えるようになりました。
ちなみにこの時点でもともとのDROP INDEXは無事(?)に反映されていました。
4. 終わりに
何をするにせよ、浅い知識でそれっぽいことをするのは危険です笑
オンラインDDLはとても便利な反面、なかなか深い落とし穴があるなと感じました。
今回のケースでいえば、もしDBがAuroraでなく例えばオンプレミスだったら、おそらくmax_connectionに抵触してDB自体が使えなくなっていたと思われます。
(その前にサービスが使えないというクレーム電話がじゃんじゃん鳴ったかも)
サービスを運用する身として、日々知識のアップデートをしていかないといけないなと痛感した出来事でした。
5. 参考