Hasura Migration 檔案長什麼樣?up/down.sql & yaml 解剖

Published August 5, 2025 by 徐培鈞
Web API

想像一下這個情況:你和同事一起開發一個專案,你在本地新增了一個 users 表格,但同事的資料庫裡沒有。

或者你想在正式環境部署時,確保資料庫結構和開發環境完全一樣。這時候就需要 Migration 來幫忙了!

在 Hasura 中,Migration 就像是「資料庫變更的說明書」,記錄了每一步資料庫的修改,讓團隊成員和不同環境都能保持同步。

簡單來說:

  • 🎯 Migration = 資料庫變更的歷史記錄
  • 自動同步 不同環境的資料庫結構
  • 🔄 可以回退 如果改錯了能夠復原
  • 👥 團隊協作 大家的資料庫都保持一致

Hasura Migration 檔案在哪裡?

當你在 Hasura Console 點擊任何按鈕(建立表格、新增欄位等),Hasura 會自動在背景產生檔案。

檔案長這樣:

your-project/
├── migrations/
   └── default/
       ├── 1691234567890_init/
          └── up.sql
       ├── 1691234567891_create_table_users/
          ├── up.sql      「往前做」的指令
          └── down.sql    「往後退」的指令
       └── 1691234567892_add_user_email/
           ├── up.sql
           └── down.sql
└── metadata/
    ├── tables.yaml     表格設定
    └── databases.yaml  資料庫連線設定

檔案名稱的秘密:

1691234567891_create_table_users/
              
              └── 人類看得懂的描述
└── 時間戳記(電腦用來排順序)

為什麼要用時間戳記?

  • 確保每個人的 Migration 都按照正確順序執行
  • 避免兩個開發者同時建立檔案時發生衝突

up.sql:「往前走」做了什麼?

up.sql 記錄的是「我要做什麼變更」。

實際情況 1:在 Console 建立一個新表格

你在 Console 做的事:

  1. 點擊「Create Table」
  2. 輸入表格名稱:users
  3. 新增欄位:name, email
  4. 點擊「Add Table」

Hasura 自動產生的 up.sql:

-- 建立 users 表格
CREATE TABLE "public"."users" (
    "id" uuid NOT NULL DEFAULT gen_random_uuid(),
    "name" text NOT NULL,
    "email" text NOT NULL,
    "created_at" timestamptz NOT NULL DEFAULT now(),
    PRIMARY KEY ("id")
);

白話翻譯:

  • 建立一個叫 users 的表格
  • id(自動產生)、nameemailcreated_at 四個欄位
  • id 是主鍵(每筆資料的唯一識別)

實際情況 2:為表格新增欄位

你在 Console 做的事:

  1. 進入 users 表格
  2. 點擊「Add Column」
  3. 新增 phone 欄位

Hasura 自動產生的 up.sql:

-- 為 users 表格新增 phone 欄位
ALTER TABLE "public"."users" ADD COLUMN "phone" text;

白話翻譯:

  • 在現有的 users 表格新增一個 phone 欄位

實際情況 3:建立表格之間的關聯

你在 Console 做的事:

  1. 建立 posts 表格
  2. 設定 author_id 欄位
  3. 建立與 users 表格的關聯

Hasura 自動產生的 up.sql:

-- 建立 posts 表格
CREATE TABLE "public"."posts" (
    "id" uuid NOT NULL DEFAULT gen_random_uuid(),
    "title" text NOT NULL,
    "content" text,
    "author_id" uuid NOT NULL,
    PRIMARY KEY ("id")
);

-- 建立關聯(posts 的 author_id 對應到 users 的 id)
ALTER TABLE "public"."posts" 
ADD CONSTRAINT "posts_author_id_fkey" 
FOREIGN KEY ("author_id") REFERENCES "public"."users"("id");

白話翻譯:

  • 建立 posts 表格
  • 每篇文章都有一個作者(透過 author_id 連結到 users

down.sql:「往後退」怎麼復原?

down.sqlup.sql 的相反操作,用來撤銷剛才的變更。

對應上面三個情況的 down.sql:

情況 1 的 down.sql:刪除整個表格

-- 刪除 users 表格
DROP TABLE "public"."users";

情況 2 的 down.sql:移除欄位

-- 從 users 表格移除 phone 欄位
ALTER TABLE "public"."users" DROP COLUMN "phone";

情況 3 的 down.sql:刪除關聯和表格

-- 先刪除關聯
ALTER TABLE "public"."posts" DROP CONSTRAINT "posts_author_id_fkey";
-- 再刪除表格
DROP TABLE "public"."posts";

為什麼需要 down.sql?

真實情況:

  • 📱 你剛發布新功能到正式環境
  • 🚨 發現有嚴重 bug,用戶無法登入
  • ⏰ 現在是晚上 11 點,需要緊急修復
  • 🔄 執行 down.sql 快速回到上一個穩定版本
# 一鍵回退最後一次變更
hasura migrate apply --down 1

為什麼 Hasura 需要兩種檔案?SQL + YAML 的分工合作

你可能會好奇:「為什麼不能只用一種檔案就好?為什麼要搞得這麼複雜?」

其實這是有原因的!讓我們用一個簡單的比喻來理解:

蓋房子的比喻

SQL 檔案 = 建築結構

  • 地基、樑柱、牆壁(資料庫的表格、欄位、關聯)
  • 這些是「硬體」,是房子的骨架

YAML 檔案 = 室內裝潢

  • 家具擺設、電器配置、裝修風格(權限、GraphQL 設定、UI 配置)
  • 這些是「軟體」,是房子的功能配置

實際差異對照

負責內容資料庫結構
舉例• 建立 users 表格• 新增 email 欄位• 設定外鍵關聯
負責內容Hasura 功能
舉例• 誰可以查看哪些資料• GraphQL API 的名稱• 自動觸發的事件

具體範例說明

情況:建立一個 users 表格

SQL 檔案處理:

-- 建立基本結構
CREATE TABLE "public"."users" (
    "id" uuid NOT NULL DEFAULT gen_random_uuid(),
    "name" text NOT NULL,
    "email" text NOT NULL
);

YAML 檔案處理:

# 設定這個表格在 Hasura 中的行為
- table:
    name: users
    schema: public
  select_permissions:
    - role: user
      permission:
        columns: [id, name, email]
        filter: { id: { _eq: "X-Hasura-User-Id" } }

為什麼要分開?

資料庫獨立性

  • SQL 檔案可以在任何 PostgreSQL 資料庫執行
  • 即使不用 Hasura,這些 SQL 也能正常運作
  • 如果哪天要換別的工具,資料庫結構不會丟失

Hasura 特有功能

  • YAML 檔案包含 Hasura 獨有的設定
  • 權限控制、GraphQL 客製化、事件觸發等
  • 這些功能其他資料庫工具不一定有

職責分離

  • 資料庫管理員關心 SQL(結構)
  • 應用程式開發者關心 YAML(功能)
  • 不同角色的人可以專注在自己的領域

版本控制更清楚

  • SQL 變更 = 資料庫結構改變(通常需要更謹慎)
  • YAML 變更 = 功能設定調整(相對安全)
  • 可以分別追蹤不同類型的變更

兩者如何協作?

完整的 Migration 流程:

  1. SQL 先執行
   # 更新資料庫結構
   hasura migrate apply
  1. YAML 後套用
   # 套用 Hasura 設定
   hasura metadata apply

為什麼要這個順序?

  • 先有桌子(SQL),才能在桌子上放東西(YAML)
  • 如果表格都沒有,就無法設定表格的權限

實際遇到的情況

場景:團隊新成員加入專案

只執行 SQL 會怎樣?

hasura migrate apply  # ✅ 資料庫結構 OK
# 但是...沒有執行 metadata apply

結果:

  • ✅ 資料庫有正確的表格和欄位
  • ❌ Hasura Console 看不到表格
  • ❌ GraphQL API 無法使用
  • ❌ 權限設定都消失了

正確做法:

hasura migrate apply   # 先處理資料庫結構
hasura metadata apply  # 再處理 Hasura 設定

記憶小技巧

SQL = Structure(結構)

  • 想到「SQL」就想到「Structure」
  • 負責資料庫的骨架

YAML = Behavior(行為)

  • 想到「YAML」就想到「行為設定」
  • 負責 Hasura 的功能配置

YAML 檔案:Hasura 的設定檔

現在你知道為什麼需要 YAML 了,讓我們看看裡面實際放了什麼:

metadata/tables.yaml:表格的進階設定

- table:
    name: users
    schema: public
  # 權限設定
  select_permissions:
    - role: user
      permission:
        columns: [id, name, email]  # 用戶可以看到這些欄位
        filter:
          id: { _eq: "X-Hasura-User-Id" }  # 只能看到自己的資料
  # 關聯設定
  object_relationships:
    - name: posts
      using:
        foreign_key_constraint_on:
          column: author_id
          table: { name: posts, schema: public }

這個設定的意思:

  • 定義了 users 表格的權限
  • 一般用戶只能查看自己的個人資料
  • 設定了與 posts 表格的關聯

metadata/databases.yaml:資料庫連線

- name: default
  kind: postgres
  configuration:
    connection_info:
      database_url:
        from_env: HASURA_GRAPHQL_DATABASE_URL  # 從環境變數讀取連線字串

白話翻譯:

  • 告訴 Hasura 要連接哪個 PostgreSQL 資料庫
  • 連線資訊放在環境變數裡(比較安全)

實戰:Migration 是怎麼運作的?

步驟 1:開發階段

小明在本地開發:

  1. 打開 Hasura Console
  2. 建立 users 表格 → 產生 Migration A
  3. 新增 posts 表格 → 產生 Migration B
  4. 把程式碼 push 到 Git

步驟 2:其他開發者同步

小華拉取程式碼:

# 拉取最新程式碼(包含 Migration 檔案)
git pull

# 套用 Migration 到本地資料庫
hasura migrate apply
hasura metadata apply

結果: 小華的本地資料庫現在和小明的一模一樣!

步驟 3:部署到正式環境

# 在正式環境執行
hasura migrate apply --endpoint https://your-production-endpoint
hasura metadata apply --endpoint https://your-production-endpoint

結果: 正式環境的資料庫也更新了!

常見問題與實際解決方法

問題 1:「我不小心刪錯表格了!」

解決方法:

# 回退到刪除表格之前的狀態
hasura migrate apply --down 1

預防方法:

  • 重要操作前先備份
  • 在測試環境先試試看

問題 2:「團隊成員的資料庫不一致」

症狀:

  • A 同事說:「咦?為什麼我這裡沒有 phone 欄位?」
  • B 同事說:「我的 GraphQL query 為什麼失敗?」

解決方法:

# 檢查 Migration 狀態
hasura migrate status

# 套用遺漏的 Migration
hasura migrate apply
hasura metadata apply

問題 3:「正式環境部署出問題」

安全部署流程:

  1. 測試環境驗證
   # 先在測試環境試跑
   hasura migrate apply --endpoint https://test-endpoint
  1. 備份正式環境
   # 備份資料庫
   pg_dump your_database > backup_$(date +%Y%m%d).sql
  1. 部署到正式環境
   hasura migrate apply --endpoint https://production-endpoint
  1. 如果有問題立即回退
   hasura migrate apply --down 1 --endpoint https://production-endpoint

實戰練習:建立一個簡單的 Todo App

讓我們透過實際操作來理解 Migration!

目標:建立一個 Todo 應用程式

需要的表格:

  • users:使用者
  • todos:待辦事項

步驟 1:建立 users 表格

在 Hasura Console 操作:

  1. 點擊 Data → Create Table
  2. 表格名稱:users
  3. 新增欄位:
  • name (Text, Required)
  • email (Text, Required, Unique)

自動產生的檔案:

  • migrations/default/xxx_create_table_users/up.sql
  • migrations/default/xxx_create_table_users/down.sql

步驟 2:建立 todos 表格

在 Hasura Console 操作:

  1. 建立 todos 表格
  2. 新增欄位:
  • title (Text, Required)
  • completed (Boolean, Default: false)
  • user_id (UUID, Required)
  1. 建立與 users 的關聯

自動產生的檔案:

  • migrations/default/yyy_create_table_todos/up.sql
  • migrations/default/yyy_create_table_todos/down.sql

步驟 3:設定權限

在 Hasura Console 操作:

  1. 進入 todos 表格的 Permissions 頁面
  2. user 角色設定權限:
  • Select:只能看到自己的 todos
  • Insert:只能新增自己的 todos

自動更新的檔案:

  • metadata/tables.yaml

步驟 4:測試和部署

本地測試:

  1. 用 GraphQL 查詢測試功能
  2. 確認權限設定正確

部署到測試環境:

hasura migrate apply --endpoint https://test-endpoint
hasura metadata apply --endpoint https://test-endpoint

部署到正式環境:

hasura migrate apply --endpoint https://production-endpoint
hasura metadata apply --endpoint https://production-endpoint

Migration 的最佳實踐

命名要清楚

好的命名:

  • create_table_users
  • add_phone_to_users
  • create_user_posts_relationship

不好的命名:

  • update_db
  • fix_bug
  • temp_change

小步快跑

建議:

  • 每次只做一件事
  • 經常 commit 和 push
  • 不要累積太多變更

避免:

  • 一次建立 10 個表格
  • 同時修改結構和資料
  • 長時間不同步程式碼

測試再測試

部署前檢查清單:

  • ✅ 在本地測試過
  • ✅ 在測試環境驗證
  • ✅ 確認 down.sql 能正常執行
  • ✅ 備份正式環境資料

團隊溝通

重大變更時:

  • 提前通知團隊成員
  • 在團隊群組說明變更內容
  • 提供 Migration 執行指令

總結:掌握 Migration 的關鍵要點

核心概念

  • Migration = 資料庫變更的版本控制
  • up.sql = 往前做什麼
  • down.sql = 如何回退
  • YAML = Hasura 的進階設定

實際操作

  • 透過 Console 操作,讓 Hasura 自動產生檔案
  • 使用 hasura migrate apply 同步變更
  • 遇到問題時用 --down 回退

最佳實踐

  • 小步快跑,經常同步
  • 測試環境先驗證
  • 重要操作前要備份
  • 保持團隊溝通

下一步學習

  1. 試著建立一個簡單的專案
  2. 觀察每次 Console 操作產生的檔案
  3. 練習使用 CLI 指令
  4. 學習更進階的 Hasura 功能

記住,Migration 不是複雜的技術,而是讓團隊協作更順暢的工具。多動手練習,很快就能熟練運用!