Mysql中的Redo Log解析(一)

  • 2019 年 11 月 6 日
  • 筆記

mysql中的redo log解析(一) 01

redo log是個啥?

Innodb是使用16k大小的數據頁來管理存儲空間的,數據頁也是記憶體和磁碟交互的最小單位。我們知道事務提交後是先將修改過的數據頁保存在記憶體中,然後再刷新到磁碟上進行持久化。我們還知道事務具有持久性的特性,那麼問題來了,如果事務提交之後,數據頁被保存在記憶體中,這個時候系統崩潰了,記憶體中的數據就沒有了,所做的修改就無法修復了,那麼事務的持久性也就沒有了。

redo log就是用來解決這個問題的。當然,有人會說,每次提交事務的之前先將記憶體中的修改刷新到磁碟上,然後再提交不久能解決這個問題了么?但是這裡有兩點需要注意:

1、刷新一個16k的數據頁太浪費時間了。

2、事務進行多處修改的時候,隨機IO刷盤比較慢。

基於上面的問題,redo log誕生了,它主要是將事務對數據頁所做的修改記錄在日誌裡面,這樣在機器重新恢復的時候能夠通過這些日誌將數據頁恢復出來,從而實現事務的持久性。

redo log有兩個特點:

第一,redo 日誌佔用的空間非常小,它只保存沒有刷新到磁碟上的操作內容。

第二,redo 日誌是順序寫入磁碟的。

02

redo log種類和寫入方法

在Innodb中,按照所做的修改不同,一共有幾十種redo log日誌,包含創建行記錄的redo日誌,刪除行記錄的redo日誌等等,而這每一項裡面,又包含很多子項,總之,我們需要了解的是,redo log的種類比較多,有幾十種,不超過128種。redo log一般保存在日誌文件ib_logfile0和ib_logfile1這種文件中,如下:

[root@ innodblog]# ll  total 4156540  -rw-r----- 1 mysql mysql 1073741824 Sep 28 11:34 ib_logfile0  -rw-r----- 1 mysql mysql 1073741824 Sep 18 08:14 ib_logfile1  -rw-r----- 1 mysql mysql 1073742918 Sep 20 01:13 mysqlbin.000129  -rw-r----- 1 mysql mysql 1035045773 Sep 28 11:34 mysqlbin.000130  -rw-r----- 1 mysql mysql         86 Sep 20 01:13 mysqlbin.index  

當然,我們可以修改ib_logfile的個數和大小以及存放路徑:

可以通過參數innodb_log_files_in_group來改變文件個數,這個參數的默認值是2;

可以通過參數innodb_log_file_size來指定每個redo日誌的大小;

可以通過參數innodb_log_group_home_dir指定redo日誌所在的目錄。

redo log文件組是通過下面這種循環的方式來進行進行文件存儲的,當文件組最後一個文件被寫滿的時候,會從第一個文件開始寫,之所以可以這樣操作,是因為數據一旦刷盤,那麼redo log中的日誌就沒有使用的意義了,也就可以被覆蓋寫了。

我們假設現在有一條insert的語句需要執行,在insert的時候,不僅僅會修改若干條記錄,還會修改索引和一些記錄之間的鏈表資訊,這樣,可能修改的就是多個頁面了,在這個過程中,如果某個數據頁已經滿了,再進行insert操作,還有可能發生數據頁的分裂。這樣,一條語句就會生成多條redo log,在Innodb中,通過一個Mini-Transaction(最小事務)的概念來劃分日誌組,這個Mini-Transaction(後面簡稱mtr)表示對底層頁面的一次原子訪問,也就是要麼成功,要麼失敗。從這個概念中我們可以看到,redo log可能不是一條一條的寫入磁碟的,是以組的概念進行寫入磁碟的,可能是一條,也可能是一次性多條。

我們知道,一個事務可以包含多個語句,一個語句中可以包含多個mtr,每一個mtr包含多個redo日誌,我們表示一下就是這樣:

先這麼多吧,有空了明兒再更新。