什麼是InnoDB交易記錄
你有沒有在文字編輯器中使用過撤消或重做的功能,想像一下編輯器在那種情境下的操作?我確信你應該使用過。你相信嗎?事務型資料庫有同樣的功能。可能不完全一樣,但原理是相同的。
就像當你編輯文字時始終有能力撤消數步的重要性一樣,重做和撤消功能也對事務型資料一樣重要。為什麼呢?主要有兩個原因:
1.復原事務(那是撤消)
2.在資料庫崩潰的情況下回放已提交的事務(那是重做)
撤消
當你使用的是事務儲存引擎(假設是InnoDB),你更改一個記錄時,更改並沒有馬上寫入資料檔案。
首先,它們被寫入到一個硬碟上特定的檔案叫做交易記錄。同時,它們也更改了記憶體 – InnoDB緩衝池。現在新InnoDB頁麵包含了已更改的記錄叫髒資料。
被複製到硬碟上特別地區的原始未被更改的頁面叫做復原段。
如果有人在提交之前使用ROLLBACK中斷了一個事務,撤消操作就發生了 – 你的記錄已經被還原到原始狀態。
由於更改還沒有被寫入到資料檔案,這個操作相當簡單 – InnoDB僅僅需要從復原段中提取舊頁面,從記憶體中擦除髒頁,並在交易記錄中標記那個事務已經復原。
所以你看,資料檔案從沒有被更改,因為在執行隨機寫操作以把髒資料重新整理到硬碟之前你已經把所有更改取消了。
重做
當你提交事務,然後InnoDB確認你的提交,更改準備寫入到實際的資料檔案。
現在你認為它們會被馬上寫入到硬碟的資料檔案,事實上不是這樣的。為什嗎?因為這樣做效率非常低。反而,更改僅僅被寫入到交易記錄(因為是順序寫,速度會很快,稱為重做日誌記錄),而更改的記錄仍然在日誌中 – InnoDB緩衝池的髒頁,過一定的時間才重新整理到硬碟。
這時候MySQL崩潰了!
猜猜MySQL會怎樣做?
如果MySQL(實際上是InnoDB)沒有重做日誌,僅僅是保留了髒頁在記憶體中 – 所有未被重新整理到硬碟已提交的事務將會永久丟失。
幸運的是,所以的更改總會寫入到交易記錄,
所以InnoDB需要做的就是在重做日誌中找到上一次的checkpoint(已同步資料到硬碟的位置),然後重做未同步到硬碟已提交的事務。
日誌大小
你可能想知道的一個事就是如何正確設定innodb_log_file_size的大小。規則很簡單:
* 小記錄檔使寫入速度更慢,崩潰恢複速度更快
* 大記錄檔使寫入更快,崩潰恢複速度更慢
由於交易記錄相當於一個寫緩衝,而小記錄檔會很快的被寫滿,這時候就需要頻繁地重新整理到硬碟,速度就慢了。如果產生大量的寫操作,MySQL可能就不能足夠快地重新整理資料,那麼寫效能將會降低。
大的記錄檔,另一方面,在重新整理操作發生之前給你足夠的空間來使用。反過來允許InnoDB填充更多的頁面。
對於崩潰恢複 – 大的重做日誌意味著在伺服器啟動前更多的資料需要讀取,更多的更改需要重做,這就是為什麼崩潰恢複慢了。
重做日誌大小
最後,讓我們來談談如何找出重做日誌的正確大小。
幸運的是,你不需要費力算出正確的大小,這裡有一個經驗法則:
在伺服器繁忙期間,檢查重做日誌的總大小是否夠寫入1-2小時。
你如何知道InnoDB寫入多少,下面有一個方法:
mysql> pager grep seq
mysql> show engine innodb status\G select sleep(60); show engine innodb status\G
Log sequence number 1777308180429
...
Log sequence number 1777354541591
mysql> nopager
mysql> select (1777354541591-1777308180429)*60/1024/1024;
+--------------------------------------------+
| (1777354541591-1777308180429)*60/1024/1024 |
+--------------------------------------------+
| 2652.80696869 |
+--------------------------------------------+
1 row in set (0.00 sec)
在這個60s的採樣情況下,InnoDB每小時寫入2.6GB資料。所以如果innodb_log_files_in_group沒有更改(預設是2,是InnoDB重複日誌的最小數字),然後設定innodb_log_file_size為2560M,那麼你實際上兩個記錄檔加起來有5GB,夠你寫兩小時資料了。
更改重做日誌大小
更改innodb_log_file_size的難易程度和能設定多大取決於你現在使用的MySQL版本。
特別地,如果你使用的是5.6之前的版本,你不能僅僅的更改變數,期望伺服器會自動重啟。
好了,下面是步驟:
1.在my.cnf更改innodb_log_file_size
2.停止mysql伺服器
3.刪除舊的日誌,通過執行命令rm -f /var/lib/mysql/ib_logfile*
4.啟動mysql伺服器 – 應該需要比之前長點的時間,因為需要建立新的交易記錄。
最後,需要注意的是,有些mysql版本(比如5.6.2)限制了重做日誌大小為4GB。所以在你設定innodb_log_file_size為2G或者更多時,請先檢查一下MySQL的版本這方面的限制。