MYSQL---日誌

本文將探討以下幾個問題。

一、思考

  • 問題一:MYSQL執行流程中會產生哪些日誌?

相信大家都接觸過binlog,redolog,undolog這些字眼,那麼這些日誌究竟在何時產生,存放於什麼位置呢?

  • 問題二:這些日誌的作用是什麼?

MYSQL產生這些日誌的目的在於什麼,或者說每一個日誌能帶來什麼作用?

二、分析 

2.1binlog

  • binlog功能開啓

可通過以下命令檢查binlog功能是否開啓:

如果log_bin的value爲OFF,可通過修改配置文件my.ini開啓:

該值爲binlog日誌文件名稱,可隨意填,日誌文件路徑爲datadir參數值。修改配置文件後,需要重啓mysql服務方可生效。當開啓之後會在log_bin_basename所在目錄產生以下兩個文件:

mylog.000001:binlog日誌文件,記錄了所有的DDL(數據定義語言)和DML(數據操縱語言,不包含數據查詢語言)。

mylog.index:binlog索引文件,記錄所有的二進制文件。

  • binlog查看方式

直接打開該文件爲亂碼,安裝MYSQL時,其爲我們提供了查看此日誌的工具,即mysqlbinlog.exe。該工具位於mysql服務安裝目錄bin目錄之下。使用方式:

mysqlbinlog --no-defaults mylog.000001,該命令查看的日誌具體SQL部分被進行base64編碼,可通過

mysqlbinlog  --no-defaults --base64-output=decode-rows -v   .\mylog.000001 > .\binlog.txt,將base64解碼後的文件寫到mylog.txt查看。

  • binlog產生時機和內容

當進行以下操作時,會將操作內容記錄到binlog。

  1. 數據定義:即CREATE、ALTER、DROP、TRUNCATE、RENAME操作。
  2. 數據操作:INSERT、UPDATE、DELETE。

接下來,我們以INSERT爲例,查看binlog記錄的內容:

插入語句爲:INSERT INTO role (`name`,`desc`) VALUES ('a','b');

通過mysqlbinlog工具打開mylog.0000001文件內容如下:

  • binlog文件作用

  1. 主從複製。
  2. 數據恢復。

這裏只是瞭解,後面會專門寫一篇主從複製和數據恢復相關內容。

2.2redolog

  • redolog產生背景

當修改DB某一行數據時,會先將該數據從磁盤讀取到內存中的緩衝池進行修改,這時內存中的值與磁盤中的值相比就有了差異,這種有差異性的數據也被稱之爲“髒頁”。這種差異性導致,當內存中的緩衝數據還未刷新到磁盤中,此時如果系統崩潰,便會造成數據丟失。redolog便是爲了解決這樣的問題。

  • redolog存放位置

datadir目錄/ib_logfile*文件中。

  • redolog產生的時機和內容

  1. 產生時機:事務完全提交之前。當我們提交一個事務時,InnoDB會先將修改的數據寫入到日誌文件中,再去修改內存中的緩衝區的數據。
  2. 內容:redolog主要記錄了數據被修改之後的值。用於宕機之後的數據恢復。
  • redolog的產生流程

我們先看一下redolog的設計架構:

redolog_buffer爲InnoDB層面的緩存,os_buffer爲操作系統層面的緩存。fsync函數的作用便是將os_buffer中的緩存刷新到磁盤,設置緩存的目的也是爲了避免每次都寫入磁盤而帶來的開銷。

對於redo_log_buffer,這裏借用《MYSQL實戰45講》中的舉例說明:

酒館老闆有一個賬本,假如每次客人賒賬時,酒館老闆都找到賬本,再找到對應的客人記一筆記錄,那在客流量較大時,效率則會非常慢。於是酒店老闆弄了個小黑板,每次客人賒賬時,先將記錄直接寫到小黑板上,待打烊時,將黑板的內容寫到賬本中。如果小黑板內容已滿,則先空下來,將小黑板內容寫到賬本。

這個過程在MYSQL的實現中也稱爲WAL技術(Writing-Ahead logging),即先寫日誌,再寫磁盤。而這裏的小黑板類比redo_log_buffer,賬本類比redo_log_file。

在介紹redolog產生流程之前,我們有必要了解一個參數,其控制了redolog的寫入策略。

該參數共有三個取值,分別代表三種不同策略:

0:事務提交時,僅將日誌寫到redo_log_buffer,不會直接寫入到os_buffer中,而是每秒從redo_log_buffer中寫到os_buufer中,並調用fsync刷新到磁盤。

1(默認):事務提交時,將日誌寫到redo_log_buffer,同時將redo_log_buffer中的日誌寫到os_buffer,再調用fsync刷新到磁盤。

2:事務提交時,不寫入redo_log_buffer,而是直接寫入os_buffer,然後每秒調用fsync刷新到磁盤。

那麼這三個不同的取值會帶來什麼影響呢?我們從DB故障和操作系統故障兩個方面分析一下。

0:其每隔一秒從os_buffer刷新到磁盤,假如剛好在一秒的間隙內,此時DB故障,redo_log_buffer的內容會丟失,導致這一秒間隙內的數據將丟失。

2:日誌將直接寫入到os_buffer中,這樣當操作系統發生故障時,日誌還未從os_buffer刷新到磁盤,造成數據丟失。

1:此時每次redo_log_buffer和os_buffer中都有數據。只要當DB故障和操作系統故障恢復,都能將數據重新寫入磁盤。

有了以上內容,我們再分析一下當一個更新事務來臨時,redolog的產生流程是怎樣的?

  1. 查詢磁盤數據到內存中的緩存區。
  2. 修改數據,依然保存到緩存。
  3. 事務提交時,先生成一條redolog日誌。
  4. 根據innodb_flush_log_at_trx_commit參數,執行對應的策略,將日誌寫入到文件。
  5. 提交事務。
  6. 將內存中的更新後的數據寫入到文件。
  • redolog的作用

redolog可以進行數據恢復,因爲其保存了數據被修改之後的值,這樣當DB故障或者操作系統故障修復之後,便能通過該日誌恢復之前的操作。事務的持久性也是通過redolog實現的,這種機制被稱之爲“Force log at commint”,即事務在提交之前必須成功寫入redolog。

後面會寫一篇博文專門分析事務的實現原理。

2.3undolog

在上一小節我們介紹了redolog,其主要用來實現持久性。那麼如果事務執行過程中出錯,那麼我們如何得到事務開始時的數據呢,這就要用到接下來所說的undolog。

  • undolog存放位置

datadir目錄/ibdata*(即默認存在於系統表空間),也可通過一下參數修改:

  • undolog產生的時機和內容

  1. 產生時機:在數據修改時,會記錄相應的undolog。如果操作的非臨時表,則記錄undolog的操作也會記錄redolog。
  2. 內容:老版本數據。可以認爲當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。
  • undolog的作用

redolog保證了事務一旦提交,則其所有的修改必然同步到數據文件。而undolog則是針對事務失敗情況,將贖回恢復到事務開始狀態。

  1. 事務回滾。
  2. MVCC。

三、其他

  • 日誌分層

binlog屬於Server層產生,所有存儲引擎都有。而redolog和undolog是InnoDB引擎特有。

  • redolog和binlog寫入順序,redolog的兩階段提交(引用《MYSQL實戰45講》02篇)

假設有這樣一條SQL:UPDATE t  SET  x=x+1   WHERE id=1,其執行流程如下:

  1. 執行器將命令發送給執行引擎InnoDB。
  2. InnoDB引擎從磁盤上查詢到t表id=1對應的行數據並將其加載到內存返回給執行器。
  3. 執行器拿到數據之後將x值加1,產生一個新的數據行,並調用InnoDB引擎的接口寫入這個數據行。
  4. InnoDB引擎將這行新數據保存到內存,並記錄一條redo_log日誌,此時redolog處於prepare狀態。
  5. InnoDB引擎告知執行器可以隨時提交事務。
  6. 執行器生成這個操作的binlog。並把binlog寫入磁盤。
  7. 執行器調用InnoDB引擎的事務提交接口,並將redolog狀態改爲commit,更新完成。

可以看出“兩階段提交”體現在:redolog處於prepare狀態---寫binglog---redolog處於commit狀態。這樣做的目的也是爲了保證數據一致性,即binlog中的操作和數據文件中對應的數據是一致的,以免日後利用binlog做數據恢復時,數據不完整。我們借用《MYSQL實戰45講》02篇的反證法來說明一下,假如不按照兩階段提交,會有什麼問題:

  1. 假如先寫完redolog再寫binlog。這種情況當redolog寫完之後,如果MYSQL服務故障,導致沒有寫入binlog。。當MYSQL服務故障恢復之後,可以根據redolog將數據恢復,但是binlog將永遠丟失這條數據。日後如果根據binlog做數據恢復,那該條數據流丟失。
  2. 假如先寫完binlog再寫redolog。這種情況當binlog寫完之後,如果MYSQL服務故障,導致沒有寫入redolog。當MYSQL服務故障恢復之後,由於redolog中沒有該條記錄,這條數據將不存在。但是binlog確有這條數據。日後如果根據binlog做數據恢復,那將會多出這條數據。

 

 

本文只是簡單介紹了InnoDB引擎的三種日誌。後續也會專門寫事務和MVCC的博文,來探索事務是如何藉助日誌來實現其特性的,以及MVCC的實現原理。

如果你想進一步瞭解,例如各種日誌的數據結構,請參考一下文章:

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

參考文章:

  1. <<MYSQL實戰45講>>02篇
  2. redolog是什麼:https://zhuanlan.zhihu.com/p/35355751
  3. 詳細分析MySQL事務日式:https://www.cnblogs.com/DataArt/p/10209573.html
  4. InnoDB.undolog漫遊:http://mysql.taobao.org/monthly/2015/04/01/
  5. InnoDB.redolog漫遊:http://mysql.taobao.org/monthly/2015/05/01/

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章