サービス稼働中のMySQLのカラム変更で気をつけること
はじめに
こんにちは。webエンジニアの ningenMe です。
サービス稼働中にMySQLのカラムを変更したい、そんな場面に遭遇したとき。
そういうときのtipsを知ってる範囲で並べていきます......と思っていたらちょうど良い記事が既に出ていました。なので、ここで上げてないポイントを書いていきます。
直でalterを打つ。
趣味の開発など、dbが止まる時間があって良いならこれが一番楽です。
ただロックがかかる、一時的に対象のテーブル容量が2倍になるなどの弱点があるので注意が必要です。
リアルタイムでapiとかから叩かれるdbならこの選択肢は殆ど無理そうです。
pt-online-schema-change を使う
上記の記事でも上げられていましたが、便利なツールです。
リアルタイムで更新のあるテーブルや、レコード数がそこそこ多いテーブル(1億件ぐらい)でも、数時間かかるものの手間いらずでカラム変更が出来ます。
中規模のデータ量ならこれで大体十分だと思います。
after句やfirst句が使えるのもいいところです。
容量に関しては普通にalter打つときと同じで、2倍持てるかを気をつける必要があります。
途中で容量足りなくなって止まると、triggerを自分で外す作業などが出てきて余計な本番作業が発生するので気をつけましょう。
メンテナンスに入れる
サービス止める対応が許されるなら、メンテナンスと称してサービスを止めてしまってalter打つというのがかなり楽に感じます。もちろんアプリケーションにもよります。
ここで「メンテナンスに入れる」は対象のテーブルを参照や更新のない状態にしてしまうという意味です。
容量が気にならない場合はalter打つだけでいいのですが、容量が逼迫しているときでも下記の方法で変更できます。
- alterを打つ前に更新したいテーブルをdump。
- その後更新したいテーブルをtruncate。
- alterを打つ。
- dumpしたデータをrestore。
シンプルですね。
ただdump取るとはいえtruncate打つのが心理的ハードルが少し高いのが難点です。
複数カラムの変更がある場合、1個のクエリで処理する。
カラムが変更された後、MySQL側のキャッシュが一時的に無くなるためクエリの負荷が普段より大きくなります。
そのため修正必要なカラムが複数ある場合はできるだけクエリをまとめる方が良いです。
複数テーブルを更新する際は1テーブル処理した後負荷が上がっていないか少し待つのがベター。
この「キャッシュ乗るまでパフォーマンスが悪い」は他の場面でも効いてくるときがあって、例えばMySQLのクラスタ構成でサーバを増やしたときなどにもサービスインしたばかりのdbはこのようになることがあります。
気づいてない罠とかは結構あるので、何の操作をするにもgrafanaなどでメトリクス見ておきましょうという感じがありますね。
高負荷な時間を避けて作業をする
全然tipsでもないし当たり前やんけ、とはなるんですが結構危機感の度合いが個人差あるなと思うので改めてと。
私事ですがdbのbusyが100%になってapiから軒並みconnectionできなくなってサービス死ぬみたいなのを経験してから、かなり怖さが生まれました。
まあそもそもこれぐらいの作業で落ちるようなbusyが常態化していることがかなり問題ですが......。
完全に本番の負荷を想定するのは難しいですが、最低限、本番と同様のレコード数のテーブルを別のテスト用のqa環境などに作って試し打ちするのは必須なように思います。
さいごに
かなりふわっとした記事になってしまいました。すみません。先行記事がしっかりしていると思うので是非そっちを読んでください。
alter時にテーブル容量2倍いることだけでも伝わればなと思います。
MySQLじゃなくてcassandraでカラム追加だとめっちゃ楽なので(比較するものでもないですが)、データの拡張性やリカバリのコストも初期設計でちゃんと見積もれるといいなってひしひしと感じます。
みなさんも楽しくてドキドキな本番db作業を是非。
ではでは。