【Mysql】三大日志 redo log、bin log、undo log


@

redo log(物理日志\重做日志)

redo log是InnoDB存儲引擎層的日志,又稱重做日志文件,是物理日志。redo log記錄數據修改后新數據的備份、冗雜的undo log、未提交的事務和回滾的事務,數據緩存到內存中,只是在事務提交前將redo log持久化到磁盤

redo log 可以保證即使數據庫發生異常重啟,之前提交的記錄都不會丟失,保證了事務的持久性

當有一條記錄需要更新的時候,InnoDB引擎就會先把記錄寫到redo log中,並更新內存。之后,InnoDB引擎會在適當的時候,將這個操作更新到磁盤中,這個更新是在系統比較空閑的時候做,他的關鍵點是先寫日志,再寫磁盤。

redo log日志大小是固定的,若空間滿了以后會回到頭部停止更新,先加載一些數據到磁盤讓出文件空間,之后繼續寫入


物理日志:因為mysql數據最終是保存在數據頁中的,物理日志記錄的就是數據頁變更

為了保證Redo Log能夠有比較好的IO性能,InnoDB 的 Redo Log的設計有以下幾個特點:

  • 盡量保持Redo Log存儲在一段連續的空間上。因此在系統第一次啟動時就會將日志文件的空間完全分配。以順序追加的方式記錄Redo Log,通過順序IO來改善性能。

  • redo log包括兩部分:一是內存中的日志緩沖(redo log buffer),該部分日志是易失性的;二是磁盤上的重做日志文件(redo log file),該部分日志是持久的。日志並不是直接寫入文件的,而是先寫入日志緩沖,當需要將日志刷新到磁盤時(如事務提交),將許多日志一起寫入磁盤.

  • 並發的事務共享Redo Log的存儲空間,它們的Redo Log按語句的執行順序,依次交替的記錄在一起,以減少日志占用的空間。所以,當一個事務將Redo Log寫入磁盤時,也會將其他未提交的事務的日志寫入磁盤。

  • Redo Log上只進行順序追加的操作,當一個事務需要回滾時,它的Redo Log記錄也不會從Redo Log中刪除掉。


注意

一般在事務提交之前會將redo log持久化到磁盤中,以此來保證持久性



binlog(邏輯日志/歸檔日志)

binlog是屬於MySQL Server層面的,又稱為歸檔日志,屬於邏輯日志,是以二進制的形式記錄的是這個語句的原始邏輯,依靠binlog是沒有CrashSafe能力的

邏輯日志:可以簡單理解為記錄的就是sql語句

binlog主要使用場景:主從復制數據恢復

主從復制:在Master端開啟binlog,然后將binlog發送到各個Slave端,Slave端重放binlog從而達到主從數據一致。

數據庫恢復方法

系統會定期整庫備份,binlog會記錄所有的邏輯操作,當需要恢復到指定的某一時刻時:

  • 首先,找到最近的一次全量備份
  • 然后,從備份時間開始,將binlog依次取出來,一直重放到指定的時刻

為什么 redo log 具有 crash-safe 的能力,而 binlog 沒有?

CrashSafe指MySQL服務器宕機重啟后,能夠保證:
- 所有已經提交的事務的數據仍然存在。
- 所有沒有提交的事務的數據自動回滾。

當數據庫 crash(崩潰) 后,想要恢復未刷盤但已經寫入 redo log binlog 的數據到內存時,binlog 是無法恢復的。雖然 binlog 擁有全量的日志,但沒有一個標志讓 innoDB 判斷哪些數據已經刷盤,哪些數據還沒有。

redo log 不一樣,只要刷入磁盤的數據,都會從 redo log 中抹掉,數據庫重啟后,直接把 redo log 中的數據都恢復至內存就可以了。這就是為什么 redo log 具有crash-safe的能力,而binlog 不具備。


redo log 和 binlog的區別:

  1. redo log是InnoDB特有的日志,binlog 所有引擎都可以使用
  2. redo log是物理日志,記錄的是該數據頁更新的內容;binlog是邏輯日志,記錄的是這個更新語句的原始邏輯
  3. redo log是循環寫的,空間固定會用完。binlog是可以追加寫的,當binlog寫到一定大小會切換到下一個,並不會覆蓋以前的日志
  4. binlog可以作為恢復數據使用,主從復制搭建,redo log作為異常宕機或者介質故障后的數據恢復使用。

update語句執行流程

首先進行sql查詢語句的執行流程,如需 update ID = 2 ,先找到這一行,執行以下流程:

image-20211121192944090

為什么update語句 要有兩階段提交?

這是為了讓兩份日志之間的邏輯一致。

當執行update語句時,數據修改完更新到內存,先寫redo log 並設置redo log為准備階段,再寫binlog,寫完binlog設置為redo log為結束階段。兩個中間有一個寫入差錯,那么該操作都是失敗,即redo log發現只有准備階段沒有結束,那么會將該條事務進行回滾。


假如不采用兩階段提交機制的話那么會有什么影響呢?
(1)先寫redo log:當寫完redo log設備斷電,binlog沒有記錄,那么數據庫剛剛啟動之后通過redo log可以恢復到斷電前的狀態,但是由於binlog沒有寫入,當從某個節點進行恢復時(或者創建一個備份庫),那么binlog沒用這條記錄,恢復出來的數據庫是有錯誤的。
(2)先寫binlog:當寫完binlog設備斷電,redo log沒有記錄,還沒有寫入磁盤,那么數據庫重新啟動之后通過redo log恢復並沒有這條數據,而當從某個時間點進行恢復(或者創建一個備份庫)時,binlog有相關數據,所以會導致數據不統一。



Undolog(回滾日志/重做日志)

Undo Log 是為了實現事務的原子性,事務中執行失敗,進行回滾,在MySQL數據庫 InnoDB 存儲引擎中,還用Undo Log來實現多版本並發控制(簡稱:MVCC)。由引擎層的InnoDB引擎實現,是邏輯日志,記錄數據修改被修改前的值。


原理:

Undo Log的原理很簡單,為了滿足事務的原子性,在操作任何數據之前,首先將數據備份到Undo Log。然后進行數據的修改。如果出現了錯誤或者用戶執行了ROLLBACK語句,系統可以利用Undo Log中的備份將數據恢復到事務開始之前的狀態。


回滾時機?

  • 用戶調用 rollback 主動回滾
  • 事務出錯
  • 輔助 redo log 實現事務持久性

undo log 的清除

當事務提交的時候,innodb不會立即刪除undo log,因為后續還可能會用到undo log,如隔離級別為repeatable read時,事務讀取的都是開啟事務時的最新提交行版本,只要該事務不結束,該行版本就不能刪除,即undo log不能刪除。

但是在事務提交的時候,會將該事務對應的undo log放入到刪除列表中,未來通過purge來刪除。並且提交事務時,還會判斷undo log分配的頁是否可以重用,如果可以重用,則會分配給后面來的事務,避免為每個獨立的事務分配獨立的undo log頁而浪費存儲空間和性能。

undo log 主要分為兩種:

  1. insert undo log
    代表事務在 insert 新記錄時產生的 undo log, 只在事務回滾時需要,並且在事務提交后可以被立即丟棄。
  2. update undo log
    事務在進行 update 或 delete 時產生的 undo log ; 不僅在事務回滾時需要,在快照讀時也需要;所以不能隨便刪除,只有在快速讀或事務回滾不涉及該日志時,對應的日志才會被 purge 線程統一清除

purge

從前面的分析可以看出,為了實現 InnoDB 的 MVCC 機制,更新或者刪除操作都只是設置一下老記錄的 deleted_bit ,並不真正將過時的記錄刪除。

為了節省磁盤空間,InnoDB 有專門的 purge 線程來清理 deleted_bit 為 true 的記錄。為了不影響 MVCC 的正常工作,purge 線程自己也維護了一個read view(這個 read view 相當於系統中最老活躍事務的 read view );如果某個記錄的 deleted_bit 為 true ,並且 DB_TRX_ID 相對於 purge 線程的 read view 可見,那么這條記錄一定是可以被安全清除的。


undo log+redo log保證持久性

除了可以保證事務的原子性,Undo Log也可以用來輔助完成事務的持久化,如數據庫異常之后的恢復機制。

因為未提交的事務和回滾了的事務也會記錄在Redo Log,因此在進行恢復時,這些事務要進行特殊的的處理。有2種不同的恢復策略:

A. 進行恢復時,只重做已經提交了的事務。
B. 進行恢復時,重做所有事務包括未提交的事務和回滾了的事務。然后通過Undo Log回滾那些未提交的事務。

MySQL數據庫InnoDB存儲引擎使用了B策略,InnoDB存儲引擎中的恢復機制有幾個特點:

  • Undo Log回滾那些未提交的事務,被回滾了的事務在恢復時先redoundo,也不會破壞數據的一致性

  • ​ 必須要在寫Redo Log之前將對應的Undo Log寫入磁盤。為了降低復雜度,InnoDB將Undo Log看作數據,因此記錄Undo Log的操作也會記錄到redo log中。這樣undo log就可以象數據一樣緩存起來,而不用在redo log之前寫入磁盤了。


參考:

極客時間 mysql45講

https://www.qiancheng.me/post/coding/mysql-001

說說MySQL中的Redo log Undo log都在干啥 - 蘇家小蘿卜 - 博客園 (cnblogs.com)

詳細分析MySQL事務日志(redo log和undo log) - 駿馬金龍 - 博客園 (cnblogs.com)

MySQL事務日志undo log和redo log分析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM