Mysql日誌

CLoud11y發表於2024-09-11

mysql日誌中最重要的3種為redo log(重做日誌), binlog(歸檔日誌) 和 undo log(回滾日誌)
下面來詳細介紹一下這3種日誌

redo log

redo log是Innodb引擎特有的,記錄了資料頁上的改動,使資料庫在當機後有資料恢復的能力,保證資料的永續性

為什麼需要redo log

  • 使資料庫在當機或異常重啟後有恢復資料的能力,保證資料永續性
  • 配合mysql的WAL(Write-Ahead Logging)機制,mysql在更新操作時會只寫記憶體就返回,然後非同步去刷盤。這樣就存在系統crash後記憶體中資料丟失的問題,而redo log 是crash safe的,可以利用redo log避免此情況

redo log的寫入方式

redo log分為兩部分,記憶體中的redo log buffer和磁碟中的redo log file
mysql每次執行一條DML語句時,會把記錄寫入redo log buffer中,後續某個時間點把redo log buffer中的內容寫入到redo log file中,這種先寫日誌,再寫磁碟的操作就是WAL

但是我們知道,在計算機作業系統中,使用者空間的緩衝區資料是沒辦法直接寫入磁碟的,需要經過核心的緩衝區OS buffer才能寫入,所以redo log完整的寫入過程如下:

  1. 寫入使用者空間的redo log buffer
  2. 將redo log buffer中內容儲存到核心空間的os buffer
  3. 透過fsync()命令,將os buffer中內容儲存到磁碟redo log file中

可以透過引數innodb_flush_log_at_trx_commit來配置日誌從redo log buffer到os buffer再到redo log file的時機

  • 0:延時寫,事務提交後不會直接寫入os buffer,而是每隔1s寫入os buffer並寫入redo log file中
  • 1:實時寫、實時刷,事務提交後寫入os buffer並寫入redo log file中
  • 2:實時寫、延時刷,事務提交後寫入os buffer,每隔1s將os buffer中內容寫入redo log file

redo log如何保證crash safe

  • 在每次更新操作後,事務提交前就會記錄日誌,如果記錄失敗那麼該事務也不會提交
  • redo log記錄了頁的資料變化,當系統crash後可以讀取redo log進行重放,恢復資料

binlog

redo log是物理日誌,記錄了某個資料頁中修改了什麼內容,屬於innodb儲存引擎
而binlog是邏輯日誌,它記錄了語句的原始邏輯,屬於server層,不管用什麼儲存引擎,是要發生了表內容修改就會產生binlog,用於資料庫備份、主備、主從、主主來同步資料,保證資料一致性

binlog記錄格式

  • statement:基於sql語句的複製,記錄原始sql語句,效能好但是update_time=now()此類語句會出問題
  • row:基於行的複製,不記錄sql語句上下文相關資訊,僅儲存哪條記錄被修改,較為佔用空間
  • mixed:混合模式複製,Statement與Row的結合。一般的語句修改使用statment格式,如一些函式statement無法完成主從複製的操作,則採用row格式,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式

binlog寫入方式

當事務執行時寫入binlog cache(快取大小由binlog_chache_size控制),事務提交後從binlog cache寫入binlog file。
binlog cache重新整理到磁碟的時機由sync_binlog控制:

  • 0:mysql不管,由系統決定何時刷盤。若系統當機,快取中的binlog丟失
  • 1:每次commit,進行刷盤
  • N(大於1的整數):每N個事務進行一次刷盤

兩階段提交

為什麼需要兩階段提交呢?
首先redo log的記錄時機是在每一次資料修改時,而binlog只有在事務提交後才進行刷盤儲存。因此,若系統在某條記錄redo log成功,但事務未提交時當機,那麼就會造成redo log和binlog不一致的情況,原系統透過redo log恢復資料,從系統透過binlog恢復資料就會造成資料不一致。兩階段提交就是為了解決此類問題的。

兩階段提交就是把redo log的寫入拆分為prepare和commit兩個狀態:

  1. redo log記錄後進入prepare狀態
  2. 執行器記錄binlog
  3. 事務提交後進入commit狀態
    image.png
    如此做,當mysql重啟時便可保證資料的一致性
    image.png

undo log

回滾日誌,用於發生錯誤後的回滾操作,保證了事務的原子性。
所有事務進行的修改都會先記錄到這個回滾日誌中,然後再執行相關的操作。如果執行過程中遇到異常的話,直接利用回滾日誌中的資訊將資料回滾到修改之前的樣子即可。
並且,回滾日誌會先於資料持久化到磁碟上。這樣就保證了即使遇到資料庫突然當機等情況,當使用者再次啟動資料庫的時候,資料庫還能夠透過查詢回滾日誌來回滾之前未完成的事務。

日誌記錄整體流程圖

image.png

相關文章