先把回補視為可恢復的資料變更
回補最常見的風險,不是程式無法執行,而是執行到一半後無法判斷哪些資料已成功、哪些需要重做。開始前應固定來源範圍、轉換版本與目標資料表,並為每次作業建立批次識別碼。批次清單至少要記錄來源區間、讀取筆數、寫入筆數、錯誤筆數、開始與完成時間,以及使用的程式版本。
不要把整段歷史資料包成一個巨大交易。實務上應依日期、租戶、檔案或其他穩定邊界切成可重跑的小批次,完成一批便寫入檢查點。批次大小需要平衡吞吐量與復原成本:太小會增加協調與索引負擔,太大則會拉長鎖定時間,失敗時也必須重做更多工作。
用業務識別決定資料是新增還是更新
避免重複的核心是冪等性:同一批輸入重跑後,結果應與只執行一次相同。最可靠的方法通常是先寫入暫存表,再依穩定的業務鍵合併至正式表。若來源提供不可重複的事件識別碼,可以直接作為唯一鍵;若沒有,才考慮以訂單編號、明細序號、來源系統等欄位組成複合鍵。
內容雜湊適合偵測資料是否改變,但不一定適合作為唯一識別。來源若修正地址、狀態或金額,整列雜湊會改變,把它當主鍵反而可能新增第二筆資料。正式寫入前應明確定義哪些欄位構成身分、哪些欄位允許更新,以及來源與目標衝突時由哪一方優先。
- 只會新增的事件:使用事件識別碼與唯一約束,重複輸入直接對應同一事件。
- 會被來源修正的主資料:以穩定業務鍵更新現況,並另存異動時間與來源版本。
- 需要保留歷史版本的資料:將生效區間納入模型,不要以覆寫現況取代版本管理。
- 無可靠識別碼的舊檔:先建立正規化規則與例外清單,不要單靠忽略重複錯誤。
明確處理時間邊界與晚到資料
漏載經常發生在時間條件,而不是資料庫連線。建議所有批次使用半開區間,也就是包含開始時間、不包含結束時間,讓相鄰批次能無縫銜接。時間戳應保留原始時區並轉成統一比較基準;若來源只有日期,必須先定義該日期代表來源當地時間、會計日,還是系統處理日。
也要區分事件發生時間、來源更新時間與資料進站時間。只依事件時間回補,可能漏掉日後才補登的舊事件;只依更新時間查詢,又可能改變報表所屬期間。常見做法是以來源更新時間擷取,再依事件時間歸屬分析期間,同時保留原始時間與載入時間。切換回即時同步前,還應重疊掃描最後一段區間,交由冪等鍵消除重複。
先隔離資料,再讓報表看見
回補期間若直接持續寫入報表正在讀取的正式表,使用者可能看到只完成一半的月份、突然變動的累計值,或重複計入尚未合併的資料。較安全的流程是先載入暫存區,完成驗證後再以分區交換、受控合併或版本化檢視一次發布。若無法完全隔離,至少應讓報表排除尚未完成的批次。
驗證不能只比較來源與目標的總筆數,因為重複與漏載可能互相抵銷。檢查應涵蓋唯一性、缺漏、關聯完整性與業務彙總,並針對報表實際使用的日期、組織、產品或狀態維度進行比對。
- 對業務鍵執行重複檢查,並用反向比對找出只存在於來源或目標的資料。
- 按日與主要維度比較筆數、金額、數量及空值分布,不只檢查全表總計。
- 驗證外鍵與主從資料關係,避免明細已載入但對應主檔尚未完成。
- 在相同輸入上重跑已完成批次,確認資料與彙總結果不再改變。
把發布、監控與回滾納入同一份計畫
正式執行前應先用代表性區間演練,觀察查詢時間、鎖定、索引更新、交易日誌與下游刷新負載。回補速度不應以壓垮線上交易或即時同步為代價;必要時限制併發、分時執行,並設定可以暫停的條件。監控內容除了成功與失敗,也要包括批次延遲、異常筆數與待處理例外。
回滾方式必須在寫入前決定。每筆資料若能追溯至批次識別碼,就能刪除該批新增內容或還原被更新的舊值;若採分區或版本化資料集,則可切回上一版本。完成後再刷新語意層、快取與報表,並保留對帳結果。若無法說明一批資料如何安全重跑、如何驗證、如何撤回,就還不適合進入正式環境。