1 redo log 和 binlog 的區別
- redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實現的,所有引擎都可以使用。
- redo log 是物理日誌,記錄的是“在某個資料頁上做了什麼修改,實現 crash-safe,即使資料庫發生異常重啟,之前提交的記錄都不會丟失。而 binlog 是邏輯日誌,記錄的是寫入性操作(不包括查詢)資訊,比如“給 ID=5 這一行的 c 欄位加 1 ”,保證資料的一致性。
- redo log 是迴圈寫的,空間固定會用完;binlog 是可以追加寫入的。“追加寫”是指 binlog 檔案寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。
-
binlog 僅在事務提交時記錄,並且對於每一個事務,僅包含對應事務的一個日誌。而對於 redo log,由於其記錄的是物理操作日誌,因此每個事務對應多個日誌條目。
2 redo log 和 binlog 的相同點
redo log 和 binlog 落盤的步驟是差不多的,都分為三部分:
- 將日誌寫入 log buffer 和 binlog cache。
- 將上述的內容寫入作業系統的 file system page cache。
- 由作業系統將檔案快取中的資料寫入到磁碟中。
3 redo log 的兩階段提交
對資料進行修改後,需要寫入 redo log 和 binlog,那麼這勢必存在一個先後順序,假設執行過程中寫完 redo log 日誌後,binlog 日誌寫期間發生了異常,會發生什麼?
由於 binlog 沒寫完就異常,這時候 binlog 裡面沒有對應的修改記錄。從機用 binlog 日誌更新資料時,就會少這次更新,而主機用 redo log 日志恢復,會導致最終資料不一致的情況。
為了解決兩份日誌之間的邏輯一致問題,InnoDB 使用兩階段提交方案,將 redo log 的寫入拆成 prepare 和 commit 兩階段。
在資料庫發生崩潰重啟後,它將會去檢查 redo log:
- 如果 redo log 有 commit 標識則直接提交事務。
- 如果 redo log 沒有 commit 標識且不存在對應的完整 binlog,則回滾事務。redo log 和 binlog 有一個共同的資料欄位,叫XID。崩潰恢復的時候,redo log 會拿著 XID 去 binlog 找對應的事務。
- 如果 redo log 沒有 commit 標識且存在對應的完整 binlog,說明在 commit 階段發生了崩潰,此時實際上 redo log 和 binlog 都已經完整寫入,可以提交事務。
4 為什麼不能用 binlog 進行崩潰恢復
由於 binlog 記錄的是寫入性操作,如果想用 binlog 來恢復資料,我們必須知道現在得從哪裡開始,因為一條語句多執行幾次會帶來資料上的錯誤。但是 binlog 雖然儲存了所有的歷史操作,但是它沒有標識每條操作是否已經寫入磁碟,所以我們確定從哪開始。
而 redo log 記錄的是資料頁的更改,並且刷盤完成的資料會從 redo log 中刪除。
References: