資料庫與遷移
確認 D1 目標,檢查實際結構和遷移紀錄,處理缺少資料表、遷移中斷與資料約束問題。
遇到資料庫問題時,先確認連線目標,再檢查結構和資料。目前範本有兩個 D1,業務資料放在 DB,造訪統計資料放在 ANALYTICS_DB,本機與遠端也各自擁有獨立狀態。
一、確認正在檢查哪個資料庫
| Binding | 內容 | 基準資料表 | 初始化檔案 |
|---|---|---|---|
DB | 帳號、付款、權限、客服案件、通知、Reaction 等 | saas_user | schema/db-init.sql |
ANALYTICS_DB | 造訪統計工作階段、事件和屬性 | analytics_session | schema/analytics-init.sql |
wrangler.jsonc 中的 binding 是程式碼存取名稱,database_name 是資源名稱,database_id 才是遠端資源識別碼。CLI 會依專案名稱調整資源名稱,不能一律尋找 saavo-template-db。
以下是本機唯讀檢查,不會修改資料表結構:
npx wrangler d1 execute DB --local --command "SELECT name FROM sqlite_schema WHERE type = 'table' ORDER BY name;"
npx wrangler d1 execute ANALYTICS_DB --local --command "SELECT name FROM sqlite_schema WHERE type = 'table' ORDER BY name;"確認帳戶和資源 ID 後,遠端查詢請明確使用 --remote:
npx wrangler d1 execute DB --remote --command "SELECT name FROM sqlite_schema WHERE type = 'table' ORDER BY name;"不要省略環境旗標,再猜測指令會操作哪裡。指令參數請見 D1 Wrangler 指令。
二、出現 no such table 或 no such column
先核對發生錯誤的資料表屬於哪個資料庫,再判斷是否遺漏遷移。
本機專案執行:
npm run db:migrate:local已確認遠端目標、遷移內容和相容性的正式環境專案執行:
npm run db:migrate:remote這兩個指令分別處理對應環境中的兩個資料庫,不是只處理 DB。指令碼會依序執行,若前一個資料庫成功、後一個失敗,不能認為兩個資料庫都沒有變動。
缺少欄位時,也應檢查是否只修改了初始化 SQL。既有資料庫不會因為基準檔案新增一個欄位,就自動取得該欄位。結構變更需要寫入 schema/migrations。
請透過資料表結構確認結果,例如:
PRAGMA table_info('saas_user');查詢結果符合程式碼需求後,再重試原本的業務請求。不要只因為遷移指令未出現錯誤,就認為已完成全部驗證。
三、非空白資料庫缺少基準資料表
遷移指令碼的判斷流程如下:
- 沒有使用者建立的資料表時,執行該資料庫的初始化指令碼。
- 已有使用者建立的資料表,且存在對應基準資料表時,繼續套用遷移。
- 已有使用者建立的資料表,但缺少基準資料表時,停止執行。
第三種情況可能是繫結到其他專案、匯入不完整,或先前執行過破壞性的結構操作。請先保留資料表清單,核對資源 ID 和歷史操作,再決定恢復方式。
saas_user 或 analytics_session 是否存在,只是指令碼用來辨識基準的條件,並不是完整的結構驗證。不要手動建立空白的同名資料表來略過檢查。
請勿直接重新執行初始化 SQL
基準檔案包含刪除舊資料表的陳述式。對已有資料的資料庫執行初始化 SQL,或執行 db:reset,都會遺失資料。指令碼沒有復原功能,還原必須依靠事先準備的備份或資料庫還原功能。
四、遷移失敗或部署中斷
先記錄失敗的資料庫、遷移檔名、第一個 SQL 錯誤和執行時間。檢查遷移目錄中的命名:
schema/migrations/0001-db-add-example.sql
schema/migrations/0002-analytics-add-example.sql前綴必須是四位數字,中間的 db 或 analytics 決定所屬資料庫。檔名錯誤可能遭檢查指令碼拒絕,或未納入對應資料庫的遷移集合。
確認 d1_migrations 存在後,可在目標資料庫執行唯讀查詢:
SELECT id, name, applied_at
FROM d1_migrations
ORDER BY id DESC
LIMIT 20;同時也要檢查實際資料表結構。先前已完成的遷移,不會因為後續失敗而一併復原。跨兩個資料庫的更新,也不是同一筆資料庫交易。
| 檢查結果 | 處理方向 |
|---|---|
| 遷移尚未執行,SQL 本身有錯誤 | 先在本機修正並驗證,再套用至目標環境 |
| 檔案已在部分環境執行成功 | 保留已發布的遷移歷史,透過後續遷移修正差異 |
| 遷移紀錄與結構不一致 | 檢查是否有人手動修改資料表或匯入資料,不要直接刪除遷移紀錄 |
| SQL 已套用,但新 Worker 尚未發布 | 確認舊程式碼仍能執行,再修正發布步驟 |
目前 deploy:update 會在發布新 Worker 前執行遠端遷移。刪除或重新命名舊程式碼仍在使用的欄位,可能在新版本發布前就造成線上故障,設計遷移時應同時考慮新舊版本。
五、查不到剛儲存的資料
依序檢查:
- 寫入請求是否確實成功,回應本文是否包含業務失敗。
- 讀取和寫入是否使用同一個環境、同一個 Binding 和資源 ID。
- 是否需要經過 Webhook 或 Queue 才會實際寫入。
- 查詢條件是否包含錯誤的使用者 ID、連線 ID、狀態或時間範圍。
- 時間欄位是否以 Unix 毫秒比較,避免將秒直接當成毫秒。
不要直接使用 SELECT * 匯出工作階段或使用者資料表來排錯。僅查詢本次需要的 ID、狀態和時間,避免將 Token、雜湊值和加密資料混入共用記錄。
六、唯一約束與外部索引鍵約束失敗
唯一約束失敗可能是重複請求,也可能是業務 Key 設計錯誤。付款和 Reaction 都有各自的等冪邊界,應先定位違反了哪個索引,再追蹤本次業務來源。
外部索引鍵失敗時,請檢查父紀錄是否存在、寫入順序是否正確,以及資料是否誤寫至另一個資料庫。不要關閉外部索引鍵檢查,讓錯誤資料進入資料庫。
尤其是付款和權限資料,修正前必須了解事件帳本、交易明細、角色和權益之間的關係。手動刪除一筆紀錄,可能使系統將已完成的業務視為首次執行,造成重複授予權益。
修正後的驗證
在目標資料庫確認資料表結構和遷移紀錄,重試一筆最小業務操作,再查詢對應狀態。若涉及遷移,還應確認既有使用者能繼續讀取和更新舊資料。
欄位詳細資訊請見資料庫參考,正式環境的變更順序請見正式環境資料庫與遷移。