先釐清「不同步」究竟代表什麼
使用者回報「ERP 顯示已出貨,但 CRM 還是處理中」時,第一步不是重送 API,而是確認兩個畫面是否真的在描述同一個業務狀態。不同系統常以不同粒度管理訂單:電商平台可能只有待處理、已出貨、已完成;倉儲系統則區分揀貨、包裝、交運與簽收;財務系統關心的又是請款、收款與退款。若沒有狀態對照表,看似不同步的資料可能只是語意不同。
工程團隊應先記錄訂單識別碼、各系統目前值、預期值,以及使用者認為狀態應改變的業務事件。接著確認問題影響的是整張訂單、單一品項、出貨批次,還是付款紀錄。同一張訂單可能分批出貨,也可能在付款後局部取消;若整合邏輯只保存訂單層級狀態,細部變更就容易被錯誤地合併。
- 識別一致性:確認外部訂單號、內部流水號、出貨單號與退款單號的關聯沒有串錯。
- 語意一致性:確認各系統狀態的定義、進入條件與終止條件,而不只比較文字名稱。
- 時間一致性:區分事件發生時間、來源系統提交時間、中介層接收時間與目標系統寫入時間。
- 範圍一致性:確認狀態屬於訂單、品項、付款、發票或物流批次中的哪一層。
凍結證據,再沿著事件軌跡查找斷點
不要先在資料庫手動修正,也不要立刻大量重送。這些動作可能覆蓋原始時間戳記、觸發重複通知,或讓真正的錯誤路徑消失。較安全的做法是先建立事件時間線:來源系統何時產生變更、哪個服務讀取它、傳出的內容為何、中介層如何轉換、目標系統回覆什麼,以及後續是否有重試或人工操作。
每一段傳輸都應使用可跨服務查詢的關聯識別碼。若既有系統沒有 trace ID,可暫時用訂單號、事件類型、來源時間與 payload 雜湊交叉比對,但要注意訂單號可能重複使用,時間也可能受時區或主機時鐘影響。日誌必須保留方向、端點、HTTP 狀態、業務錯誤碼與重試次數;只記錄「呼叫成功」不足以證明目標系統已接受業務變更。
重建狀態轉移,而不是只比較最後結果
找到所有紀錄後,應按照業務事件的因果關係排列,而不是單純依資料庫寫入時間排序。常見斷點包括 webhook 晚到、訊息佇列重複投遞、批次匯入覆蓋新值、狀態映射缺漏,以及人工操作與自動流程競爭。舉例來說,「取消」事件可能先到達目標系統,「已出貨」事件卻因重試較晚寫入;若消費端沒有版本檢查,訂單便會倒退到已出貨。
排查時要逐一回答:來源是否真的提交事件;傳輸是否成功;轉換後的欄位是否正確;目標是否接受請求;寫入後是否又被其他程序覆蓋。特別要區分技術成功與業務成功。HTTP 200 可能只代表請求已收到,實際處理仍在背景佇列中;相反地,逾時也不代表寫入失敗,盲目重送反而可能建立重複出貨單。
- 缺失事件:檢查交易提交與事件發布之間是否存在空窗,必要時採用 outbox 模式。
- 重複事件:以穩定的事件鍵實作冪等,不能只靠短時間內去重。
- 順序錯亂:比較業務版本或序號,不要假設網路到達順序就是發生順序。
- 轉換錯誤:保存原始 payload 與轉換結果,讓欄位映射可以被重現。
- 後續覆寫:檢查批次同步、人工匯入、排程工作及其他整合是否寫入同一欄位。
明確指定每個狀態的權威來源
責任鏈的核心問題是:誰有權宣告這個狀態成立。答案通常不是「ERP 負責所有訂單資料」,而是依欄位與生命週期拆分。例如付款結果由金流或財務系統負責,實際出貨由倉儲系統負責,客戶聯絡資訊可能由 CRM 維護。當兩個系統都能修改同一欄位,必須定義優先權、允許的轉移,以及衝突時是拒絕、等待人工判斷,還是以新版本覆蓋。
修復方式取決於影響與可逆性。單筆且已確認責任來源的問題,可以透過受控補償指令修正;大量或持續發生的問題,應先停止有問題的寫入路徑,再從權威來源執行差異比對。直接以完整資料表覆蓋雖然快速,卻可能抹除目標系統中的合法人工調整。較穩健的方式是產生差異清單,依欄位、版本與允許的狀態轉移逐筆套用,並保留操作稽核。
把一次事故轉成可持續的控制機制
問題修復後,至少要補上狀態契約、事件可追蹤性與定期對帳。狀態契約應列出來源、目標、映射規則、不可逆狀態與例外流程;監控則應觀察事件積壓、處理延遲、死信與業務拒絕,而不只是服務是否存活。對帳工作可以比較權威來源與下游快照,輸出可重跑的差異清單,避免讓客服或營運人員靠肉眼巡查。
成熟的整合並不承諾任何時刻都完全同步,而是明確定義可接受延遲、衝突處理方式,以及如何證明每筆資料走過哪條路徑。當責任鏈能被查詢、重播與稽核,訂單落差就會從難以重現的跨部門爭議,轉變為可以定位與控制的工程問題。