mysql-2.日誌系統:redo log和binlog

在mysql中一條查詢語句需要經過以下流程:
在這裏插入圖片描述
對於一條更新語句,其實也是需要走上面的流程的(查詢緩存這一步沒有,上章有提到,在做更新操作時候,會清空查詢緩存),只不過更新語句除了上面流程還會涉及到兩個重要的日誌模塊redo log(重做日誌)和 binlog(歸檔日誌)

redo log(重做日誌)

  1. 當有一條記錄需要更新的時候,InnoDB 引擎就會先把記錄寫到 redo log裏面,並更新內存,這個時候更新就算完成了。
  2. 同時,InnoDB 引擎會在適當的時候,將這個操作記錄更新到磁盤裏面,而這個更新往往是在系統比較空閒的時候做

InnoDB的redo log大小是固定的,比如可以配置爲一組四個文件,每個文件大小1GB,那麼這個redo log就可以一共記錄4G的操作。從頭開始寫,寫到末尾就又回到開頭循環寫
在這裏插入圖片描述
write pos 是當前記錄的位置(寫到那裏了),一邊寫一邊順時針往後移動,寫到第 3 號文件末尾後就回到 0 號文件開頭。
checkpoint 是當前要擦除的位置,也是往後推移並且循環的,擦除記錄前要把記錄更新到數據文件。擦除之後的綠色區域就又空出來,可以記錄新的操作。

tips:因爲是循環寫,所以如果redo log滿了再寫,就會覆蓋前面寫的內容,所以需要在覆蓋之前將記錄更新到磁盤數據文件。redo log滿了,就是write pos 追上check point,這個時候。這時候不能再執行新的更新,得停下來先擦掉一些記錄,把 checkpoint 推進一下。

有了 redo log,InnoDB 就可以保證即使數據庫發生異常重啓,之前提交的記錄都不會丟失,這個能力稱爲 crash-safe。

tips:

  • Redo log不是記錄數據頁“更新之後的狀態”,而是記錄這個頁 “做了什麼改動”

binlog(歸檔日誌)

我們知道mysql從整體上看可以分爲:server 和 存儲引擎。binlog和redo log不同,binlog是屬於server層的。也就是你使用任何存儲引擎都可以使用binlog.

binlog有兩種模式,statement 格式的話是記sql語句, row格式會記錄行的內容,記兩條,更新前和更新後都有。

redo log和binlog比較:

  • binlog日誌只能用來歸檔,並沒有crash-safe的功能
  • redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實現的,所有引擎都可以使用
  • redo log 是物理日誌,記錄的是“在某個數據頁上做了什麼修改”;binlog 是邏輯日誌,記錄的是這個語句的原始邏輯,比如“給 ID=2 這一行的 c 字段加 1 ”
  • redo log 是循環寫的,空間固定會用完;binlog 是可以追加寫入的。“追加寫”是指 binlog 文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。

我們來看下一條update語句執行流程:update T set c=c+1 where ID=2;

  1. 執行器先找引擎取 ID=2 這一行。ID 是主鍵,引擎直接用樹搜索找到這一行。如果 ID=2 這一行所在的數據頁本來就在內存中,就直接返回給執行器;否則,需要先從磁盤讀入內存,然後再返回。
  2. 執行器拿到引擎給的行數據,把這個值加上 1,比如原來是 N,現在就是 N+1,得到新的一行數據,再調用引擎接口寫入這行新數據。
  3. 引擎將這行新數據更新到內存中,同時將這個更新操作記錄到 redo log 裏面,此時 redo log 處於 prepare 狀態。然後告知執行器執行完成了,隨時可以提交事務。
  4. 執行器生成這個操作的 binlog,並把 binlog 寫入磁盤。
  5. 執行器調用引擎的提交事務接口,引擎把剛剛寫入的 redo log 改成提交(commit)狀態,更新完成。
    在這裏插入圖片描述
    兩階段提交:
    上面的倒數三步,用到了兩階段提交,來保證binlog和redolog的一致性。

1 prepare階段 2 寫binlog 3 commit

  • 當在2之前崩潰
    重啓恢復:後發現沒有commit,回滾。備份恢復:binlog中沒有本次更新記錄 。binlog和redolog一致
  • 當在3之前崩潰
    重啓恢復:雖沒有commit,但滿足prepare和binlog完整,所以重啓後會自動commit。備份恢復:binlog有本次更新記錄。重啓後會commit,最後binlog和redolog也一致

總結:

tips:

  • redo log 用於保證 crash-safe 能力。innodb_flush_log_at_trx_commit 這個參數設置成 1 的時候,表示每次事務的 redo log 都直接持久化到磁盤。這個參數建議你設置成 1,這樣可以保證 MySQL 異常重啓之後數據不丟失
  • sync_binlog 這個參數設置成 1 的時候,表示每次事務的 binlog 都持久化到磁盤。這個參數也建議你設置成 1,這樣可以保證 MySQL 異常重啓之後 binlog 不丟失。

下一章:事務隔離

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章