遷移:安全地更改 Schema
你的 schema 會變化——你會新增一列、重新命名一張表、加一個索引。把它想像成對一份共享文件的修訂追蹤:每一次更改都按順序記錄下來,於是每個人的副本都能用同樣的方式更新到最新。一次**遷移(migration)**是一個版本化的、可重複的指令碼,描述這樣一次更改。遷移之所以重要,是因為你筆記本上的 schema、你隊友筆記本上的 schema,以及生產環境裡的 schema 必須保持完全一致。
讓遷移保持安全的規則:
- 絕不要在生產環境裡手動改資料庫。 寫一次遷移。
- 遷移只往前走。 每一次都是一個新檔案;你不要去重寫那些已經執行過的舊檔案。
- 謹慎進行破壞性更改。 刪除一列或一張表會永久刪除資料。先有一份備份。
- 追加式更改最安全。 新增一個可空的列很少會破壞什麼;重新命名或移除一個列則可能破壞正在執行的程式碼。
遷移構成一條有序的鏈:每一次都是一個編號步驟,把資料庫的每一份副本從一個已知狀態推進到下一個,於是你的筆記本、隊友的筆記本和生產環境最終都完全一致:
空資料庫
│
▼
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ 001_init │ ▶ │ 002_add │ ▶ │ 003_index │ ▶ │ 004_bio │
│ users │ │ posts │ │ on author │ │ 列 │
└────────────┘ └────────────┘ └────────────┘ └────────────┘
按順序應用 ────────────────────────────────────────▶ 當前
切勿編輯已執行過的步驟 — 新增一個
像 Prisma、Drizzle,或 Rails 遷移這樣的工具會為你生成並跟蹤這些。讓它們去做。
一次遷移由兩半組成:要應用的更改(up)和如何撤銷它(down)。一個值得信賴的工具會把兩者都生成出來,這樣一次糟糕的部署就能幹淨地回滾:
-- up: 新增一個可選的 bio,可在線上安全地應用
ALTER TABLE users ADD COLUMN bio TEXT;
-- down: 把它反轉回去
ALTER TABLE users DROP COLUMN bio;
真正危險的遷移是重新命名和型別更改,因為舊程式碼和新 schema 會短暫地相互矛盾。專業的做法是把它們拆成追加式的步驟:新增新列、回填它、把程式碼切換到讀取它,只有在之後的一次部署裡、當沒有任何東西再引用舊列時,才把舊列刪掉。它感覺很慢,但這正是一次平滑釋出與部署途中每個使用者都看到 500 錯誤激增之間的區別。