はじめに
はじめまして!今回がQiitaへの初投稿になります。
現在、GCP(Google Cloud Platform)上で医療系のシステムを運用しています。
医療現場で使われるシステムということもあり、高い可用性が求められる環境ですが、Cloud SQLのメンテナンス・リリース時に肝を冷やす事態に何度か遭遇しています。
その時の失敗談と、試行錯誤の末に辿り着いた運用回避策についてお話しさせてください。
1. 発生したトラブル:カラム変更後に訪れる「死」
Cloud SQLのカラム変更や大規模なデータ更新(UPDATE)の際、以下のような事象に遭遇しました。
① 翌日のユーザー利用時間帯にCPU 100%
リリース時にカラム変更を実施。その場では正常に終了したように見えても、翌日のユーザー利用ピーク時に突然CPU使用率が100%に達し、レスポンスが極端に低下することが数回ありました(酷くなると100%に張りついて、全く使えなくなる)。
- 対処: この場合は、インスタンスの再起動で一旦は収束しました。

こうなった時は、放置しておくと100%で固定されるので、次のリリースまで、ひたすら再起動をして、お茶を濁している(うーん)。
② DBの破損とPITR(ポイントインタイムリカバリ)の失敗
さらに深刻だったのが、大規模なUPDATEを伴うリリース時です。DBが不安定になり、ついには接続不能に陥りました。再起動を試みるも復旧しません。
- 試したこと: GCPの標準機能であるPITR(ポイントインタイムリカバリ)で特定の時点への復旧を試行。
- 結果: データが壊れた状態で立ち上がるという事態に、どの時点でバックアップしても無駄であったため、インスタンスが壊れているという結論に。
- 最終的な解決策: 幸い、事前にエクスポートしておいたダンプファイルがあったため(めちゃくちゃ優秀かつ慎重な人が作業したから、僕だったらやってない笑)、Cloud SQLを新規で建て直し、リストアすることでなんとか復旧させました。
2. なぜ壊れたのか?(原因の考察)
調査の結果、Cloud SQLの割り当てストレージ容量が関係している可能性がある?のかなぁぐらいのことが分かりました。
大規模なDDL(カラム変更など)や大量のUPDATEを実行すると、内部的には「変更前のデータ」と「変更後のデータ」を一時的に両方保持したり、ログが急激に肥大化したりするみたいです(このあたり曖昧、とにかくストレージを一時的に使うみたいです)。
学び:
デフォルト設定のとき「ストレージ容量が無駄に大きいな、そんなに要らない」と感じていたのですが、こうした作業領域としてのバッファが必要だからかもしれません。
3. 対処法の変遷:より速く、より安全に
フェーズ1:リリース直前のダンプ取得
②の失敗を受けて、リリース作業の直前に必ず gcloud sql export でダンプを取るようにしました。
- 課題: インスタンスの規模によっては、エクスポートだけで1時間以上かかることも。ダウンタイムを最小限にしたいリリース作業において、この待ち時間は大きなボトルネックでした。
フェーズ2:リードレプリカ昇格による切り替え(現在)
現在採用しているのが、リードレプリカを身代わりにする手法です。
運用の流れ:
- リリース作業の直前に、本番DBのリードレプリカを作成しておく。
- 本番DBに対してリリース(DB変更)を実施。
- もし本番DBが壊れたり不安定になったりしたら、用意しておいたリードレプリカを昇格(Promote)させる。
- アプリケーションの接続先を、新しく昇格したDBに切り替える。
これならば、万が一の際も「新規インスタンス構築 + 長時間のリストア」を待たずに、数分での復旧が可能になりました。
4. 今後の展望:理想のBlue/Greenへ
現在の方法は「壊れた時の保険」としては優秀ですが、運用としてはまだ改善の余地があります。
- 理想: ダウンタイムなしでデータベース変更を含むリリースを実現すること。
- 課題: Cloud SQLには標準でポチッと押せる「Blue/Greenデプロイメント」機能が(現時点では)用意されていません。
今後は、Database Migration Service (DMS) の活用や、Proxy層での切り替え(ProxySQL)など、より高度なBlue/Green環境の構築を追求していきたいと考えています。AWS AuroraはAurora Blue/Green Deploymentsというボタン一つで切り替えられる機能があるらしい(書き込み制御、同期を行ってからの切り替えなどを全てやってくれる)ので、それも試したい!GCPで上手いやり方あったら誰か教えてください!
おわりに
医療系システムという「止めてはいけない」環境だからこそ、DB操作には人一倍慎重になります(とはいえ、操作ミスでとんでもないことになることもあるあるですよね)。もし同じようにCloud SQLの挙動やリリース手法で悩んでいる方がいれば、一つの事例として参考になれば幸いです。
「もっと良い方法があるよ!」という知見をお持ちの方がいれば、ぜひコメントで教えてください!
この記事が、どこかの現場で困っている誰かの一助になれば!
