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完整的寫入過程如下:
- 寫入使用者空間的redo log buffer
- 將redo log buffer中內容儲存到核心空間的os buffer
- 透過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兩個狀態:
- redo log記錄後進入prepare狀態
- 執行器記錄binlog
- 事務提交後進入commit狀態
如此做,當mysql重啟時便可保證資料的一致性
undo log
回滾日誌,用於發生錯誤後的回滾操作,保證了事務的原子性。
所有事務進行的修改都會先記錄到這個回滾日誌中,然後再執行相關的操作。如果執行過程中遇到異常的話,直接利用回滾日誌中的資訊將資料回滾到修改之前的樣子即可。
並且,回滾日誌會先於資料持久化到磁碟上。這樣就保證了即使遇到資料庫突然當機等情況,當使用者再次啟動資料庫的時候,資料庫還能夠透過查詢回滾日誌來回滾之前未完成的事務。