引言
在分布式系統的事務處理中,如何保障跨節點數據操作的一致性始終是核心挑戰。經典的兩階段提交協議(2PC)通過準備階段與提交階段的協調機制,以同步決策模式確保事務原子性。其改進版本三階段提交協議(3PC)通過增加預提交階段和超時機制,旨在解決2PC的阻塞風險。值得注意的是,MySQL數據庫的Binlog與InnoDB引擎通過內部兩階段提交機制,實現了事務日志與存儲引擎狀態的一致性保障。
兩階段提交
第一階段:準備階段,第二階段:提交階段。將提議的節點稱為協調者(coordinator),其他參與決議節點稱為參與者。
第一階段:協調者發起一個提議,分別問詢各參與者是否接受,參與者如果認為自己可以提交事務,它們將執行所有必要的操作但不提交(記錄redo log,undo log),正常執行返回Yes,否則返回No。
第二階段:協調者根據參與者的反饋,提交或回滾事務,如果參與者全部同意則提交,只要有一個參與者不同意就回滾。
MySQL的兩階段提交
當在 InnoDB 中執行事務,并且啟用了 Binlog 時,提交事務時會觸發兩階段提交過程。
- 當有數據需要更新的時候,InnoDB 引擎就會先把記錄寫到redo log buffer以及binlog cache(線程獨有的),并更新內存(chang buffer),這個時候更新就算完成了。
-
- 如果是唯一索引更新操作會寫入到redo log,普通索引的更新操作會先寫入到change buffer,在合適的時機merge到redo log。
- 事務提交時寫入 redo log 并變成 prepare 狀態。(一階段)
- 再把 binlog cache 寫到 binlog 文件中,最后 redo log 變成 commit 狀態。(二階段)
三階段提交
三階段提交,是二階段提交(2PC)的改進版本。與兩階段提交不同的是,三階段提交有兩個改動點。
- 引入超時機制。同時在協調者和參與者中都引入超時機制。
- 在第一階段和第二階段中插入一個準備階段。保證了在最后提交階段之前各參與節點的狀態是一致的。也就是說,除了引入超時機制之外,3PC把2PC的準備階段再次一分為二,這樣三階段提交就有CanCommit、PreCommit、DoCommit三個階段。
第一階段CanCommit:事務協調者向所有參與者發送詢問消息(CanCommit),詢問它們是否能夠提交事務。
第二階段PreCommit:協調者根據參與者的反應情況來決定是否可以進行事務的PreCommit操作。
- 參與者如果認為自己可以提交事務,它們將執行所有必要的操作但不提交(記錄redo log,undo log),并鎖定資源,然后向協調者發送準備提交(PreCommit)的響應。
- 協調者等待來自所有參與者的響應。如果收到所有參與者的肯定回復,它將進入提交階段;如果任何一個參與者否定或者等待超時,它將進入中止階段。
第三階段DoCommit:
- 如果進入提交階段,協調者向所有參與者發送提交消息(doCommit),指示它們正式提交事務。
- 如果進入中止階段,協調者向所有參與者發送中止消息(abort),指示它們回滾事務。
兩階段提交和三階段提交區別?
阻塞性問題
兩階段提交會存在阻塞性問題,如果參與者都已經執行一階段,但協調者崩潰的話,參與者會進入等待狀態,直到協調者恢復并做出決定。
三階段提交利用超時機制解決阻塞性問題,參與者在預提交階段后等待協調者的最終提交請求時,如果超過超時時間可以選擇回滾事務。
感謝您的閱讀!如果文章中有任何問題或不足之處,歡迎及時指出,您的反饋將幫助我不斷改進與完善。期待與您共同探討技術,共同進步!