面試官:MySQL Redo Log 和 Binlog 有什么區別?分別用在什么場景?
MySQL 的 Redo Log 和 Binlog 是兩種完全不同、但又緊密協同的日志機制。理解這兩種日志,對理解 MySQL 的事務機制有重要幫助。今天來聊一聊這兩種日志。
1.概念回顧
1.1 兩階段提交
我們知道,分布式事務一般都是使用兩階段提交達到最終一致。比如下圖一個購買商品的案例,用戶下訂單后,訂單服務保存訂單,賬戶服務扣減金額,庫存服務扣減庫存。這三個服務通過兩階段提交,先 prepare,然后 commit 最終實現事務一致性。
圖片
1.2 事務提交
我們再來看一下 MySQL 的邏輯架構,看下圖:
圖片
在 MySQL 邏輯架構中,執行器負責執行具體的 SQL,跟存儲引擎進行交互。
執行器就是兩階段提交的“事務協調者”,事務執行過程如下圖:
圖片
假如我們要執行一條 SQL:
update t set a=10 where id=5;這個 SQL 的執行過程如下:
- 執行器先從存儲引擎拿到 id=5 這一行數據,然后把這一行數據的字段 a 改成 10,再把這行修改后的數據寫入存儲引擎。
- prepare 階段:存儲引擎將這行新數據寫入內存,同時將這行數據的更新操作記錄到 Redo Log ,但不提交事務,然后給執行器返回成功。此時 Redo Log 處于 prepare 狀態。
- 執行器為這行數據的更新操作生成 Binlog 并寫入磁盤,當然,是否刷盤要根據 sync_binlog 配置來決定。
- commit 階段:執行器通知存儲引擎提交事務,存儲引擎把剛剛寫入的 Redo Log 改成提交 commit 狀態,完成事務提交。
2.Redo Log
2.1 介紹
從前面介紹可以看到,Redo Log 是存儲引擎層控制的日志,事實上,Redo Log 是 InnoDB 存儲引擎特有的日志,它是一個物理日志, 記錄了在某個數據頁上做了哪些修改,主要用于崩潰恢復。
Redo Log 的刷盤機制通過下面參數來控制:
innodb_flush_log_at_trx_commit- 0:事務提交時,Redo Log 不會被立刻被寫入磁盤,而是存在緩存中(Redo Log Buffer),InnoDB 后臺日志線程每秒將日志從緩沖區寫入文件系統緩存(Page Cache),然后調用 fsync 落盤。優點是減少了 I/O 操作,提升了性能,缺點是如果 MySQL 服務掛了,或者操作系統宕機,可能丟失 1s 的數據。
- 1:默認值。事務提交時,Redo Log 立即寫入 Page Cache,并調用 fsync 保存磁盤,優點是系統宕機時丟失數據風險小,缺點是磁盤 I/O 操作頻繁,影響性能。
- 2:事務提交時,Redo Log 被直接寫入到 Page Cache,然后依賴操作系統的刷盤機制將 Page Cache 中的日志寫入磁盤,優點是性能好,如果 MySQL 服務掛了,并不會導致數據丟失,只有操作系統宕機,Page Cache 未刷盤的數據才會丟失。
2.2 寫日志
在寫數據時,Redo Log 是循環寫,空間大小固定,寫滿后會覆蓋掉前面的日志。
Redo Log 采用固定大小的文件組,比如下圖文件組配置了 4 個文件,每個文件大小相同,寫滿一個后接著寫下一個,全部寫滿后就清除一部分前面的日志,繼續寫入。write pos 控制當前寫入的位置,check point 控制可以寫入的最后位置,如果兩個點重合了,那就需要清除部分日志,讓 check point 后移。
圖片
2.3 Redo Log 使用場景
崩潰恢復
這是 Redo Log 最根本的用途。它確保了數據庫宕機后,已提交事務的數據不會丟失。Redo Log 基于 WAL (Write-Ahead Logging) 原則,即先寫日志,再寫磁盤。事務提交時,先將修改內容的記錄到 Redo Log,MySQL 宕機重啟后,利用 Redo Log 做崩潰恢復。恢復過程如下。
首先,InnoDB 會檢查數據頁的 LSN (日志序列號),并與 Redo Log 中的 LSN 對比。Redo Log 上 LSN 比數據頁大的就是需要重做的數據。
接著,InnoDB 會掃描 Redo Log 中要恢復的日志,如果日志狀態是 COMMIT,則直接重做。如果日志狀態是 PREPARE,則還要去檢查對應的 Binlog,如果該事務的 Binlog 存在且完整,說明事務已經提交成功,應該重做。如果該事務的 Binlog 不存在或不完整,說明事務應該回滾,Redo Log 日志不進行重做。
圖片
通過這個機制,確保了 Redo Log 和 Binlog 的邏輯一致性:只要 Binlog 寫成功了,數據就一定能夠被恢復;如果 Binlog 沒寫成功,說明事務應該被回滾,數據無需恢復。
優化性能
通過將數據文件隨機寫磁盤轉換為 Redo Log 順序寫磁盤,大大提升了事務執行效率和數據庫整體吞吐量。
3.Binlog
3.1介紹
Binlog 是 MySQL Server 層的日志,所有引擎都可以使用。它是一個邏輯日志,記錄的是數據邏輯的變化(比如插入一條數據),用于主從復制和故障恢復。
跟 Redo Log 寫日志方式不同的是, Binlog 是追加寫,寫滿一個文件后切換到下一個文件寫。
3.2 刷盤時機
MySQL 中 sync_binlog 參數定義了將 Binlog 內容從內存緩沖區同步到磁盤的頻率。
- 0:MySQL 不會主動將 Binlog 內容同步到磁盤,完全依賴文件系統刷盤機制來落盤。這種方式磁盤 I/O 操作較少,性能最好,但存在數據丟失的風險。
- 1:每次事務提交時,都會將 Binlog 內容同步到磁盤。這種方式丟失數據的風險較小,但因為磁盤 I/O 操作多,容易影響數據庫性能。
- N(N>1):每 N 個事務提交后,才會將 Binlog 內容同步到磁盤。這種方式是前兩種方式的折中,既考慮了一定的性能,也兼顧了數據的安全性。
3.3 Binlog 使用場景
主從復制
這是 Binlog 最重要的用途。在主從架構中,Master 節點將自己的 Binlog 發送給 Slave 節點,Slave 通過重放 Binlog 中的 SQL 語句,實現數據同步。
點播恢復
因為 Binlog 完整記錄了對數據庫的所有更改操作,它可以通過重放來恢復某一個時間段的全部數據。在實際工作中,有時我們需要恢復數據庫到某一個歷史時間點的狀態,這時我們可以找出這個時間點之前最近的一個全量備份,用這個全量備份恢復到一個空數據庫,然后找出全量備份時間點到目標時間點之間所有 Binlog 文件并進行回放。這樣就實現了精確的時間點恢復。這對于修復誤操作(如誤刪表、誤更新)非常有用。
總結
Redo Log 保存在 InnoDB 中,用于保證宕機后數據不丟,是 MySQL 支持數據庫事務的基礎。Binlog 保存在 MySQL server 層,用于主從同步或點播恢復。
兩者分工明確但又緊密協作,共同保障了 MySQL 數據安全和高可用性。
為了讓兩個日志區別更清晰,總結下表:
特性 | Redo Log | Binlog |
歸屬 | InnoDB 存儲引擎 | Server 層 |
日志類型 | 物理日志,記錄對數據頁修改 | 邏輯日志,記錄修改 SQL 或行變化 |
用途 | 崩潰恢復 | 主從同步、點播恢復 |
寫磁盤 | 循環寫 | 追加寫 |
































