跨多個節點的交易,要嘛全部提交、要嘛全部中止,不能部分成功。單機靠儲存引擎寫 WAL 就能原子提交;多節點就得有協定來協調——這就是原子提交問題,經典解是兩階段提交 (2PC)。
🧠 Core Ideas
TIP
2PC 引入一個協調者 (coordinator),分兩階段:prepare(問所有參與者「你能提交嗎」)→ commit/abort(收齊 yes 才提交)。參與者投 yes 是不可撤回的承諾;協調者把決定寫入磁碟那一刻是提交點。這兩個「不可逆時刻」共同保證原子性。
- 比喻:2PC 像婚禮——說「我願意」之前可隨時反悔;一旦說了,即使之後暈倒沒聽到宣佈,婚也已經成立。
- 別和第七章的兩階段鎖 (2PL) 混淆——完全不同的東西。
⚖️ 致命弱點:協調者故障
疑問狀態 (In-Doubt) 與阻塞
- 若協調者在「參與者都投 yes」之後、「發出 commit/abort」之前當機,參與者陷入疑問狀態:
- 不能單方面中止(別人可能已收到 commit 提交了)。
- 不能單方面提交(別人可能已收到 abort 中止了)。
- 問別的參與者也沒用(大家一樣不知道)。
- 唯一解法:等協調者恢復。等待期間交易持有的行級鎖不釋放,阻塞所有想碰這些行的交易——故障可能波及整個資料庫。
3PC 為什麼救不了
- 三階段提交加逾時讓參與者能自行決定、避免阻塞,但它假設網路延遲有界、節點回應時間有界。
- 真實網路延遲不可預測(GC 暫停、擁塞都會讓節點「看起來像掛了」),這假設不成立,3PC 可能做出不安全決定。所以 2PC 仍是主流。
⚖️ XA 與異質分散式交易
XA 標準與它的實務問題
- XA(eXtended Architecture)是跨異質技術(不同廠商 DB、DB 與訊息代理間)實作 2PC 的標準 C API。PostgreSQL、MySQL、多數訊息代理都支援。
- 問題:協調者是單點故障且有狀態(要持久化交易日誌,不能無狀態水平擴展);相容性限制了各 DB 的高階最佳化;諷刺的是——它為容錯而生,故障時的鎖定效應反而把單一系統的故障擴散到所有參與系統。
- 許多雲端服務因此乾脆不實作 XA。
微服務的替代:Saga
- 微服務世界常放棄跨服務的 2PC,改用 Saga:把長交易拆成一串本地交易,每步失敗就跑補償交易 (compensating transaction) 回滾已完成的步驟。
- 代價是只有最終一致、沒有隔離性,要自己處理中間狀態——但避開了 2PC 的跨服務鎖定與阻塞。
🔑 Takeaways
- 原子提交=跨節點要嘛全提交要嘛全中止;2PC 是經典解(prepare → commit,兩個不可逆時刻)。
- 2PC 的死穴是協調者故障 → 疑問狀態 → 持鎖阻塞;3PC 因網路假設不實際而不被採用。
- 2PC 不是容錯共識——它不滿足終止性;需要容錯就用 共識演算法。
- 跨服務時優先考慮 Saga + 冪等,而非把 2PC 硬拉進微服務。
No notes yet — jot your takeaways or Q&A here.