mysql日誌系統之redo log和bin log
首先,我們先來看看一次查詢/更新語句流程圖

mysql查詢/更新流程圖.png
mysql不是每次資料更改都立刻寫到磁碟,而是會先將修改後的結果暫存在記憶體中,當一段時間後,再一次性將多個修改寫到磁碟上,減少磁碟io成本,同時提高操作速度。
-
mysql通過WAL(write-ahead logging)技術保證事務
在同一個事務中,每當資料庫進行修改資料操作時,將修改結果更新到記憶體後,會在redo log新增一行記錄記錄“需要在哪個資料頁上做什麼修改”,並將該記錄狀態置為prepare,等到commit提交事務後,會將此次事務中在redo log新增的記錄的狀態都置為commit狀態,之後將修改落盤時,會將redo log中狀態為commit的記錄的修改都寫入磁碟。過程如下圖
更新流程.png
-
redo log記錄方式
redolog的大小是固定的,在mysql中可以通過修改配置引數innodb_log_files_in_group和innodb_log_file_size配置日誌檔案數量和每個日誌檔案大小,redolog採用迴圈寫的方式記錄,當寫到結尾時,會回到開頭迴圈寫日誌。如下圖
redolog記錄方式.png
有了redo log,當資料庫發生宕機重啟後,可通過redo log將未落盤的資料恢復,即保證已經提交的事務記錄不會丟失。
有了redo log,為啥還需要binlog呢?
1、redo log的大小是固定的,日誌上的記錄修改落盤後,日誌會被覆蓋掉,無法用於資料回滾/資料恢復等操作。
2、redo log是innodb引擎層實現的,並不是所有引擎都有。
- 基於以上,binlog必不可少
1、binlog是server層實現的,意味著所有引擎都可以使用binlog日誌
2、binlog通過追加的方式寫入的,可通過配置引數max_binlog_size設定每個binlog檔案的大小,當檔案大小大於給定值後,日誌會發生滾動,之後的日誌記錄到新的檔案上。
3、binlog有兩種記錄模式,statement格式的話是記sql語句, row格式會記錄行的內容,記兩條,更新前和更新後都有。
binlog和redo log必須保持一致,不允許出現binlog有記錄但redolog沒有的情況,反之亦然。之前說過在一個事務中,redolog有prepare和commit兩種狀態,所以,在redolog狀態為prepare時記錄binlog可保證兩日誌的記錄一致,下圖列出各種情況來說明。

4.png
現在我們再來看看整個完整的流程圖

更新流程.png
1、innodb_flush_log_at_trx_commit:設定為1,表示每次事務的redolog都直接持久化到磁碟(注意是這裡指的是redolog日誌本身落盤),保證mysql重啟後資料不丟失。
2、sync_binlog: 設定為1,表示每次事務的binlog都直接持久化到磁碟(注意是這裡指的是binlog日誌本身落盤),保證mysql重啟後binlog記錄是完整的。