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

































