MySQL——日誌系統

redo log(重做日誌)

首先,明確redo log是innodb存儲引擎層面的日誌文件,當我們對數據進行更改操作之後,innoDB會將記錄先記錄在redo log中,然後更新內存,這樣我們的更改操縱也就算完成了,然後存儲引擎會在一個合適的時機,將更改數據寫入磁盤,這個時間一般在比較空閒的時候。
redo log是固定大小的,意思就是我們不能無限的向redo log裏面寫記錄,當寫滿的時候,我們需要擦除redo log,redo log是循環輸入的,我們可以將它理解爲一個循環隊列,一個標誌位叫write pos 表示當前記錄的位置上,另一個標誌位是check point 表示當前要擦除的位置,可以先簡單理解爲一個環形跑道,兩個人在追逐,當write pos 追上check point時就表示滿了,要擦除redo log ,但是在擦除之前要將這些記錄更新到數據文件
接下來想redo log 替我們完成了一個什麼功能,換一句話就是InnoDB引擎利用redo log實現了即使數據庫發生了異常重啓,提交的記錄也不會丟失,我們可以根據redolog記錄恢復,這個能力稱爲crash-safe

binlog(歸檔日誌)

Mysql整體可以分爲兩部分,一層是server層,另一層就是存儲引擎層,redo log是存儲引擎層面的日誌,而binlog就是server層的日誌,爲什麼引入兩個日誌?
原因是MySQL支持插件式存儲引擎,最開始MySQL默認是MyISAM存儲引擎,但是這個存儲引擎不支持crash-safe,也就是說binlog只能用於歸檔使用不支持crash-safe,所以只能引入redo log 日誌系統來實現這個功能

Undo log

undo log有兩個作用:提供回滾和多個行版本控制(MVCC)。
在數據修改的時候,不僅記錄了redo,還記錄了相對應的undo,如果因爲某些原因導致事務失敗或回滾了,可以藉助該undo進行回滾。
undo log和redo log記錄物理日誌不一樣,它是邏輯日誌。可以認爲當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。
注意:undo log是邏輯日誌,可以理解爲實現記錄中的記錄就能抵消產生這條記錄的操作(相反):
– 當delete一條記錄時,undo log中會記錄一條對應的insert記錄
– 當insert一條記錄時,undo log中會記錄一條對應的delete記錄
– 當update一條記錄時,它記錄一條對應相反的update記錄

比較redo log 和 binlog的不同

  1. redo log 是innoDB引擎特有的,binlog是server層的所有引擎都能使用
  2. redo log是物理日誌,記錄的是“某個數據頁數據發生的變化”,binlog是邏輯日誌,記錄的是語句的原始邏輯
  3. redo log是循環寫的,空間固定會用完,binlog是可以追加寫入的,不會被覆蓋,寫到一定大小就會切換到下一個,並不會覆蓋以前的日誌

redo log 兩階段提交

首先我們來分析一個update語句的執行流程, update T set c=c+1 where ID=2;如圖所示
在這裏插入圖片描述
執行流程:
1、執行器先從引擎中找到數據,如果在內存中直接返回,如果不在內存中,查詢後返回
2、執行器拿到數據之後會先修改數據,然後調用引擎接口重新吸入數據
3、引擎將數據更新到內存,同時寫數據到redo中,此時處於prepare階段,並通知執行器執行完成,隨時可以操作
4、執行器生成這個操作的binlog
5、執行器調用引擎的事務提交接口,引擎把剛剛寫完的redo改成commit狀態,更新完成

因爲redo log 和binlog是兩個獨立的邏輯,如果不用兩階段提交,那麼就會出現兩種情況,一種是先寫完redo log 然後寫完binlog,另一種是順序反過來。我們來分析一下這兩種情況

先寫 redo log 後寫 binlog

假設在 redo log 寫完,binlog 還沒有寫完的時候,MySQL 進程異常重啓。由於我們前面說過的,redo log 寫完之後,系統即使崩潰,仍然能夠把數據恢復回來,所以恢復後這一行 c 的值是 1。但是由於 binlog 沒寫完就 crash 了,這時候 binlog 裏面就沒有記錄這個語句。因此,之後備份日誌的時候,存起來的 binlog 裏面就沒有這條語句,然後你會發現,如果需要用這個 binlog 來恢復臨時庫的話,由於這個語句的 binlog 丟失,這個臨時庫就會少了這一次更新,恢復出來的這一行 c 的值就是 0,與原庫的值不同。

先寫 binlog 後寫 redo log

如果在 binlog 寫完之後 crash,由於 redo log 還沒寫,崩潰恢復以後這個事務無效,所以這一行 c 的值是 0。但是 binlog 裏面已經記錄了“把c 從 0 改成 1”這個日誌。所以,在之後用 binlog 來恢復的時候就多了一個事務出來,恢復出來的這一行 c 的值就是 1,與原庫的值不同。
兩階段提交是跨系統維持數據邏輯一致性時常用的一個方案,所以說爲什麼必須有“兩階段提交”呢?這是爲了讓兩份日誌之間的邏輯一致。

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