1. 程式人生 > 其它 >mysql redo日誌與刷髒

mysql redo日誌與刷髒

1.redo日誌

為了在伺服器崩潰時保證資料安全並提升系統性能,innodb儲存引擎首先會將提交的事物內容記錄到redo日誌,而對實際資料檔案修改則放在以後,批處理方式刷盤。redo日誌像邏輯的儲存場所,它迴圈使用多個檔案。(ib_logfile0、ib_logfile1、ib_logfile2)

innodb_log_file_size #各日誌檔案大小

innodb_log_files_in_group #日誌檔案的個數,innodb最終可用的日誌大小為innodb_log_file_size *innodb_log_files_in_group

innodb_log_group_home_dir #日誌目錄

redo日誌空間越大,innodb緩衝池中就可以停留更多的“髒頁”。這樣,innodb緩衝池的髒頁就可以更大批量的新式重新整理到磁碟。由於mysql5.5redo日誌可用空間最大為4GB,所以在擁有大容量快取的innodb中,工作效率並不高。mysql5.6開始允許使用者設定4GB以上redo日誌,innodb_log_file_size *innodb_log_files_in_group組合最大可以為512GB.這樣,當在擁有大量快取空間時髒頁可以更有效發揮寫緩衝作用。

2.刷髒

在innodb中處理使用者查詢後,其結果在記憶體空間的緩衝池已經發生變化,但是還未記錄到磁碟。這種頁面稱為髒頁,將髒頁記錄到磁碟的過程稱為刷髒。刷髒分兩種演算法:flush-list(依據時間管理緩衝池中更改頁面的列表)LRU-list(用於管理緩衝池中非常用頁面的列表)

(1)flush-list根據RDBMSredo日誌的工作方式(write Ahead Log),在redo日誌與髒頁中,redo日誌總要首先被完全刷到磁碟時,才能再次使用與該髒頁相關的redo日誌槽。此時為了在緩衝池中快速查詢髒頁,會根據髒頁的修改時間順序維護一個連結串列,該連結串列稱為flush-list。

(2)假如innodb的緩衝池全部由資料頁和索引填滿,innodb緩衝池沒有空閒空間。此情形下,一個新查詢到來,這時為了執行該查詢,innodb儲存引擎必須從緩衝池中刪除幾個已經載入的頁面,innodb不會隨意刪除,innodb管理著LRU-list連結串列,需要刪除時會從該連結串列選擇。LRU-list維護著最近不常用的頁面列表。LRU-list分為兩個區域,MRU和LRU。MRU位於LRU-list的5/8之前,其餘部分為LRU。也就是5/8之前儲存著常用的頁面,其餘3/8為不常用頁面(可以修改innodb_old_blocks_pct系統變數值控制MRU與LRU之間的分割點,預設值為5/8)。刪除內容會在最不常用連結串列的末端刪除幾個頁面。刪除之前會進行刷髒。

mysql5.6開始引入了page cleaner執行緒,專門負責刷髒:

1)緩衝池無空閒空間時,就會依據LRU_list將最近最少使用的頁面重新整理到磁碟,要 刷髒頁的順序由LRU_list管理。

2)flush_list連結串列會依據變更的時間順序對髒頁進行管理,並使用xxx演算法重新整理flush_list中的頁面。

mysql5.6的innodb針對LRU_list重新整理引入了innodb_lru_scan_depth系統變數,該變數可以針對每個緩衝池例項分別進行設定,查詢page cleaner執行緒要重新整理的髒頁時。可以藉助該變數設定要在LRU_list中掃描的頁數。IO比較閒的伺服器可以設定大點,寫入多,緩衝池大適當減小。

innodb緩衝池中可保留的髒頁數由redo日誌大小總和確定,同樣,flush_list中可保留的頁面總量也由innodb中redo日誌大小總和決定。

為了在innodb的redo日誌檔案中留下適合大小的空閒空間,就要不斷重新整理flush_list中的髒頁。但是重新整理過多會導致緩衝池效率下降。如果重新整理太慢,又很難保證innodb的redo日誌有足夠的空閒空間。當innodbredo日誌中的空閒空間即將耗盡,mysql的所有查詢都會進入阻止狀態,innodb儲存引擎會拼命將flush_list中的髒頁重新整理到磁碟。為了防止出現這一情況,在保證innodb redo日誌有空閒空間的同時,又要讓快取保留適當髒頁,並定期進行管理。

mysql5.6的innodb提供了innodb_io_capacity與innodb_io_capacity_max以使後臺執行緒可以控制髒頁重新整理。

root@localhost:mysql3316.sock  14:14:28 [(none)]>show global variables like "innodb_io_capacity%";
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_io_capacity     | 2000  |
| innodb_io_capacity_max | 4000  |
+------------------------+-------+

innodb_io_capacity,與緩衝池中的髒頁或change buffer的索引合併一樣,需要將許多這樣的資料記錄到磁碟,這些工作全部由innodb後臺執行緒負責處理。innodb的後臺執行緒處理這些操作並寫磁碟時,通過innodb_io_capacity可以限制允許的最大寫磁碟頁數。此值,若設定太大,緩衝池的髒資料會快速重新整理到磁碟,設定太小,緩衝池的全部髒頁數就會增加,redo空閒空間就會減少。

innodb_io_capacity_max,與innodb redo日誌的增長量相比,若髒頁重新整理延遲,innodb就會更激進的執行重新整理工作,可能會超過innodb_io_capacity指定的IOPS值,這種危急情況下,innodb_io_capacity_max系統變數用於設定允許的最大iops,這樣,即使發生IO爆發,也能保證磁碟IO不會耗盡所有系統資源。