這篇文章帶大家了解MySQL的兩階段提交的機制,介紹一下redo log和bin log,看看他們兩者是如何配合完成兩階段提交的,希望對大家有幫助!
MySQL透過兩階段提交的機制,保證了redo log和bin log的邏輯一致性,進而保證了資料的不遺失以及主從函式庫的資料一致。
而說起兩階段提交,就得先介紹一下redo log和bin log。
redo log即重做日誌,是InnoDB引擎特有的一種日誌(有的面試官常常問到這一點)。
redo log主要做什麼呢?
以更新數據為例,我們知道,MySQL的數據是儲存在磁碟上的,如果每一次更新數據,都去磁碟尋址找到要更新的數據,進行更新操作的話,這個IO成本是非常高的。
如果是固態硬碟還好,如果是機械式硬碟,那麼MySQL的更新效能根本無法滿足我們的業務需求。
所以,MySQL採用了一種叫做WAL的技術,Write-Ahead Logging。
當更新資料時,將更新操作(即某個資料頁上做了什麼修改)先寫到redo log裡面,然後更新內存,這個更新操作就算完成了。 MySQL會在伺服器空閒的時候,把redo log的作業記錄刷新到磁碟裡,以保持資料的一致性。
要注意的是,redo log雖然也是磁碟上的文件,但由於操作是順序寫,所以效能是非常高的。
當然了,redo log也是有大小上限的,不可能無限制的寫入。
以上圖為例,配置了4個redo log,write pos就是代表目前記錄寫到什麼位置了,而check point表示一個推進點,它會不斷的前移,做擦除資料的操作,以確保redo log可以不斷的寫入。
當然,在擦除資料之前,會把redo log的記錄刷新到磁碟。
透過redo log,可以保證即使MySQL發生異常重啟,資料也不會遺失(因為redo log是實體日誌,可以進行重播),這個特性就叫做crash-safe。
bin log是MySQL Server提供的一種日誌,叫做歸檔日誌,所有引擎都可以使用bin log。
那bin log和redo log的差別是什麼呢?
1,這兩種日誌的提供者不同:bin log是由MySQL Server提供的,redo log是InnoDB引擎特有的。
2,redo log主要記錄的是某個資料頁做了什麼修改,bin log記錄的是語句的原始邏輯,例如更新了某一行的某個欄位。
3,redo log是循環寫的,資料會被覆寫。 bin log是追加寫,一個文件寫滿,就寫下一個文件。
介紹完了redo log和bin log,我們再看一下他們兩者是如何配合完成兩階段提交的。
上圖就是更新資料的流程,可以看到,在更新一條資料之前,MySQL會先將資料載入到內存,然後更新內存,開始寫redo log。
此時,redo log處於prepare狀態,等到bin log寫完之後,再提交事務,這一記錄的更新操作就算完成了。
redo log prepare -> 寫bin log -> redo log commit,這個流程就叫做兩階段提交。
下面我們分析一下,採用兩階段提交的好處。
情境一,redo log處於prepare狀態時,如果寫bin log失敗了,那麼更新失敗,此時redo log沒有commit,bin log也沒有記錄,兩者的狀態是一致的,沒有問題。
情境二,redo log處於prepare狀態時,寫bin log成功,但是當機導致commit失敗了。此時bin log產生了記錄,redo log沒有寫入成功,資料暫時不一致。
但不用擔心,當MySQL重新啟動時,會檢查redo log中處於prepare狀態的記錄。在redo log中,記錄了一個叫做XID的字段,這個字段在bin log中也有記錄,MySQL會透過這個XID,如果在bin log中找到了,那麼就commit這個redo log,如果沒有找到,說明bin log其實沒有寫成功,就放棄提交。
透過這樣的機制,保證了redo log和bin log的一致性。
之所以MySQL中既存在redo log,又存在bin log,這是因為bin log是MySQL Server提供的一種歸檔日誌,本身並不具備crash-safe能力。而redo log本身不具備歸檔能力,他是一種循環寫的日誌。
MySQL透過將這兩個日誌整合起來,並透過兩階段提交的機制,保證了資料的一致性。
寫文不易,感謝您的按讚和追蹤。
【相關推薦:mysql影片教學】
#以上是面試官:聊聊MySQL的兩階段提交的機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!