Cloud Spannerのスキーマ管理:破壊的な進化を「無停止」で実現するエンジニアリング
Spannerを「ただの分散RDBMS」だと思っているなら、今すぐその認識を改めるべきだ。
Spannerは、Googleのデータセンター規模の整合性を担保するための巨大なステートマシンである。この「巨大な機械」に対して、稼働中にメスを入れる(スキーマを変更する)という行為は、並大抵のRDBMSとは次元の異なる緊張感を伴う。
今日は、Spannerにおけるスキーマ管理の本質と、現場で生き残るための「マイグレーション戦略」について、綺麗事抜きで語る。
—
1. DDLの性質を正しく理解せよ
まず心に刻んでほしい。Spannerの `ALTER TABLE` は、MySQLのオンラインDDLとはわけが違う。
- 非同期実行の真実: `UpdateDatabaseDdl` を発行すると、Spannerは非同期でスキーマ変更を開始する。これは「データ移行」ではなく「メタデータの伝播」だ。
- バックグラウンド処理のインパクト: インデックスの追加や列の追加は、バックグラウンドで全スプリットを走査する。これを甘く見ると、ピーク時にIOPSとCPUを食い荒らされ、レイテンシが跳ね上がる。
鉄則:DDLは「冪等性」を信じるな
多くのフレームワークがDDLのマイグレーションツールを提供しているが、Spannerで最も危険なのは「中途半端な失敗」だ。DDL実行中に何らかの理由でタイムアウトした場合、そのDDLが「いつ完了したか」を正確に追跡する仕組みを、アプリケーション側(あるいはマイグレーション用パイプライン)で握っておく必要がある。
—
2. 堅牢なスキーマ管理のアーキテクチャ
Spannerのスキーマ管理で「やってはいけないこと」は、人間がコンソールからポチポチ操作することだ。
推奨構成:IaCによるバージョン管理
スキーマを `schema.sql` としてリポジトリに入れ、CI/CDで適用する。この際、以下の戦略を徹底せよ。
1. Statefulな管理の排除: マイグレーションツール(LiquibaseやFlywayなど)を使う場合、Spannerがネイティブに持つ `INFORMATION_SCHEMA` を正として使う設計にせよ。
2. DDLの分割: 1つのトランザクションで複数のDDLを投げない。特にインデックス作成とテーブル変更を混ぜると、運用上のデバッグが地獄になる。
3. オンライン・マイグレーションの3ステップ:
- Phase 1 (Add): 新しい列を追加する(Nullableであること)。
- Phase 2 (Sync): アプリ側で新旧両方の列に書き込む(読み込みは旧を参照)。
- Phase 3 (Switch): 読み込みを新列に切り替え、旧列を削除する。
—
3. パフォーマンスを殺さない「インデックス戦略」
Spannerにおいて最大のパフォーマンス事故は「不適切なタイミングでのインデックス追加」だ。
— 危険な例:巨大なテーブルに対して、いきなり複雑なインデックスを貼る
— これをやると、バックグラウンドでの再構築処理が長時間続き、スプリットの負荷が跳ね上がる。
ALTER TABLE Users ADD INDEX idx_users_email ON Users(email);
チーフアーキテクトからの助言:
インデックスを追加する際は、`STORING` 句を活用し、クエリの実行計画が `Index Scan` だけで完結するように設計せよ。また、バックグラウンド処理の影響を最小化するために、負荷が低い時間帯を狙うか、`FORCE_INDEX` を使った検証を事前に行うのが鉄則だ。
—
4. 破壊的な変更をどう管理するか
Spannerは「データの整合性」に対して極めて厳格だ。一度作成した主キーや、パーティションのキーを変更することはできない。
もし主キーを変えたい場合は、以下の手順を踏むしかない。
1. 新しいテーブルを作成: 変更後のスキーマを定義する。
2. Dataflowでマイグレーション: 既存テーブルから新しいテーブルへデータを流し込む。
3. シャドー書き込み: 新旧両方のテーブルへ書き込みを行う。
4. 切り替え: アプリケーションの接続先を新テーブルへ切り替える。
このプロセスを自動化するための「マイグレーション・パイプライン」を構築できているか? これができていないチームは、Spannerを使いこなしているとは言えない。
—
最後に:なぜ「バージョン管理」が重要なのか
Spannerは止まらない。しかし、システムの進化に合わせてスキーマは必ず「腐る」。
- レビューの自動化: `gh-ost` のような仕組みをSpannerでも意識し、スキーマの変更が「読み込み負荷」にどれだけの影響を与えるか、`EXPLAIN` を見てレビューすること。
- メタデータの可視化: 現在のDBのスキーマバージョンを `DatabaseOptions` にタグとして埋め込み、アプリケーション起動時に現在のコードとスキーマの互換性をチェックするロジックを入れること。
「スキーマ管理」とは単なるSQLの履歴保存ではない。「サービスを止めずに、Spannerという巨大な海を航海し続けるための地図」を作成する行為なのだ。
この地図を雑に描くエンジニアに、Spannerを扱う資格はない。今日から、リポジトリの `schema.sql` を、プロダクトの命綱として扱いなさい。
以上だ。実装に移れ。
コメント