分佈式事務兩階段提交數據庫
在分佈式事務中,須要協調全部分佈式原子事務參與者,並決定提交或回滾分佈式事務,所以採用兩階段提交協議:app
第一階段爲請求階段或表決階段,事務協調者通知事務參與者準備提交或取消事務,而後進入表決過程,事務參與者將表決結果告知協調者是否贊成提交事務;分佈式
第二階段是提交階段,協調者收集到全部參與者的表決結果,當且僅當全部表決者都贊成提交事務,事務協調者才通知全部參與者提交事務,不然通知參與者回滾事務。
分佈式事務首選須要確保各個參與者上面的事務都能進行提交,才能在全部參與者上提交,所以須要兩個階段提交。函數
MySQL事務兩階段提交spa
在MySQL事務中,因爲事務涉及到存儲引擎層和MySQL服務層以及binlog的寫入,所以MySQL採用兩階段提交協議來處理事務。日誌
先在事務涉及到的全部存儲引擎上進行prepare成功後,調用方法將相關數據寫到binlog,而後再調用存儲引擎的commit完成事務提交。code
Binlog在2PC中充當事務協調者的角色,因爲Binlog來通知InnoDB引擎來執行Prepare,Commit或者Rollback操做。orm
在大部分關係性數據庫中,爲保證事務ACID特性,經過會要求事務在提交前,先將事務日誌寫入到磁盤固化即採用WAL預先寫日誌機制,但在MySQL Innodb事務引擎中,並無遵循WAL預先寫日誌機制,所以可能存在數據不一致問題。
在MySQL Innodb處理事務的函數lock_trx_release_locks中,有如下注釋:blog
/* The following assignment makes the transaction committed in memory and makes its changes to data visible to other transactions. NOTE that there is a small discrepancy from the strict formal visibility rules here: a human user of the database can see modifications made by another transaction T even before the necessary log segment has been flushed to the disk. If the database happens to crash before the flush, the user has seen modifications from T which will never be a committed transaction. However, any transaction T2 which sees the modifications of the committing transaction T, and which also itself makes modifications to the database, will get an lsn larger than the committing transaction T. In the case where the log flush fails, and T never gets committed, also T2 will never get committed. */
事務T1先在內存中進行提交,此時事務日誌還沒有刷新到事務日誌文件中,但事務所在修改對其餘事務T2可見,因爲T2訪問T1數據,所以T2的LSN確定大於T1的LSN,若是在T1的事務日誌被刷新到日誌文件以前發生宕機,在系統恢復時,因爲事務T1由於沒有預寫日誌而被回滾,當T2由於LSN大於T1且T1發生回滾,所以T1的事務也會發生回滾。
在刷新日誌到日誌文件時,T2的LSN大於T1的LSN,若是T1的事務日誌未刷新到磁盤,那麼T2的事務日誌確定不會被刷新到磁盤。事務