事務的兩階段提交

爲什麼必須有“兩階段提交”呢?

這是爲了讓兩份日誌(redo log和binlog)之間的邏輯一致。

詳細解釋

用update 語句來做例子。假設當前 ID=2 的行,字段 c 的值是 0,再假設執行 update 語句過程中在寫完第一個日誌後,第二個日誌還沒有寫完期間發生了 crash,會出現什麼情況呢?
1. 先寫 redo log 後寫 binlog
假設在 redo log 寫完,binlog 還沒有寫完的時候, MySQL 進程異常重啓。由於我們前面說過的,redo log 寫完之後,系統即使崩潰,仍然能夠把數據恢復回來,所以恢復後這一行 c 的值是 1。但是由於 binlog 沒寫完就 crash 了,這時候 binlog 裏面就沒有記錄這個語句。因此,之後備份日誌的時候,存起來的 binlog 裏面就沒有這條語句。 然後你會發現,如果需要用這個 binlog 來恢復臨時庫的話,由於這個語句的 binlog 丟失,這個臨時庫就會少了這一次更新,恢復出來的這一行 c 的值就是 0,與原庫的值不同。
2. 先寫 binlog 後寫 redo log
如果在 binlog 寫完之後 crash,由於 redo log 還沒寫, 崩潰恢復以後這個事務無效,所以這一行 c 的值是 0。但是 binlog 裏面已經記錄了“把 c 從 0 改成 1”這個日誌。所以,在之後用 binlog 來恢復的時候就多了一個事務出來,恢復出來的這一行 c 的值就是 1,與原庫的值不同。
 
可以看到,如果不使用“兩階段提交”,那麼數據庫的狀態就有可能和用它的日誌恢復出來的庫的狀態不一致。你可能會說,這個概率是不是很低,平時也沒有什麼動不動就需要恢復臨時庫的場景呀?
其實不是的,不只是誤操作後需要用這個過程來恢復數據。當你需要擴容的時候,也就是需要再多搭建一些備庫來增加系統的讀能力的時候,現在常見的做法也是用全量備份加上應用 binlog 來實現的,這個“不一致”就會導致你的線上出現主從數據庫不一致的情
況。
簡單說,redo log 和 binlog 都可以用於表示事務的提交狀態,而兩階段提交就是讓這兩個狀態保持邏輯上的一致。
發佈了131 篇原創文章 · 獲贊 42 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章