MySQL中的兩階段(2PC)提交


介紹MySQL兩階段提交之前,先介紹一下Redo Log 和 Binlog

redo log:

在MySQL中如果每次更新都需要寫進磁盤,然后磁盤也要找到那條記錄,然后在更新,整個過程IO成本、查找成本都很高,因此引入了redo log。這里用到了MySQL中的WAL技術,Write-Ahead Logging,它的關鍵點是先寫日志,再寫磁盤。

具體來說就是,當需要更新一條數據時,InnoDB引擎會先把記錄寫進redo log中,並更新內存,這個時候就算完成。同時InnoDB會在空閑的時候將這個記錄寫進磁盤。

redo log是固定大小,從頭開始寫入,寫到尾部就又回到開頭循環寫。指針write pos記錄當前位置,checkpoint是要擦出的位置,當兩者之間有空余位置,即可繼續更新,當滿了后,就需要checkpoint擦除數據后繼續更新。

有了redo log,InnoDB就可以保證數據庫即使發生異常重啟,之前提交的記錄也不會丟失。

 

binlog:

MySQL有兩塊組成:server層,主要負責MySQL功能層面的事情;引擎層,負責存儲相關的事情,redo log 就是InnoDB特有的日志。而server層也有自己的日志,就是binlog。

 

redo log 和 binlog的區別:

  • redo log是InnoDB特有的,binlog是MySQL的server層實現的,所有引擎都有
  • redo log是物理日志,記錄的是“在某個數據頁上做了什么操作”;binlog是邏輯日志,記錄的是這個語句的原始邏輯,比如“給ID=2這一行的c字段加1”。
  • redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的,“追加寫”是指binlog文件寫到一定大小后會切換到下一個,並不會覆蓋以前的日志。

在更新一條數據時,會先執行,然后寫入redo log中,redo log進入prepare狀態,執行器執行完成。然后執行器生成這個操作的binlog,並寫入磁盤。然后提交commit,更新完成。

 

兩階段提交:

redo log 和binlog是兩個獨立的邏輯,如果不用兩階段提交,那么就會先寫redo log,后寫binlog,或者反過來的順序寫。看看會有什么問題。把數據0更新到1

  • 先寫redo log,后binlog:假設redo log在寫完后,系統崩潰了,binlog還未完成,因為redo log寫完了,數據依然可以恢復到之前的狀態。但是當我們需要使用binlog來恢復臨時庫時,binlog中並沒有這條記錄,那么恢復后的值就會和之前的不同,本應該是1,但是結果是0。
  • 先binlog,后redo log:同樣的假設,binlog寫完,系統崩潰,redo log未完成。這個時候系統崩潰,由於沒有完成redo log,那么就不能恢復到執行結果后的數據,依然是沒有執行這條語句前的數,但是binlog已經寫入,那么同樣使用binlog恢復臨時表時,數據就會之前的不同。本應該是0,但是結果是1.

因此兩階段提交保證了兩個日志的一致性,要么都成功,要么都失敗。可以對照zookeeper的2PC理解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM