【実務・中級編】 スキーマのバージョン管理 – Cloud Spanner

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` を、プロダクトの命綱として扱いなさい。

以上だ。実装に移れ。

コメント

タイトルとURLをコピーしました