Skip to Content
核心概念遷移與診斷

遷移、表鎖與診斷

加欄、改型別、刪欄、產生大量測試資料或診斷大表,可能需要在背景掃描資料列。遷移 API 把「這張表現在是否能接受 schema 寫入」與「某一個背景工作的進度」分成兩個狀態,前端要分別追蹤。

什麼時候會出現 migration

Schema endpoint 的成功回應若含 background_migration: truemigration_id,表示 schema 變更已受理,但資料回填仍在背景進行。純量欄位變更通常在小表同步處理,超過門檻才背景化;計算欄多半是 metadata-only。不要把固定筆數寫死成 UI 判斷,應以回應為準。

遷移期間伺服器會鎖表,避免另一個 schema/大量操作與它交錯。衝突請求回 423 Locked。此時不要盲目重送原 mutation;先查 table lock 與已知 migration。

欄位更新與轉型

PATCH .../columns/{column_id} 並不代表每個欄位都可修改。linkrolluplookupformula 欄只能修改 namedescription;關係、彙總、lookup、pick 與 expression 都是建立時設定。欄位也不能轉成或轉離這四種計算型別。若要改設定,必須刪除並重建。

Stored 欄位轉型在遷移開始前有以下 preflight gates:

  • 轉成 selectmulti_select 時,同一個請求必須提供完整 options 清單。
  • 必填欄必須提供新的、與新型別相容的 default_value。選填欄若沒有提供新預設值,schema 預設值會被清除,無法轉換的 cell 會退回 null
  • required 從 false 改為 true 會掃描 live rows;任何 cell 缺少或為 JSON null 都會讓更新失敗。Preflight 不會"" 當成空值,雖然後續 record write 會拒絕明確寫入空字串到必填欄;client 應先清理既有空字串。
  • 被 link/rollup/lookup/formula 相依引用的欄位一律不能轉型,唯一例外是 integerfloat。這也會擋看似相近的 stringtext;有損數值轉換仍會針對適用的 unique 規則預先檢查碰撞。
  • 舊型別專用設定會被移除,例如離開 select 會移除 options,離開 attachment 會移除附件限制。

既有 cell 轉換矩陣

轉型不會無條件把每個值替換成新預設值。伺服器會逐一盡力轉換既有且已存在的 cell;只有無法轉換的值才退回新的 default_value,未提供時則為 null。既有 null"" 會保持空值,不會被預設值填滿。同步與背景路徑使用同一套規則。

舊型別新型別既有 cell 結果
integerfloat另一個數值型別進行數值轉換;integer→float 可能失去精度,float→integer 會先四捨五入,且必須落在 signed 64-bit 範圍。
string / textinteger / float解析 trim 後的數值文字;無效、非有限或超出範圍時退回。
integer / float / booleanstring / text使用伺服器的字串表示;布林會變成 "True""False"
stringtext另一個文字型別保留字串值。
datedatetime附加 00:00:00;這個僅遷移會產生的含秒形狀與一般 datetime 驗證衝突,見下方。
datetimedate保留空白或 T 之前的日期部分。
string / textjson把 trim 後的字串解析成 JSON,並套用 JSON byte、depth、node 與有限數字限制;無效時退回。
integer / float / booleanjson保留純量,作為合法 JSON 值。
jsonstring / text以 object key 排序後序列化;若超過新的明確 max_length 則退回。
任意型別轉成或轉離 attachment一律退回;blob ID 不會跨欄位型別轉換。
任意型別轉成或轉離 principal / user / social_client一律退回;schema 遷移不會重新驗證不透明的租戶身分。這包含 usersocial_clientuserprincipal——沒有任何轉型會把裸 id 加上前綴變成帶標籤的 cell。
selectmulti_select 或上表未列出的任何組合另一個 stored 型別退回新預設值,未提供時為 null

已知後端不一致 一般紀錄寫入與預設值只接受不含秒的 YYYY-MM-DD HH:mm。但 date→datetime 遷移會寫入 YYYY-MM-DD 00:00:00,所以前端可能讀到一個無法原樣寫回的含秒值。請把它視為遷移輸出,而不是新支援的輸入格式;後續寫入前先正規化到分鐘。

Select 選項改名是另一種遷移。option_renames 會改寫 live 與 soft-deleted records 的相符值、同步更新相符的 select 預設值,並重建受影響的 unique-rule entries。同一個請求不能同時使用 option_renames 與完整 options replacement。

Table migration status:回答「表是否被鎖」

這條路徑仍是一般 scoped table path:

GET /private/module/custom_tables/{scope}/.../tables/{table_id}/migration/status

聊天室與部門版本的 {scope} 仍包含自己的 scope ID。回應重點是:

{ "table_id": "22222222-2222-4222-8222-222222222222", "is_locked": true, "lock_info": { "operation": "add_column", "acquired_at": "2026-07-19T02:20:00Z", "expires_at": "2026-07-19T02:30:00Z" }, "record_count": 15000 }

它適合在表設定頁決定是否 disable schema controls,也能在只收到 423、手上沒有 migration ID 時診斷目前 lock。is_locked: false 才表示可以重新整理 schema 並考慮重試使用者動作。

Migration status:回答「工作做到哪裡」

背景工作用 migration_id 輪詢:

GET /private/module/custom_tables/{scopeName}/migrations/{migration_id}/status

這是 id-less pathscopeName 只填 chatroomdepartmentcompany,後面沒有 chatroom_iddepartment_idtable_id。例如:

GET /private/module/custom_tables/department/migrations/88888888-8888-4888-8888-888888888888/status

Migration IDs 在全系統全域唯一。伺服器會由 migration ID 找到所屬的表,並依該表真實的 scope 做授權;只有 company 前綴的路由會在表不屬於 company 時額外回 404 — chatroom/department 前綴的路由則不比對 URL 前綴,只看你對該表的存取權。全域唯一不代表只要登入就能讀別人的進度。

回應提供 operationstatusprogresstotal_recordsmigrated_records 與失敗時的 error_message。常見狀態是 pendingrunningcompletedfailedcancelled。只有 completed 才刷新 schema/records;failedcancelled 應停止 polling 並呈現伺服器訊息。

Diagnosis:找 schema、資料與效能問題

診斷從一般 scoped table route 啟動:

POST .../tables/{table_id}/diagnosis

它檢查有效/無效資料列、validation errors、schema issues、data-integrity issues 與 performance recommendations。聊天室與部門需要 table moderator;公司範圍只要求 table access,這是不能從相同 path tail 推論 auth 的例子。

小表可能同步回 diagnosis_results。超過背景門檻時回 background_processing: true 與 migration ID;先輪詢一般 migration status,完成後再取:

GET /private/module/custom_tables/{scopeName}/migrations/{migration_id}/diagnosis-results

Diagnosis results 路徑與 status 一樣沒有 scope ID/table ID,而且只在背景診斷完成且結果仍可取得時使用。若啟動時表已被其他遷移鎖住,會回 423,不會排入另一個互相衝突的診斷。

建議的前端狀態機

  1. Schema/diagnosis 回同步結果:立即刷新並結束。
  2. migration_id:保存 ID、scope name、table ID 與 operation,畫進度並輪詢 job status。
  3. 只收到 423:查 table migration status,顯示 lock_info.operation
  4. Job completed:若是 diagnosis,再取 diagnosis-results;否則重新抓 table/schema。
  5. Job failedcancelled:停止重試,顯示 error_message,保留診斷資訊供支援使用。

不要只把 polling state 放在單一 React component;重新整理後應能從保存的 migration ID 恢復,或至少用 table lock endpoint 誠實顯示維護中。

所有狀態 response 與各 scope auth 見生命週期參考。欄位變更如何產生 migration 見欄位型別;可在 API Playground檢查 id-less URL 展開結果。

Last updated on