Reconciliation 與 data repair 的核心責任是把資料錯誤從模糊異常轉成可驗證、可修復、可稽核的流程。進入特定資料庫或 ORM 前、讀者需要先理解資料修復屬於正式狀態責任的一部分。

本章從不一致分類開始、進入偵測模式(連續 vs scheduled)、處理修復策略(auto vs manual)、最後對接 audit trail 跟 backup recovery。讀完後讀者能設計:對帳機制、修復 runbook、evidence handoff、audit chain。

Reconciliation

Reconciliation 的責任是比較兩個或多個資料來源、確認正式狀態是否與外部事實一致。付款狀態要和金流 provider 對齊、發票狀態要和開票系統對齊、庫存狀態要和出貨或倉儲系統對齊。

對帳需要明確定義資料來源、時間窗、比對鍵、差異分類與 owner。這些欄位能把「資料看起來不一致」轉成可分派、可修復、可驗證的決策材料。

對帳系統的設計欄位

設計對帳作業時、要先把這幾件事談清楚、再寫 query。少談任何一項、對帳結果都會在事故當下被質疑可信度。

來源 A 與來源 B:明確指出哪個是內部 source of truth、哪個是外部事實。金流對帳的 A 是訂單表、B 是 provider 結算檔;庫存對帳的 A 是訂單庫存表、B 是倉儲 WMS 報表。兩邊都要有明確 owner、否則差異發生時沒人能解釋為何資料長那樣。

比對鍵(comparison key):A 跟 B 要用什麼欄位對齊。最理想是雙方共用的業務 ID(例如金流交易序號);次優是 timestamp + 業務外鍵組合;最差是用 fuzzy matching(金額 + 時間範圍)、這時對帳結果天然帶有噪音、要在 output schema 標示信心度。

時間窗(time window):對帳要對哪段時間的資料、什麼時候做。每日對帳通常設定 T-1 整天、跳過今天(避免 in-flight 資料);分鐘級對帳要明確處理 in-flight:是排除最近 N 分鐘、還是允許重複跑直到收斂。在跨時區業務裡、時間窗要對齊雙方 timezone、不然每天差異會穩定出現在 0:00 前後。

差異分類規則:mismatch 不是只有「不一致」一種。常見要再切:「A 有 B 沒有」(missing in B)、「B 有 A 沒有」(missing in A)、「兩邊都有但欄位不同」(value mismatch)、「同一個 key 在 A 有多筆」(duplicate)。每類差異的處理路徑跟 owner 都不同、不分類會讓修復決策無法分派。

Output schema:對帳產出的不是「對 / 不對」、而是一份結構化報告。最少要有:mismatch 樣本(不是全部)、總筆數與金額影響、覆蓋率(總共比對了多少筆)、未覆蓋資料(哪些 A 或 B 沒涵蓋)、結果時間戳。這份報告會被 4.20 Observability Evidence Package 收進釋出證據鏈、結構不穩定會讓上游 release gate 拒絕採信。

對帳跟 anomaly detection 的差異

兩件事都是「找資料異常」、但本質不同、不能互相替代。

對帳是 deterministic:給定兩個來源、結果是確定的差異集合、可以被任何工程師重跑驗證。anomaly detection 是 statistical:用模型或閾值判斷一筆資料是否「看起來不對」、結果帶機率、不同模型跑出來不一樣。

在金流、庫存、付款這類正式狀態場景、對帳是必須、anomaly detection 是補充。anomaly detection 適合抓「對帳沒設計到的維度」(突然某 tenant 訂單量爆增)、但不能用它當 source of truth、因為事故時無法回答「為何這筆被判定為異常」。

兩者輸出格式也不同:對帳輸出 mismatch list、anomaly detection 輸出 confidence score。把兩者混在同一份報告會讓 incident reviewer 無法判斷哪些是必修、哪些是可疑。

不一致的三種分類

不是所有「資料不一致」都一樣。按 成因 分三類、各有不同處理策略。

Temporal Inconsistency(時間性不一致)

  • 來源:replication lag、async event delivery、eventual consistency
  • 特徵:兩邊都是「對的」、只是 時間點 不同
  • 例:cache 跟 DB 看到不同 value(cache 還沒 invalidate)、replica 跟 primary 不同步
  • 處理:等待收斂或主動觸發 sync、不必修資料
  • 持續時間:通常 < 1 秒到分鐘級

Structural Inconsistency(結構性不一致)

  • 來源:schema migration 期間、dual-write 失敗、partial write
  • 特徵:兩邊應該一致但實際不一致、其中一邊是 錯的
  • 例:訂單寫進主表但 line items 沒寫、外鍵 reference 一個不存在的 row
  • 處理:必須修復、不能等
  • 持續時間:永久(直到修復)

Semantic Inconsistency(語意不一致)

  • 來源:業務邏輯 bug、應用層 race condition、人工誤操作
  • 特徵:資料結構 OK、但 業務語意
  • 例:訂單付款狀態是 paid 但金流端是 refunded、帳戶餘額跟交易紀錄 sum 不符
  • 處理:複雜、需要業務判斷哪邊是 source of truth
  • 持續時間:永久(且容易擴大)

處理優先序:Semantic > Structural > Temporal。Semantic 影響業務最深、Temporal 通常自動收斂。

偵測模式

不同類型的不一致需要不同偵測模式。

Continuous Detection(持續偵測)

  • 每筆寫入跑 sanity check(trigger、constraint)
  • 應用層 invariant check
  • 適合:structural inconsistency(讓 DB 自己擋)
  • 成本:每筆寫入有 overhead

Scheduled Detection(定期對帳)

  • 每 N 分鐘 / 每天跑對帳 query
  • 跟外部 provider 比對
  • 適合:semantic inconsistency(業務級對齊)
  • 成本:對帳 query 本身耗資源

Sampling Detection(抽樣偵測)

  • 不跑全表、抽樣 10% / 1% 跑 checksum
  • 適合:大表(全表對帳成本高)
  • 成本:可能漏掉低頻 inconsistency

Reactive Detection(反應式偵測)

  • 用戶 / 客服回報後才查
  • 適合:尾長 inconsistency(找不到通用 pattern)
  • 成本:用戶體驗已受影響

對應 9.C20 Zomato — migration 期間 shadow read 持續對帳、抓 mapping 規則漂移。

Data Repair

Data repair 的責任是把已確認的資料差異修回正式狀態、並保留修復原因、範圍、證據與回退條件。修復可以是 SQL update、補事件、補發 webhook、重建 projection 或人工客服流程、但每種修復都要有範圍控制。

資料修復要先分成三種:

類型說明常見風險
欄位修復修正單筆或小批正式欄位mapping 規則錯誤會造成二次污染
派生狀態重建重建 index、cache、read model可能掩蓋正式狀態尚未修復
補償動作補退款、補發票、補通知可能產生重複副作用

修復前要先確認問題落在哪一層。正式欄位錯誤要修 source of truth;派生狀態錯誤要重建副本;外部副作用漏做要走補償流程。

欄位修復的判讀重點是 mapping 規則是否正確、因為錯誤規則會把單點差異擴成批次污染。派生狀態重建的判讀重點是 source of truth 是否已經正確、否則重建會複製錯誤。補償動作的判讀重點是副作用是否可逆、因為退款、通知或外部 webhook 可能已經被使用者或第三方看見。

Repair 原則

不管哪種修復、都遵守三個原則:

1. Idempotency(冪等)

  • 同樣的修復跑兩次、結果跟跑一次一樣
  • WHERE current_value != target_value 而不是無條件 update
  • 補通知 / webhook 帶 idempotency key、第三方可去重
  • 對應 Idempotency 卡片

2. Auditable(可稽核)

  • 每次修復都有 record:誰、什麼時候、改了什麼、為什麼
  • 修復前 + 修復後的 snapshot 都要存
  • 對應 Audit Log 卡片1.5 Red Team 的 audit 段

3. Reversible(可逆)

  • 萬一修復是錯的、能回退到 before state
  • 不可逆操作(DELETE)必須有 dry-run、必須備份
  • 對應 Rollback Window 卡片

修復前的 dry-run 與 impact assessment

修復前要先回答「這次修復會碰多少筆、影響多少業務、最壞情況是什麼」、才能進入執行。直接跑 update 是 production-grade 流程的反例、即使在 incident 壓力下也不能跳過這步。

Dry-run 的責任:把 update 改成 select、用同樣的 WHERE 條件、產出將被修改的資料樣本。Dry-run 結果要包含:影響筆數總計、影響金額或業務值(如果有)、affected tenant / user list 的抽樣、未涵蓋的邊界 case。Dry-run 跟正式修復必須共用 mapping 規則、否則 dry-run 結果無法當審核依據。

規模分級的執行策略:影響筆數會決定執行方式。

  • 單筆到十筆:客服等級的修復、一名工程師執行 + 一名同儕審核 + audit log 即可。
  • 百筆到千筆:要在低流量時段執行、分批跑、每批跑完比對 invariant、發現意外停下。
  • 萬筆以上:當成 production deploy 處理、要有 deploy review、staged rollout(先 1% tenant、再 10%、再全量)、跟 oncall 同步。
  • 跨表 / 跨 service:必須先做跨團隊 review、確認下游依賴(cache、search index、外部 webhook)的處理計畫、不能單一團隊獨自決定。

Impact assessment 的必看欄位:除了筆數、還要看 連帶影響。修復 orders 表會不會觸發 audit trigger 把每筆寫進 audit log 表?會不會觸發 outbox event 把每筆當成新事件對外發布?會不會讓某 tenant 的 metric 一次性異常、誤觸 alert?這些 second-order effect 在 dry-run 階段就要識別、否則修復本身會變成新事故。

Sandbox / staging 驗證:不可逆或大規模修復、先在 staging 跑一次、確認 query plan、執行時間、lock 行為。Production 規模沒辦法在 staging 重現的話、至少要在 production 的某個低風險 tenant / region 先試跑、再擴大。

Approval gate(4-eyes process):超出單筆規模或修復金錢、權限、個資的場合、必須 兩位以上人員 各自看過 dry-run 結果再簽核。常見實作是:執行者提 PR / ticket 帶 dry-run output、reviewer 簽核後才能執行、執行後產出 audit log 帶兩人簽核紀錄。Reviewer 的責任不是橡皮圖章、是獨立驗證 dry-run 結果跟 incident 描述一致。

Repair Patterns

實務上常見的 repair pattern:

Pattern 1:條件式 UPDATE

最簡單也最安全的修復。

1UPDATE orders
2SET status = 'paid'
3WHERE id = 12345
4  AND status = 'pending'
5  AND payment_id = 'abc';

AND 條件確保只在 當前狀態符合預期 時才改、避免 race condition。

Pattern 2:批次修復 + 節流

大量資料修復、必須節流避免影響 production。

1-- 每批 100 筆、間隔 1 秒
2UPDATE orders SET status = 'fixed'
3WHERE status = 'broken'
4  AND id IN (SELECT id FROM orders WHERE status = 'broken' LIMIT 100);

對應 Backfill 卡片 — backfill 跟 batch repair 是同類技術。

Pattern 3:補事件 / 補 webhook

外部副作用漏做時、補發事件。

  • 必須帶 idempotency key(third-party 才能去重)
  • 紀錄補發原因(incident report 連結)
  • 注意:補發前確認 third-party 是否真的沒收到

Pattern 4:重建 derived state

cache 跟 search index 是 derived state、出錯通常 砍掉重建

  • 不是直接修 cache value、是 invalidate 讓下次 read 重算
  • 大規模重建用 batch job 跑、避免 thundering herd
  • 對應 9.C25 Tubi feature store 重建模式

Pattern 5:Point-in-time Recovery

當資料 損毀且無法重建 時、靠 backup recovery。

  • PostgreSQL:WAL + base backup → PITR
  • MySQL:binlog + snapshot → PITR
  • Aurora:cluster snapshot + continuous backup
  • 注意:recovery 期間可能要 整個 DB restore、影響範圍大

Repair Runbook

Repair runbook 的責任是讓資料修復可重複執行、並降低對當下工程師記憶的依賴。最小 runbook 需要包含:

  1. 差異查詢與 query link
  2. 影響範圍與 tenant / region / time range
  3. 修復方式與 dry-run 結果
  4. 審核 owner 與執行 owner
  5. rollback condition 與後續 validation query

runbook 要和 validation query 共用語意。若查詢與修復程式用不同 mapping 規則、修復結果就難以被同一份 evidence 驗證。

Audit 與權限邊界

Data repair 常常需要高權限、因此必須接到 audit 與資料保護邊界。修復個資、付款、權限或方案資料時、要保留操作者、審核者、查詢範圍、寫入範圍與修復前後樣本。

Audit log 必要欄位

  • timestamp(操作時間)
  • actor(誰執行)
  • reviewer(誰審核、如果是 4-eyes process)
  • query(執行了什麼 SQL / API call)
  • before / after snapshot(值的變化)
  • reason(為什麼做這次修復、incident ID)
  • rollback path(如何回退)

這裡要接到 7.7 Audit Trail 與 Accountability Boundary。資料修復同時是可靠性、資安與合規問題。

權限分離與憑證時效

修復權限不該是常駐權限。日常開發 / SRE 帳號只該有 read-only、修復需要時才透過 break-glass 流程申請臨時 write 權限。

常見實作:

  • 角色分離:reviewer 跟 executor 是不同帳號、reviewer 不能執行、executor 不能 self-approve。系統強制檢查兩個帳號不同、避免一人偽造另一身分。
  • 時效性憑證:申請 write 權限時帶 expiry(30 分鐘 / 2 小時)、過期自動回收。不是「給了就一直有」、避免遺留高權限帳號變成攻擊面。
  • 範圍限定:申請時要指定哪張表、哪個 tenant / region。粒度不細的話、一次申請就拿到全 production write、超出實際需求。
  • 同步 alert:高權限被啟用要同步發 alert 到 security channel、給 security team reviewer 看見。事後若 audit log 跟 alert 對不上、表示權限被繞過。

對應 Identity Access BoundarySecrets and Machine Credential Governance。修復權限管理跟 incident-time 緊急存取是同一套機制、不該各做各的。

跨服務 / 跨組織的對帳責任

當對帳跨團隊、跨子系統、跨外部 provider 時、責任不清是首要失敗模式。對帳結果在組織邊界 穿越 時、要明確標記每段的 owner、否則 mismatch 出現後、所有相關方都會說「不是我們的問題」。

跨服務對帳的責任切分

  • 資料 owner:誰擁有那張表 / 那組欄位、誰負責解釋為何資料長那樣。資料 owner 通常是寫入該表的服務團隊。
  • 對帳作業 owner:誰負責定義 reconciliation query、跑、看結果。可能跟資料 owner 是不同人(例如平台團隊跑對帳、業務團隊擁有資料)。
  • 差異處理 owner:mismatch 出現後、誰負責決定修復策略。通常跟資料 owner 一致、但跨團隊 mismatch 要先約定誰主導。
  • 修復執行 owner:實際下 SQL / call API 的人。可能跟差異處理 owner 不同(後者決策、前者執行)。

四個 owner 在簡單場景可以是同一人、在複雜跨團隊場景必須清楚分派。AGENTS.md 規範優先序段的「明確 owner」原則在這裡指的是 對每一段流程 都有人能簽收、不是只指對帳這件事整體有 owner。

跨組織對帳的特殊問題:跟外部 provider(金流、物流、SaaS supplier)對帳時、對方不見得會接受你的對帳結果、也不見得會給差異列表。常見處理:

  • 自己跑兩份對帳:A vs provider report(每天)、A vs provider API(即時抽樣)、兩份結果不同代表 provider report 本身有問題。
  • 約定差異仲裁流程:簽 SLA 時就寫清楚、mismatch 出現後雙方各保留多久的資料、誰先給對方檢視。
  • 不能依賴 provider 修:金流 provider 通常只負責對帳、不負責修你的 DB。修復永遠是你方責任。

跟 Backup / PITR 整合

備份的 權限獨立性attack surface 屬於 1.5 Red Team 備份段 — 本段聚焦 recovery 角度的資料修復責任。兩者互補:1.5 解決「備份本身怎麼防被攻擊」、本段解決「事故後怎麼用備份回復」。

當修復必須跨越「point in time」時、需要 backup 配合。

Snapshot-based recovery

  • 整個 cluster 從 N 小時前的 snapshot 還原
  • 影響:所有 其他 資料也回到那個時間點
  • 適合:catastrophic data corruption

PITR(Point-in-Time Recovery)

  • snapshot + WAL / binlog replay 到指定時間
  • 影響:只在指定時間點 stop replay
  • 適合:「3 小時前 admin 誤刪一張表」這類精準回放

Logical backup(mysqldump / pg_dump)

  • 整個 schema + data 的 SQL script
  • 適合:跨環境遷移、特定表回復、小規模修復

Continuous archive

  • WAL / binlog 持續備份到 S3 / GCS
  • 一直可以回放到 任何時間點
  • 對應 9.C24 Genesys 99.999% — 高可用需要快速 PITR

Recovery 時的對抗壓力

PITR / snapshot recovery 不是純技術問題、會在事故當下面對「為了快、要不要跳檢查」的取捨。對應 VMware ESXiArgs 2023 ransomware recovery pressure — 虛擬化平台勒索後、團隊在 營運壓力資料可信度 之間擺盪:snapshot 是否乾淨、回復後資料是否被污染、跳過 integrity check 換 RTO 是否可接受。判讀重點:recovery 流程要事前 演練 過、否則事故當下不知道要 verify 什麼、容易在壓力下接受被污染的 backup。對應 8.5 Incident Decision Log、事故當下的取捨要寫進 decision log。

RTO/RPO 跟業務可接受中斷的對照表

業務可接受中斷時間是 RTO/RPO 的判讀對照基準。RTO(Recovery Time Objective、多久能恢復)跟 RPO(Recovery Point Objective、最多丟多少資料)是技術指標、要對照業務側的可接受上限才能判斷夠不夠。常見錯誤是把 RTO/RPO 訂在「技術上能做到的最佳值」、忽略業務實際的容忍範圍。

對應 Change Healthcare 2024 — 「定義核心流程的 RTO / RPO、讓資料修復時間跟業務可接受中斷時間明示對照、不藏在直覺」。事故當下發現「DB 能 2 小時恢復、但業務只能容忍 30 分鐘中斷」、來不及補救。

對照表設計

業務流程RTO(技術)業務可接受中斷落差處理
用戶登入30 分鐘5 分鐘加 standby region failover
訂單寫入1 小時30 分鐘加 outbox + replay
報表查詢4 小時1 天RTO 充裕、不需投資
對帳 batch8 小時3 天RTO 充裕
付款1 小時0(不能停)必須 active-active

關鍵情境延伸

  • 付款(必須 active-active):業務可接受中斷為 0、單一 region failover 都不能用(failover 期間用戶看到失敗)、必須多 region 同時寫入、靠 Aurora DSQL / Spanner / Cosmos DB multi-region write 撐。設計權衡是 跨 region 寫入延遲對帳一致性的特殊處理(同一筆款項可能在兩個 region 各被處理一次、要靠 idempotency key 去重)。詳見 1.11 全球分散式 OLTP
  • 訂單寫入(outbox + replay):30 分鐘容忍區間夠用 outbox pattern — 訂單寫進 DB 同步寫進 outbox table、async worker 把 outbox event 推下游。即使下游中斷、訂單本身已落地、event 可在恢復後 replay。設計權衡是 outbox table 的儲存成本跟 replay 邏輯的冪等性、跟 03 訊息佇列模組 的 outbox pattern 整合。
  • 用戶登入(standby region failover):5 分鐘容忍意味 自動 failover 必須在這時間內完成、人類介入做不到、要靠 DNS health check + Route 53 / Cloudflare 自動切流。權衡是 standby region 平時付閒置成本、跟 active-active 比、便宜但 failover 時有 1-3 分鐘延遲跟 cache miss。

落差是 投資訊號、不是「忽略它」。RTO > 業務容忍時、要嘛降 RTO(加 HA / DR 投資)、要嘛跟業務協商提高容忍(通常不接受)。

判讀重點:對照表要每年 review。業務模式變了(例如從 B2C 變 B2B 客服 SaaS)、容忍時間會大幅縮短、RTO 必須跟著降。

事故角色預定義

DB 事故當下、資安處置業務連續性處置分軌並行、不是線性執行。這要求事先有 dual-track IC(Incident Command)角色、不是事故當下臨時拉人。

對應 Change Healthcare 2024 — 「技術處置與業務處置分軌並行的前提是事先有 dual-track IC 角色」。沒事先定義、事故當下會出現「資安 team 在隔離系統、business team 在喊客戶等不及」、兩條軌道互相干擾。

Dual-track IC 角色定義(以下為通用 IC 模型、非案例直接揭露;具體角色細分視組織規模調整):

軌道角色責任
技術軌道Tech IC漏洞修補、系統恢復、技術決策(rollback / restart 等)
業務軌道Business IC客戶溝通、降級流程啟動、合規通報、業務 fallback
協調軌道Overall IC兩條軌道協調、跨軌道決策、對外發言
資料軌道Data IC資料完整性驗證、修復決策、audit chain
Comms 軌道Communications Lead內部通報、外部公告、media 應對

Overall IC 跟一般技術 IC 的差異:一般 IC 主要在技術軌道內決策(要不要 rollback、要不要重啟);Overall IC 額外承擔 跨軌道仲裁 責任 — 當 Tech IC 想停服務止血、Business IC 想保服務維持收入、兩者衝突時、由 Overall IC 拍板。這個角色需要對技術跟業務都有足夠理解、不能只懂一邊;通常由高階工程主管或 CTO/VP Eng 兼任、不是輪值的 oncall。

Data IC 的特殊角色:跟其他軌道相比、Data IC 的決策時間軸最長 — 技術修復可能 1 小時完成、但 資料是否被污染、要不要 PITR、PITR 到哪個時間點 可能要 24-72 小時驗證。Data IC 不能被 Tech IC 跟 Business IC 的「快快上線」壓力推動、必須有獨立判斷權。實務上常見的失誤是讓 Tech IC 兼任 Data IC、結果為了 RTO 跳過 integrity check、事後發現資料污染擴大。

事先準備

  • Primary + backup 雙人配置:每個角色都要有 primary + backup、避免單人不可用(休假、生病、被另一事故占住)讓事故當下卡住。實務上要有 指定流程 而非「臨時找誰」、避免事故當下浪費 30 分鐘喬人。
  • 責任寫進 runbook:runbook 要列出每個角色該做什麼決策、不該做什麼決策(避免越權)。事故當下查職位、會在最壓力大的時候做組織決策、出錯機會高。
  • 定期 tabletop 演練:演練的重點不是「技術修復對不對」、是「角色交接是否流暢」。Overall IC 跟 Tech IC 之間的權限邊界、Data IC 何時介入、Comms Lead 何時對外發言、都要在演練中試出來。
  • 跨時區 follow-the-sun 輪值:B2B SaaS 跟全球業務、事故不分時區、要有 24/7 覆蓋。單一時區團隊在事故發生在凌晨時、人力不足或反應慢、會放大事故代價。

判讀重點:DB 事故不只是技術事件、會成為 跨多軌道 的事件。角色預定義是組織能力、不是技術能力、但缺它會放大技術事故的代價。

對應 8.5 Incident Decision Log7.13 Security Routing — 角色預定義是這些跨模組工作的前置。

Evidence Handoff

資料修復的 evidence handoff 要能支援 release gate 與 incident review。

欄位內容
Sourcereconciliation query、provider report、audit log
Time range差異發生窗口與修復窗口
Query linkmismatch sample、修復前後驗證
Ownerdata owner、service owner、reviewer
Data quality抽樣覆蓋率、延遲、未覆蓋資料
Known gap尚未確認的 provider callback、低流量 tenant

這份 handoff 要進入 4.20 Observability Evidence Package8.22 Incident Evidence Write-back

判讀訊號

訊號判讀重點對應動作
對帳差異率持續上升上游邏輯有 bug、或時間窗對齊問題修上游 + 確認對帳時間窗
同筆資料對帳 run-to-run 結果不同對帳 query 沒處理 in-flight 資料邊界排除最近 N 分鐘、或允許收斂多跑幾次
修復後不一致再次出現沒修根因、只修了 symptom找根因、增加 invariant check
修復影響超出預期範圍mapping 規則錯誤、二次污染立即停止修復、回退
修復沒 dry-run 直接執行流程違規、事後無法佐證影響範圍事後 audit、把 dry-run 列入 gate
Recovery 後 derived state 仍錯重建 derived 時 source 還沒修先修 source、再重建 derived
Audit log 缺欄位事故時無法追究、難 rollback補 audit schema、加 reviewer 欄位
高權限帳號在非 incident 時段啟用可能誤用或攻擊面、break-glass 沒回收立刻檢查 audit log、回收憑證
跨服務 mismatch、各方都推卸對帳 owner 沒分派、責任空白補資料 owner / 對帳 owner / 執行 owner
anomaly alert 跟對帳 mismatch 混報兩種訊號性質不同、reviewer 無法判讀拆 dashboard、deterministic 跟 statistical 分開

常見誤區

把對帳當成「定期 batch job」、不關心 當下不一致。實時對帳跟 batch 對帳是 不同工具、不能互相替代。

把資料修復當成「一個工程師動手改」、沒 audit、沒 review、沒 rollback。資料修復本質是 production 操作、跟 deploy 同等嚴格。

把 PITR 當成 常規修復工具。PITR 影響大、適合 catastrophic event、不適合單筆資料修復。

把 derived state 不一致跟 canonical state 不一致 混在一起 處理。derived 是 再生 的、canonical 是 永久 的、處理流程完全不同。

把對帳結果跟 anomaly detection 結果放同一份報告。前者是 deterministic、後者是 statistical、混報會讓 incident reviewer 無法判斷必修跟可疑。對帳 mismatch 要有獨立追蹤面板、anomaly 走另一條路徑。

跳過 dry-run、直接 update。即使單筆修復、也要先 select 看到當前 row、確認 WHERE 條件命中預期。incident 壓力下尤其容易跳、結果反而把單點問題擴成批次污染。

把修復權限當常駐權限發放。長期 write 權限放在工程師帳號上、會在事故無關時段被誤用、且事後無法區分「正常工作」跟「非法修復」。修復權限要時效化、申請即用即收。

案例對照

案例reconciliation 重點
9.C20 Zomatomigration 期間用 shadow read 持續對帳
9.C4 DraftKings體育博彩 ledger、結算後對帳
9.C14 Standard Chartered跨市場銀行、每市場獨立對帳

實體服務討論承接點

實體資料庫文章要承接本篇的 reconciliation 與 data repair 責任。PostgreSQL、MySQL、MSSQL 或其他資料庫的差異、應放在它們如何產生 validation query、保留 audit trail、支援 point-in-time recovery、處理 replica lag 與控制修復權限。

若服務需要高頻對帳、後續文章要比較查詢成本、索引策略與 replica 讀取延遲。若服務需要高風險資料修復、後續文章要比較 transaction log、backup/restore、row-level audit 與權限分離。若服務需要跨系統補償、後續文章要把資料庫能力接到 queue replay 與 incident decision log。

跨模組路由

  1. 與 1.3 的交接:transaction boundary 決定哪些不一致可避免 — Transaction Boundary
  2. 與 1.5 的交接:audit 跟 access control — Red Team Data Layer
  3. 與 1.7 的交接:migration 後驗證 — Schema Migration Rollout Evidence
  4. 與 1.8 的交接:canonical vs derived 是修復的前置 — State Ownership
  5. 與 3.8 的交接:消息重放與補事件 — Queue Consumer Retry / Replay
  6. 與 4.20 的交接:evidence handoff — Observability Evidence Package
  7. 與 7.7 的交接:audit trail — Audit Trail and Accountability Boundary
  8. 與 8.22 的交接:incident evidence write-back — Incident Evidence Write-back

下一步路由

要處理 migration 造成的資料差異、接著讀 1.7 Schema Migration Rollout 證據。要處理事件漏發造成的副作用修復、接著讀 3.8 Queue Consumer Retry 與 Replay Handoff。要設計跨服務 reconciliation 跟 saga compensation、接著讀 1.3 Transaction Boundary 的 Saga 段。