Mysql 系列 | 紀錄檔模組

2022-07-20 15:01:21

瞭解了 SQL 執行的流程,知道每一條語句都經過聯結器、查詢儲存、分析器、優化器、執行器最後到儲存引擎的過程。查詢語句是如此,更新語句也不例外。
不同的是,更新語句會修改表資料,這裡就涉及到兩個重要的紀錄檔模組 redologbinlog
本篇還是選用 InnoDB 搜尋引擎。

系統的紀錄檔模組

之一 redolog

下面引入丁奇的經典比喻。

《孔乙己》這篇文章中,酒店掌櫃有一個粉板,專門用來記錄客人的賒賬記錄。
如果賒賬的人不多,他可以把顧客名和賬目寫在板上。
但如果賒賬的人多了,粉板總會有記不下的時候,這個時候掌櫃一定還有一個專門記錄賒賬的賬本。

如果有人要賒賬或者還賬的話,掌櫃一般有兩種做法:
一是直接把賬本翻出來,把這次賒的賬加上去或者扣除掉;
另一種是先在粉板上記下這次的賬,等打烊以後再把賬本翻出來核算。

在生意紅火櫃檯很忙時,掌櫃一定會選擇後者,因為前者操作實在是太麻煩了。
首先,你得找到這個人的賒賬總額那條記錄。你想想,密密麻麻幾十頁,掌櫃要找到那個名字,可能還得帶上老
花鏡慢慢找,找到之後再拿出算盤計算,最後再將結果寫回到賬本上。

你想想,如果掌櫃沒有粉板的幫助,每次記賬都得翻賬本,效率是不是低得讓人難以忍受?

上面的比喻非常形象地說明了 Mysql 中的 WAL(Write-Ahead-Logging) 技術。

先寫紀錄檔(redolog),再寫磁碟。也就是先寫粉板再寫賬本。

  • redolog 是 InnoDB 引擎特有的紀錄檔。

  • 當有資料要更新時,InnoDB 會先記錄 redolog,同時更新記憶體,更新操作就結束了。等到合適的時候(空閒或者粉板寫滿了),再更新磁碟。

  • redolog 有固定大小,就像固定大小的粉板,寫滿就得回到開頭回圈寫。

    • write pos 是當前記錄粉板的位置,一邊寫一邊往後移。

    • check point 是擦除的位置,擦除前會把更新記錄到資料檔案。

    • redolog 保證了資料庫異常重啟時資料不丟失,這個能力被稱為 crash-safe


(丁奇原圖)

  • redolog 預設在 Mysql 的 data 目錄下,ib_logfile0、ib_logfile1、。。。
mysql> show variables like "innodb_log_group_home_dir";
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_log_group_home_dir | ./    |
+---------------------------+-------+
1 row in set (0.00 sec)
  • 設定 redolog 檔案大小及個數,預設 2 個檔案(innodb_log_files_in_group),每個檔案 32M(innodb_log_file_size)
mysql> show variables like "innodb_log_file%";
+---------------------------+----------+
| Variable_name             | Value    |
+---------------------------+----------+
| innodb_log_file_size      | 33554432 |
| innodb_log_files_in_group | 2        |
+---------------------------+----------+
2 rows in set (0.00 sec)
  • 設定 redolog 實時直接持久化到磁碟上,保證重啟後資料不丟失。
mysql> show variables like "innodb_flush_log_at_trx_commit";
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)

之二 binlog

  • binlog 是 Server 層的紀錄檔,叫歸檔紀錄檔。不同於 redolog 只有 InnoDB 有,binlog 任何引擎都可以使用。

  • binlog 是邏輯紀錄檔,記錄語句的原始邏輯;redolog 是物理紀錄檔,記錄資料頁的修改內容。

  • binlog 不會迴圈寫,一個寫完後切換到寫一個;redolog 有固定的大小。

  • binlog 在 data 目錄下,mysql-bin.xxxxxx。

  • 設定 binlog 每次事務直接持久化到磁碟上,保證重啟後資料不丟失。

mysql> show variables like "sync_binlog";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
1 row in set (0.00 sec)

update 的執行過程

update T set c=c+1 where ID=2;
  • 執行器呼叫引擎介面找 ID=2 的資料,如果 ID=2 資料所在的資料頁在記憶體中,則直接返回給執行器。否則先從磁碟讀取再返回。

  • 執行器拿到資料,把 c 加 1,得到新的一行資料。然後呼叫引擎介面,寫入這行資料。

  • 引擎將新資料更新到記憶體中,順便記錄 redolog,此時 redolog 處於 prepare 狀態,然後告訴執行器可以提交事務。

  • 執行器把 binlog 寫入磁碟,然後呼叫引擎介面提交事務。redolog 狀態變為 commit。更新完成。

資料恢復

既然記錄了 log,那麼當資料誤操作後,就可以根據資料庫定期備份,加上記錄的 log 方便的恢復到誤操作之前的狀態。

  • 先根據備份恢復到臨時表

  • 根據 binlog 找到備份後到誤操作前的記錄。

  • 把恢復好的臨時庫按需要同步到正式庫中。


只要有 log,就可以恢復到任何時刻的資料狀態。

再也不用擔心誤操作無法恢復了。