必須瞭解的mysql三大日誌-binlog、redo log和undo log

日誌是mysql數據庫的重要組成部分,記錄着數據庫運行期間各類狀態信息。mysql日誌主要包括錯誤日誌、查詢日誌、慢查詢日誌、事務日誌、二進制日誌幾大類。做爲開發,咱們重點須要關注的是二進制日誌(binlog)和事務日誌(包括redo logundo log),本文接下來會詳細介紹這三種日誌。html

binlog

binlog用於記錄數據庫執行的寫入性操做(不包括查詢)信息,以二進制的形式保存在磁盤中。binlogmysql的邏輯日誌,而且由Server層進行記錄,使用任何存儲引擎的mysql數據庫都會記錄binlog日誌。mysql

邏輯日誌:能夠簡單理解爲記錄的就是sql語句
物理日誌:由於mysql數據最終是保存在數據頁中的,物理日誌記錄的就是數據頁變動
面試

binlog是經過追加的方式進行寫入的,能夠經過max_binlog_size參數設置每一個binlog文件的大小,當文件大小達到給定值以後,會生成新的文件來保存日誌。sql

binlog使用場景

在實際應用中,binlog的主要使用場景有兩個,分別是主從複製數據恢復數據庫

  1. 主從複製:在Master端開啓binlog,而後將binlog發送到各個Slave端,Slave端重放binlog從而達到主從數據一致。
  2. 數據恢復:經過使用mysqlbinlog工具來恢復數據。

binlog刷盤時機

對於InnoDB存儲引擎而言,只有在事務提交時纔會記錄biglog,此時記錄還在內存中,那麼biglog是何時刷到磁盤中的呢?mysql經過sync_binlog參數控制biglog的刷盤時機,取值範圍是0-N安全

  • 0:不去強制要求,由系統自行判斷什麼時候寫入磁盤;
  • 1:每次commit的時候都要將binlog寫入磁盤;
  • N:每N個事務,纔會將binlog寫入磁盤。

從上面能夠看出,sync_binlog最安全的是設置是1,這也是MySQL 5.7.7以後版本的默認值。可是設置一個大一些的值能夠提高數據庫性能,所以實際狀況下也能夠將值適當調大,犧牲必定的一致性來獲取更好的性能。併發

binlog日誌格式

binlog日誌有三種格式,分別爲STATMENTROWMIXED工具

MySQL 5.7.7以前,默認的格式是STATEMENTMySQL 5.7.7以後,默認值是ROW。日誌格式經過binlog-format指定。post

  • STATMENT
    基於SQL語句的複製(statement-based replication, SBR),每一條會修改數據的sql語句會記錄到binlog
    優勢:不須要記錄每一行的變化,減小了binlog日誌量,節約了IO, 從而提升了性能
    缺點:在某些狀況下會致使主從數據不一致,好比執行sysdate()slepp()


  • ROW
    基於行的複製(row-based replication, RBR),不記錄每條sql語句的上下文信息,僅需記錄哪條數據被修改了
    優勢:不會出現某些特定狀況下的存儲過程、或function、或trigger的調用和觸發沒法被正確複製的問題
    缺點:會產生大量的日誌,尤爲是alter table的時候會讓日誌暴漲


  • MIXED
    基於STATMENTROW兩種模式的混合複製(mixed-based replication, MBR),通常的複製使用STATEMENT模式保存binlog,對於STATEMENT模式沒法複製的操做使用ROW模式保存binlog

redo log

爲何須要redo log

咱們都知道,事務的四大特性裏面有一個是持久性,具體來講就是只要事務提交成功,那麼對數據庫作的修改就被永久保存下來了,不可能由於任何緣由再回到原來的狀態。那麼mysql是如何保證一致性的呢?最簡單的作法是在每次事務提交的時候,將該事務涉及修改的數據頁所有刷新到磁盤中。可是這麼作會有嚴重的性能問題,主要體如今兩個方面:性能

  1. 由於Innodb是以爲單位進行磁盤交互的,而一個事務極可能只修改一個數據頁裏面的幾個字節,這個時候將完整的數據頁刷到磁盤的話,太浪費資源了!
  2. 一個事務可能涉及修改多個數據頁,而且這些數據頁在物理上並不連續,使用隨機IO寫入性能太差!

所以mysql設計了redo log具體來講就是隻記錄事務對數據頁作了哪些修改,這樣就能完美地解決性能問題了(相對而言文件更小而且是順序IO)。

redo log基本概念

redo log包括兩部分:一個是內存中的日誌緩衝(redo log buffer),另外一個是磁盤上的日誌文件(redo log file)。mysql每執行一條DML語句,先將記錄寫入redo log buffer,後續某個時間點再一次性將多個操做記錄寫到redo log file。這種先寫日誌,再寫磁盤的技術就是MySQL裏常常說到的WAL(Write-Ahead Logging) 技術。

在計算機操做系統中,用戶空間(user space)下的緩衝區數據通常狀況下是沒法直接寫入磁盤的,中間必須通過操做系統內核空間(kernel space)緩衝區(OS Buffer)。所以,redo log buffer寫入redo log file其實是先寫入OS Buffer,而後再經過系統調用fsync()將其刷到redo log file中,過程以下:
log-buffer

mysql支持三種將redo log buffer寫入redo log file的時機,能夠經過innodb_flush_log_at_trx_commit參數配置,各參數值含義以下:

參數值 含義
0(延遲寫) 事務提交時不會將redo log buffer中日誌寫入到os buffer,而是每秒寫入os buffer並調用fsync()寫入到redo log file中。也就是說設置爲0時是(大約)每秒刷新寫入到磁盤中的,當系統崩潰,會丟失1秒鐘的數據。
1(實時寫,實時刷) 事務每次提交都會將redo log buffer中的日誌寫入os buffer並調用fsync()刷到redo log file中。這種方式即便系統崩潰也不會丟失任何數據,可是由於每次提交都寫入磁盤,IO的性能較差。
2(實時寫,延遲刷) 每次提交都僅寫入到os buffer,而後是每秒調用fsync()os buffer中的日誌寫入到redo log file

在這裏插入圖片描述

redo log記錄形式

前面說過,redo log實際上記錄數據頁的變動,而這種變動記錄是不必所有保存,所以redo log實現上採用了大小固定,循環寫入的方式,當寫到結尾時,會回到開頭循環寫日誌。以下圖:
在這裏插入圖片描述
同時咱們很容易得知,在innodb中,既有redo log須要刷盤,還有數據頁也須要刷盤,redo log存在的意義主要就是下降對數據頁刷盤的要求。在上圖中,write pos表示redo log當前記錄的LSN(邏輯序列號)位置,check point表示數據頁更改記錄刷盤後對應redo log所處的LSN(邏輯序列號)位置。write poscheck point之間的部分是redo log空着的部分,用於記錄新的記錄;check pointwrite pos之間是redo log待落盤的數據頁更改記錄。當write pos追上check point時,會先推進check point向前移動,空出位置再記錄新的日誌。

啓動innodb的時候,無論上次是正常關閉仍是異常關閉,老是會進行恢復操做。由於redo log記錄的是數據頁的物理變化,所以恢復的時候速度比邏輯日誌(如binlog)要快不少。
重啓innodb時,首先會檢查磁盤中數據頁的LSN,若是數據頁的LSN小於日誌中的LSN,則會從checkpoint開始恢復。
還有一種狀況,在宕機前正處於checkpoint的刷盤過程,且數據頁的刷盤進度超過了日誌頁的刷盤進度,此時會出現數據頁中記錄的LSN大於日誌中的LSN,這時超出日誌進度的部分將不會重作,由於這自己就表示已經作過的事情,無需再重作。

redo log與binlog區別

redo log binlog
文件大小 redo log的大小是固定的。 binlog可經過配置參數max_binlog_size設置每一個binlog文件的大小。
實現方式 redo logInnoDB引擎層實現的,並非全部引擎都有。 binlogServer層實現的,全部引擎均可以使用 binlog日誌
記錄方式 redo log 採用循環寫的方式記錄,當寫到結尾時,會回到開頭循環寫日誌。 binlog 經過追加的方式記錄,當文件大小大於給定值後,後續的日誌會記錄到新的文件上
適用場景 redo log適用於崩潰恢復(crash-safe) binlog適用於主從複製和數據恢復

binlogredo log的區別可知:binlog日誌只用于歸檔,只依靠binlog是沒有crash-safe能力的。但只有redo log也不行,由於redo logInnoDB特有的,且日誌上的記錄落盤後會被覆蓋掉。所以須要binlogredo log兩者同時記錄,才能保證當數據庫發生宕機重啓時,數據不會丟失。

undo log

數據庫事務四大特性中有一個是原子性,具體來講就是 原子性是指對數據庫的一系列操做,要麼所有成功,要麼所有失敗,不可能出現部分紅功的狀況。實際上,原子性底層就是經過undo log實現的。undo log主要記錄了數據的邏輯變化,好比一條INSERT語句,對應一條DELETEundo log,對於每一個UPDATE語句,對應一條相反的UPDATEundo log,這樣在發生錯誤時,就能回滾到事務以前的數據狀態。同時,undo log也是MVCC(多版本併發控制)實現的關鍵,這部份內容在面試中的老大難-mysql事務和鎖,一次性講清楚!中有介紹,再也不贅述。

參考

  1. https://juejin.im/post/6844903794073960455
  2. https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html
  3. https://www.cnblogs.com/ivy-zheng/p/11094528.html
  4. https://yq.aliyun.com/articles/592937
  5. https://www.jianshu.com/p/5af73b203f2a
  6. https://www.jianshu.com/p/20e10ed721d0

原創不易,以爲文章寫得不錯的小夥伴,點個贊👍 鼓勵一下吧~

相關文章
相關標籤/搜索