1. 程式人生 > >mysql 5.7 undo redo 空間回收

mysql 5.7 undo redo 空間回收

undo redo 空間回收

InnoDB儲存引擎中,Undo log一直都是事務多版本控制中的核心元件,它具有以下的核心功能:

    事務的回退:事務在處理過程中遇到異常的時候可以rollback(撤銷)所做的全部修改。

    事務的恢復:資料庫例項崩潰時,將磁碟的不正確資料恢復到交易前。

    讀一致性:被查詢的記錄有事務佔用,轉向回滾段找事務開始前的資料映象。

Undo在完成事務回滾和MVCC之後,就可以purge掉了,在MySQL5.5以及之前,隨著資料庫上線時間越來越長,ibdata1檔案(即InnoDB的共享表空間,或者系統表空間)會越來越大,這會造成2個比較明顯的問題:

    1)磁碟剩餘空間越來越小,到後期往往要加磁碟;

    2)物理備份時間越來越長,備份檔案也越來越大。

如果要回收空間,就只能匯出來,匯入到新的例項中。非常不合理,要不就是增加磁碟空間解決ibdata1檔案的變大。

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

MySQL 5.6中開始支援把undo log分離到獨立的表空間,並放到單獨的檔案目錄下;這給我們部署不同IO型別的檔案位置帶來便利,對於併發寫入型負載,我們可以把undo檔案部署到單獨的高速儲存裝置上。增加了如下幾個引數來控制該行為。

mysql> show global variables like '%undo%'; +-------------------------+-------+   | Variable_name           | Value |   +-------------------------+-------+   | innodb_undo_directory   | .     |   | innodb_undo_logs        | 128   |   | innodb_undo_tablespaces | 0     |   +-------------------------+-------+ innodb_undo_directory=.       引數的預設值為”.”,表示當前InnoDB儲存引擎的目錄。轉移undo檔案的位置,只需要修改下該配置,並將undo檔案拷貝過去就可以了。

innodb_undo_logs=128 用來設定rollback segment(回滾段)的個數,預設為128。,該引數用來替換之前版本的引數innodb_rollback_segments。該變數可以動態調整,但是物理上的回滾段不會減少,只是會控制用到的回滾段的個數。

innodb_undo_tablespaces=0

用於設定建立的undo表空間的個數,也就是用來構成rollback segment檔案的數量,這樣rollback segment可以較為平均地分佈在多個檔案中。 在Install db時初始化後,就再也不能被改動了。預設值為0,表示不獨立設定undo的tablespace,預設記錄到ibdata中;否則,則在undo目錄下建立這麼多個undo檔案。

修改該值可能會導致Innodb無法完成初始化。 ---------------------------------------------------------------

MySQL 5.7引入了新的引數,innodb_undo_log_truncate,開啟後可線上收縮拆分出來的undo表空間。

在滿足以下2個條件下,undo表空間檔案可線上收縮:

1)innodb_undo_tablespaces>=2:因為truncate undo表空間時,該檔案處於inactive狀態,如果只有1個undo表空間,那麼整個系統在此過程中將處於不可用狀態。為了儘可能降低truncate對系統的影響,建議將該引數最少設定為3;

2)innodb_undo_logs>=35(預設128):因為在MySQL 5.7中,第一個undo log永遠在系統表空間中,另外32個undo log分配給了臨時表空間,即ibtmp1,至少還有2個undo log才能保證2個undo表空間中每個裡面至少有1個undo log;

滿足以上2個條件後,把innodb_undo_log_truncate設定為ON即可開啟undo表空間的自動truncate,這還跟如下2個引數有關:

1)innodb_max_undo_log_size:undo表空間檔案超過此值即標記為可收縮,預設1G,可線上修改;

2)innodb_purge_rseg_truncate_frequency:指定purge操作被喚起多少次之後才釋放rollback segments。當undo表空間裡面的rollback segments被釋放時,undo表空間才會被truncate。由此可見,該引數越小,undo表空間被嘗試truncate的頻率越高。

***********重點******************* 基本也就是InnoDB的purge執行緒,會根據innodb_undo_log_truncate開關的設定,和innodb_max_undo_log_size設定的檔案大小閾值,以及truncate的頻率來進行空間回收和rollback segment的重新初始化。直接刪除,將無法重啟。

mysql> show global variables like '%undo%'; +--------------------------+------------+ | Variable_name            | Value      | +--------------------------+------------+ | innodb_max_undo_log_size | 1073741824 | | innodb_undo_directory    | ./         | | innodb_undo_log_truncate | OFF        | | innodb_undo_logs         | 128        | | innodb_undo_tablespaces  | 0          | +--------------------------+------------+ 5 rows in set (0.00 sec)

mysql> show global variables like '%truncate%';   +--------------------------------------+-------+ | Variable_name                        | Value | +--------------------------------------+-------+ | innodb_purge_rseg_truncate_frequency | 128   | | innodb_undo_log_truncate             | OFF   | +--------------------------------------+-------+

======================================================================

redo log

為了最大程度避免資料寫入時io瓶頸帶來的效能問題,MySQL採用了這樣一種快取機制:當query修改資料庫內資料時,InnoDB先將該資料從磁碟讀取到記憶體中,修改記憶體中的資料拷貝,並將該修改行為持久化到磁碟上的事務日誌(先寫redo log buffer,再定期批量寫入),而不是每次都直接將修改過的資料記錄到硬碟內,等事務日誌持久化完成之後,記憶體中的髒資料可以慢慢刷回磁碟,稱之為Write-Ahead Logging。事務日誌採用的是追加寫入,順序io會帶來更好的效能優勢。

為了避免髒資料刷回磁碟過程中,掉電或系統故障帶來的資料丟失問題,InnoDB採用事務日誌(redo log)來解決該問題。

【redo log】

用於在例項故障恢復時,繼續那些已經commit但資料尚未完全回寫到磁碟的事務。

通常會初始化2個或更多的 ib_logfile 儲存 redo log,由引數 innodb_log_files_in_group 確定個數,命名從 ib_logfile0 開始,依次寫滿 ib_logfile 並順序重用(in a circular fashion)。如果最後1個 ib_logfile 被寫滿,而第一個ib_logfile 中所有記錄的事務對資料的變更已經被持久化到磁碟中,將清空並重用之。

在寫入量比較高的情況下,redo log 的大小將顯著地影響寫入效能。會被重用,固定大小,無需處理

innodb_log_file_size 用來控制 ib_logfile 的大小。5.5版本及以前:預設5MB,最大4G。

所有事務日誌累加大小不超過4G,事務日誌過大,checkpoint會減少,在節省磁碟io的同時,大的事務日誌也意味著資料庫crash後,恢復起來較慢。

可以直接刪除,啟動的時候會自動再建立。