MySQL中binlog和redo log的一致性問題

背景

網易工作期間,因爲應用開發和性能測試的原因,對數據庫寫入比較關注(網易的DDB數據庫也是基於Mysql的)。也讀了一些技術文章,比如如下。binlog和redo log的一致性問題是理解二階段提交特性的一個關鍵。記錄在此。

https://blog.csdn.net/huangjw_806/article/details/100927097
《MySQL技術內幕 InnoDB存儲引擎》----姜承堯 Netease Inc.
在這裏插入圖片描述

在事務提交時利用兩階段提交(內部XA的兩階段提交)很好地解決了上面提到的binlog和redo log的一致性問題:

第一階段:

InnoDB Prepare階段。此時SQL已經成功執行,並生成事務ID(xid)信息及redo和undo的內存日誌。此階段InnoDB會寫事務的redo log,但要注意的是,此時redo log只是記錄了事務的所有操作日誌,並沒有記錄提交(commit)日誌,因此事務此時的狀態爲Prepare。此階段對binlog不會有任何操作。

第二階段:

commit 階段,這個階段又分成兩個步驟。第一步寫binlog(先調用write()將binlog內存日誌數據寫入文件系統緩存,再調用fsync()將binlog文件系統緩存日誌數據永久寫入磁盤);第二步完成事務的提交(commit),此時在redo log中記錄此事務的提交日誌(增加commit 標籤)。

此過程中是先寫redo log再寫binlog的。但需要注意的是,在第一階段並沒有記錄完整的redo log(不包含事務的commit標籤),而是在第二階段記錄完binlog後再寫入redo log的commit 標籤。還要注意的是,在這個過程中是以第二階段中binlog的寫入與否作爲事務是否成功提交的標誌。

此時的崩潰恢復過程如下:

  1. 如果數據庫在記錄此事務的binlog之前和過程中發生crash。數據庫在恢復後認爲此事務並沒有成功提交,則會回滾此事務的操作。與此同時,因爲在binlog中也沒有此事務的記錄,所以從庫也不會有此事務的數據修改。
  2. 如果數據庫在記錄此事務的binlog之後發生crash。此時,即使是redo log中還沒有記錄此事務的commit 標籤,數據庫在恢復後也會認爲此事務提交成功(因爲在上述兩階段過程中,binlog寫入成功就認爲事務成功提交了)。它會掃描最後一個binlog文件,並提取其中的事務ID(xid),InnoDB會將那些狀態爲Prepare的事務(redo log沒有記錄commit 標籤)的xid和Binlog中提取的xid做比較,如果在Binlog中存在,則提交該事務,否則回滾該事務。這也就是說,binlog中記錄的事務,在恢復時都會被認爲是已提交事務,會在redo log中重新寫入commit標誌,並完成此事務的重做(主庫中有此事務的數據修改)。與此同時,因爲在binlog中已經有了此事務的記錄,所有從庫也會有此事務的數據修改。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章