變更資料擷取 (CDC)

★★★★Reviewed

FromDDIA

📚 From the Books

變更資料擷取 (CDC)Batch & Stream

CDC 把資料庫的每一筆變更(insert/update/delete)擷取成一條有序的事件流。核心觀念是:讓某個資料庫成為唯一的 source of truth,所有其他系統(搜尋索引、快取、倉儲)都只是這條變更流的衍生狀態。

🧠 Intuition

TIP

不要在應用層「雙寫」——寫完 DB 又寫一次 ES。改成:只寫 DB,然後讀 DB 的 replication log,把變更廣播出去。replication log 本來就是給 follower 用的,CDC 只是多接一個 consumer。

⚖️ Tradeoffs

為什麼不用應用層雙寫 (dual write)
  • 雙寫=應用同時寫 DB 和 ES。問題是兩次寫入沒有原子性:一個成功一個失敗,兩邊就永久分歧。
  • 還有並發競態:兩個請求對同一筆的兩次寫入,到達 DB 和 ES 的順序可能相反,最後狀態不一致。
  • CDC 從根本避開:只有一個寫入點(DB),順序由 replication log 唯一決定,下游照序重放永遠收斂。
初始快照 (snapshot) + 增量 (log)
  • replication log 通常只保留近期(會被截斷),無法回溯到資料庫誕生。
  • 新接一個 consumer(如新建索引)要先做一次一致性快照,記下對應的 log 位置 (LSN/GTID),再從該位置接增量。
  • Debezium 等工具把「快照 → 無縫切換到增量」自動化,是 CDC 上線最容易出錯的環節。
Log compaction — 讓流也能當完整資料集
  • 一般 log 會截斷舊紀錄,重放不到全貌。log compaction(Kafka)只保留每個 key 的最新值,刪除被覆蓋的舊版。
  • 效果:壓實後的 log 等價於「整個資料庫的當前快照」,新 consumer 可直接從頭重放重建完整狀態,不必另做 snapshot。
  • delete 用 tombstone(value 為 null)表示,compaction 後該 key 徹底消失。
CDC vs Event Sourcing
  • 兩者都「以不可變事件流為中心」,但抽象層次不同。
  • CDC:事件是低階的資料庫狀態變更(這列被改成這樣),由 DB 自動產生,應用無感。
  • Event Sourcing:事件是高階的領域意圖(「使用者取消了訂單」),由應用主動寫入,當前狀態是事件重播的結果。
  • 取捨:CDC 改造成本低(接 binlog 即可)但事件語意貧乏;event sourcing 表達力強、可重建任意視圖,但要重新設計寫入模型。

🔑 Takeaways

✍️ My Notes

2026-07-01

  • Q: CDC 和 event sourcing 都在講「不可變事件流」,到底差在哪?
  • A: 差在事件的語意層次與誰產生它。CDC 的事件是資料庫替你產生的低階變更——「orders 表第 42 列的 status 欄從 ‘paid’ 變成 ‘cancelled’」,它不知道業務為什麼這樣改,只忠實記錄結果;好處是接上 binlog 就有、應用零改動。Event sourcing 的事件是應用主動寫的高階意圖——「OrderCancelled,原因:客戶要求」,當前狀態是把這些事件重播算出來的;好處是事件保留了「為什麼」,能重建任何你事後才想要的視圖,但代價是整個寫入路徑要圍繞事件重新設計。一句話:CDC 是把既有 DB 的副產物拿來用,event sourcing 是把事件當成唯一的真相來源從頭設計。

📖 Further Reading

🔗 Dive Deeper