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
回滾日誌,用於發生錯誤後的回滾操作,保證了事務的原子性。
所有事務進行的修改都會先記錄到這個回滾日誌中,然後再執行相關的操作。如果執行過程中遇到異常的話,直接利用回滾日誌中的信息將數據回滾到修改之前的樣子即可。
並且,回滾日誌會先於數據持久化到磁盤上。這樣就保證了即使遇到數據庫突然宕機等情況,當用户再次啓動數據庫的時候,數據庫還能夠通過查詢回滾日誌來回滾之前未完成的事務。