本文將探討以下幾個問題。
一、思考
- 問題一: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。
- 數據定義:即CREATE、ALTER、DROP、TRUNCATE、RENAME操作。
- 數據操作:INSERT、UPDATE、DELETE。
接下來,我們以INSERT爲例,查看binlog記錄的內容:
插入語句爲:INSERT INTO role (`name`,`desc`) VALUES ('a','b');
通過mysqlbinlog工具打開mylog.0000001文件內容如下:
-
binlog文件作用
- 主從複製。
- 數據恢復。
這裏只是瞭解,後面會專門寫一篇主從複製和數據恢復相關內容。
2.2redolog
-
redolog產生背景
當修改DB某一行數據時,會先將該數據從磁盤讀取到內存中的緩衝池進行修改,這時內存中的值與磁盤中的值相比就有了差異,這種有差異性的數據也被稱之爲“髒頁”。這種差異性導致,當內存中的緩衝數據還未刷新到磁盤中,此時如果系統崩潰,便會造成數據丟失。redolog便是爲了解決這樣的問題。
-
redolog存放位置
datadir目錄/ib_logfile*文件中。
-
redolog產生的時機和內容
- 產生時機:事務完全提交之前。當我們提交一個事務時,InnoDB會先將修改的數據寫入到日誌文件中,再去修改內存中的緩衝區的數據。
- 內容: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的產生流程是怎樣的?
- 查詢磁盤數據到內存中的緩存區。
- 修改數據,依然保存到緩存。
- 事務提交時,先生成一條redolog日誌。
- 根據innodb_flush_log_at_trx_commit參數,執行對應的策略,將日誌寫入到文件。
- 提交事務。
- 將內存中的更新後的數據寫入到文件。
-
redolog的作用
redolog可以進行數據恢復,因爲其保存了數據被修改之後的值,這樣當DB故障或者操作系統故障修復之後,便能通過該日誌恢復之前的操作。事務的持久性也是通過redolog實現的,這種機制被稱之爲“Force log at commint”,即事務在提交之前必須成功寫入redolog。
後面會寫一篇博文專門分析事務的實現原理。
2.3undolog
在上一小節我們介紹了redolog,其主要用來實現持久性。那麼如果事務執行過程中出錯,那麼我們如何得到事務開始時的數據呢,這就要用到接下來所說的undolog。
-
undolog存放位置
datadir目錄/ibdata*(即默認存在於系統表空間),也可通過一下參數修改:
-
undolog產生的時機和內容
- 產生時機:在數據修改時,會記錄相應的undolog。如果操作的非臨時表,則記錄undolog的操作也會記錄redolog。
- 內容:老版本數據。可以認爲當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。
-
undolog的作用
redolog保證了事務一旦提交,則其所有的修改必然同步到數據文件。而undolog則是針對事務失敗情況,將贖回恢復到事務開始狀態。
- 事務回滾。
- MVCC。
三、其他
- 日誌分層
binlog屬於Server層產生,所有存儲引擎都有。而redolog和undolog是InnoDB引擎特有。
- redolog和binlog寫入順序,redolog的兩階段提交(引用《MYSQL實戰45講》02篇)
假設有這樣一條SQL:UPDATE t SET x=x+1 WHERE id=1,其執行流程如下:
- 執行器將命令發送給執行引擎InnoDB。
- InnoDB引擎從磁盤上查詢到t表id=1對應的行數據並將其加載到內存返回給執行器。
- 執行器拿到數據之後將x值加1,產生一個新的數據行,並調用InnoDB引擎的接口寫入這個數據行。
- InnoDB引擎將這行新數據保存到內存,並記錄一條redo_log日誌,此時redolog處於prepare狀態。
- InnoDB引擎告知執行器可以隨時提交事務。
- 執行器生成這個操作的binlog。並把binlog寫入磁盤。
- 執行器調用InnoDB引擎的事務提交接口,並將redolog狀態改爲commit,更新完成。
可以看出“兩階段提交”體現在:redolog處於prepare狀態---寫binglog---redolog處於commit狀態。這樣做的目的也是爲了保證數據一致性,即binlog中的操作和數據文件中對應的數據是一致的,以免日後利用binlog做數據恢復時,數據不完整。我們借用《MYSQL實戰45講》02篇的反證法來說明一下,假如不按照兩階段提交,會有什麼問題:
- 假如先寫完redolog再寫binlog。這種情況當redolog寫完之後,如果MYSQL服務故障,導致沒有寫入binlog。。當MYSQL服務故障恢復之後,可以根據redolog將數據恢復,但是binlog將永遠丟失這條數據。日後如果根據binlog做數據恢復,那該條數據流丟失。
- 假如先寫完binlog再寫redolog。這種情況當binlog寫完之後,如果MYSQL服務故障,導致沒有寫入redolog。當MYSQL服務故障恢復之後,由於redolog中沒有該條記錄,這條數據將不存在。但是binlog確有這條數據。日後如果根據binlog做數據恢復,那將會多出這條數據。
本文只是簡單介紹了InnoDB引擎的三種日誌。後續也會專門寫事務和MVCC的博文,來探索事務是如何藉助日誌來實現其特性的,以及MVCC的實現原理。
如果你想進一步瞭解,例如各種日誌的數據結構,請參考一下文章:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
參考文章:
- <<MYSQL實戰45講>>02篇
- redolog是什麼:https://zhuanlan.zhihu.com/p/35355751
- 詳細分析MySQL事務日式:https://www.cnblogs.com/DataArt/p/10209573.html
- InnoDB.undolog漫遊:http://mysql.taobao.org/monthly/2015/04/01/
- InnoDB.redolog漫遊:http://mysql.taobao.org/monthly/2015/05/01/