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不會耗盡所有系統資源。
