@
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的區別:
- redo log是InnoDB特有的日誌,binlog 所有引擎都可以使用
- redo log是物理日誌,記錄的是該資料頁更新的內容;
binlog
是邏輯日誌,記錄的是這個更新語句的原始邏輯 - redo log是迴圈寫的,空間固定會用完。binlog是可以追加寫的,當binlog寫到一定大小會切換到下一個,並不會覆蓋以前的日誌
- binlog可以作為恢復資料使用,主從複製搭建,redo log作為異常當機或者介質故障後的資料恢復使用。
update語句執行流程
首先進行sql查詢語句的執行流程,如需 update ID = 2 ,先找到這一行,執行以下流程:
為什麼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
有相關資料,所以會導致資料不統一。
Uodolog(回滾日誌/重做日誌)
Undo Log 是為了實現事務的原子性,事務中執行失敗,進行回滾,在MySQL資料庫 InnoDB
儲存引擎中,還用Undo Log
來實現多版本併發控制(簡稱:MVCC
)。由引擎層的InnoDB引擎實現,是邏輯日誌,記錄資料修改被修改前的值。
原理:
Undo Log的原理很簡單,為了滿足事務的原子性,在操作任何資料之前,首先將資料備份到Undo Log。然後進行資料的修改。如果出現了錯誤或者使用者執行了ROLLBACK語句,系統可以利用Undo Log中的備份將資料恢復到事務開始之前的狀態。
回滾時機?
- 使用者呼叫 rollback 主動回滾
- 事務出錯
- 輔助 redo log 實現事務永續性
當事務提交的時候,innodb
不會立即刪除undo log
,因為後續還可能會用到undo log
,如隔離級別為repeatable read
時,事務讀取的都是開啟事務時的最新提交行版本,只要該事務不結束,該行版本就不能刪除,即undo log不能刪除。
但是在事務提交的時候,會將該事務對應的undo log
放入到刪除列表中,未來通過purge來刪除。並且提交事務時,還會判斷undo log
分配的頁是否可以重用,如果可以重用,則會分配給後面來的事務,避免為每個獨立的事務分配獨立的undo log
頁而浪費儲存空間和效能。
undo log+redo log保證永續性
除了可以保證事務的原子性,Undo Log也可以用來輔助完成事務的持久化,如資料庫異常之後的恢復機制。
因為未提交的事務和回滾了的事務也會記錄在Redo Log
,因此在進行恢復時,這些事務要進行特殊的的處理。有2種不同的恢復策略:
A. 進行恢復時,只重做已經提交了的事務。
B. 進行恢復時,重做所有事務包括未提交的事務和回滾了的事務。然後通過Undo Log回滾那些未提交的事務。
MySQL資料庫InnoDB儲存引擎使用了B策略,InnoDB
儲存引擎中的恢復機制有幾個特點:
-
Undo Log回滾那些未提交的事務,被回滾了的事務在恢復時先
redo
再undo
,也不會破壞資料的一致性 -
必須要在寫
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)