サービスを止めずに DB のスキーマを変えるには、どうしますか

一度に壊す変更をせず、列を足す、新旧の両方に書く、古いデータを移す、読む先を切り替える、古い列を消す、と段階を分けて進める、と答える問い。どの段階でも戻せるようにする理由と、手間との引き換えまで話します。

答えてみる

面接官に「サービスを止めずに DB のスキーマを変えるには、どうしますか」と聞かれたつもりで、答えを見る前に自分の言葉で答えます。

声に出して答えた人は「書かずに答えを見る」で開けます。

解説を読む

聞かれ方から関連するコースまで、この問いの解説を全部ここに置いています。

こう聞かれます

  • 「サービスを止めずに DB のスキーマを変えるには、どうしますか」
  • 「動いているサービスで、列の名前を変えたいときは、どう進めますか」
  • 「スキーマの変更とアプリの配備は、どちらを先にしますか」

面接官が見ている点

  • 配備の途中は、古いアプリと新しいアプリが同時に動く、と分かっているか
  • 一度に壊す変更をせず、段階に分けて進められるか (列の追加、両方への書き込み、移行、読む先の切り替え、削除)
  • どの段階でも、1 つ前に戻せるようにしているか
  • 大きな表への変更で、ロックが長くかかる危険を知っているか

短い答え

  • 一度に壊す変更をせず、新しい列を足す、新旧の両方に書く、古いデータを移す、読む先を新しい列に切り替える、古い列を消す、と段階に分けて進めます。
  • 配備の途中は古いアプリと新しいアプリが同時に動くので、どの段階でも、両方の版が動ける形のスキーマにしておく必要があるからです。
  • 段階ごとに出して確かめ、何かあれば 1 つ前に戻せるようにします。そのかわり手間と期間はかかるので、止めてよい時間を取れるなら、一度に変えるほうが早いこともあります。

少し詳しい答え

なぜ段階に分けるか

アプリを止めずに出し直すと、しばらくの間、古い版と新しい版が同時に動きます。たとえば、列の名前を name から full_name に一度に変えると、まだ動いている古い版が name を探して落ちます。

だから、スキーマはいつも「古い版も新しい版も動ける形」を保ちながら、少しずつ変えます。この進め方は、広げてから縮める (expand と contract) と呼ばれることもあります。

列の名前を変える例

  1. 列を足す新しい列を、空 (NULL) を許す形で足します。古い版は新しい列を知らないので、そのまま動きます
  2. 両方に書くアプリを直して、書くときは古い列と新しい列の両方に書きます。読むのは、まだ古い列です
  3. 古いデータを移す前からある行の値を、新しい列へ少しずつ写します
  4. 読む先を切り替えるアプリが新しい列を読むようにします。様子を見て、問題が無ければ次へ進みます
  5. 古い列を消す古い列を書くのをやめ、古い版がどこにも残っていないのを確かめてから、列を消します

SQL クエリ

-- 1 列を足す (空を許す)
ALTER TABLE users ADD COLUMN full_name TEXT;

-- 3 古いデータを少しずつ写す (1 回に写す行を絞る)
UPDATE users SET full_name = name
WHERE full_name IS NULL AND id BETWEEN 1 AND 10000;

-- 5 古い版が残っていないのを確かめてから消す
ALTER TABLE users DROP COLUMN name;

どの段階でも、アプリを 1 つ前の版に戻しても動きます。列を消す最後の段階だけは戻せないので、いちばん後に回し、控え (バックアップ) を取ってから行います。

大きな表で気をつけること

行の多い表にいきなり NOT NULL の列を足す、型を変える、インデックスを作る、といった変更は、DB や変更の種類によっては、長い間表をロックしたり、全部の行を書き直したりします。その間は読み書きが止まり、実質的にサービスが止まります。

DB ごとに、ロックを短くする方法 (インデックスを作りながら読み書きを止めない指定など) があるので、使う DB の文書で確かめ、本番に近い量のデータで先に試します。データを写すときも、1 回で全部写さず、少しずつ分けて写します。

トレードオフ

段階に分けると安全ですが、配備の回数が増え、しばらく両方に書くコードが残り、終わるまで期間がかかります。途中で止めてしまうと、使われない古い列や両方に書くコードが残り、かえって分かりにくくなります。

利用者がまだ少ない、夜間に止めてよいと決めている、といった場合は、お知らせを出して短く止め、一度に変えるほうが早く確実なこともあります。止めてよいかどうかを先に決めてから、進め方を選びます。

話すときは、自分が関わったサービスでスキーマを変えた例を 1 つ用意し、何段階に分けたか、途中で戻せるようにしたかを話します。

よくある間違い

  • 列の名前を一度に変える配備の途中で動いている古い版が落ちます。足してから消す、の順にします
  • アプリを出す前に古い列を消す古い版がまだ読んでいると落ちます。消すのはいつも最後です
  • 大きな表に、いきなり重い変更をかける長いロックで読み書きが止まることがあります。本番に近い量で先に試します

深掘りの問い

  • 「スキーマの変更とアプリの配備は、どちらを先にしますか」足す変更はスキーマが先、消す変更はアプリが先 (古い列を使わなくなってから消す)、と答えます
  • 「途中で問題が出たら、どう戻しますか」最後の削除の前なら、アプリを前の版に戻すだけで動くように段階を組んでいる、と答えます
  • 「NOT NULL の列を足したいときは」 まず空を許して足し、データを埋めてから、NOT NULL の制約を付ける、と答えます

確認日 2026年10月24日

技術面接問題の一覧へ戻る