MySQL探祕(四):InnoDB的磁盤文件及落盤機制

 任何一個技術都有其底層的關鍵基礎技術,這些關鍵技術頗有可能也是其餘技術的關鍵技術,學習這些底層技術,就能夠一通百通,讓你很快的掌握其餘技術。如何在磁盤上存儲數據,如何使用日誌文件保證數據不丟失以及如何落盤,不只是MySQL等數據庫的關鍵技術,也是MQ消息隊列或者其餘中間件的關鍵技術之一。數據庫

InnoDB總體架構
 上圖詳細顯示了InnoDB存儲引擎的體系架構,從圖中可見,InnoDB存儲引擎由內存池,後臺線程和磁盤文件三大部分組成。接下來咱們就來簡單瞭解一下磁盤文件相關的概念和原理。

 InnoDB的主要的磁盤文件主要分爲三大塊:一是系統表空間,二是用戶表空間,三是redo日誌文件和歸檔文件。二進制文件(binlog)等文件是MySQL Server層維護的文件,因此未列入InnoDB的磁盤文件中。緩存

系統表空間和用戶表空間

 InnoDB系統表空間包含InnoDB數據字典(元數據以及相關對象)而且doublewrite buffer,change buffer,undo logs的存儲區域。系統表空間也默認包含任何用戶在系統表空間建立的表數據和索引數據。系統表空間是一個共享的表空間由於它是被多個表共享的安全

 系統表空間是由一個或者多個數據文件組成。默認狀況下,1個初始大小爲10MB,名爲ibdata1的系統數據文件在MySQL的data目錄下被建立。用戶可使用innodb_data_file_path對數據文件的大小和數量進行配置。bash

 innodb_data_file_path的格式以下:架構

innodb_data_file_path=datafile1[,datafile2]...
複製代碼

 用戶能夠經過多個文件組成一個表空間,同時制定文件的屬性:性能

innodb_data_file_path = /db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend
複製代碼

 這裏講/db/ibdata1和/dr2/db/ibdata2兩個文件組成系統表空間。若是這兩個文件位於不一樣的磁盤上,磁盤的負載可能被平均,所以能夠提升數據庫的總體性能。兩個文件的文件名以後都跟了屬性,表示文件ibdata1的大小爲1000MB,文件ibdata2的大小爲1000MB,並且用完空間以後能夠自動增加(autoextend)。學習

 設置innodb_data_file_path參數以後,因此基於InnoDB存儲引擎的表的數據都會記錄到該系統表空間中,若是設置了參數innodb_file_per_table,則用戶能夠將每一個基於InnoDB存儲引擎的表產生一個獨立的用戶表空間。用戶表空間的命名規則爲:表名.ibd。  經過這種方式,用戶不用將全部數據都存放於默認的系統表空間中,可是用戶表空只存儲該表的數據、索引和插入緩衝BITMAP等信息,其他信息仍是存放在默認的表空間中。spa

InnoDB表存儲引擎文件

 上圖顯示InnoDB存儲引擎對於文件的存儲方式,其中frm文件是表結構定義文件,記錄每一個表的表結構定義。操作系統

重作日誌文件和歸檔文件

 默認狀況下,在InnoDB存儲引擎的數據目錄下會有兩個名爲ib_logfile0和ib_logfile1的文件,這就是InnoDB的重作日誌文件(redo log fiel),它記錄了對於InnoDB存儲引擎的事務日誌。  當InnoDB的數據存儲文件發生錯誤時,重作日誌文件就能派上用場。InnoDB存儲引擎可使用重作日誌文件將數據恢復爲正確狀態,以此來保證數據的正確性和完整性。線程

 每一個InnoDB存儲引擎至少有1個重作日誌文件組(group),每一個文件組下至少有2個重作日誌文件,如默認的ib_logfile0和ib_logfile1。  爲了獲得更高的可靠性,用戶能夠設置多個鏡像日誌組,將不一樣的文件組放在不一樣的磁盤上,以此來提升重作日誌的高可用性。

 在日誌組中每一個重作日誌文件的大小一致,並以循環寫入的方式運行。InnoDB存儲引擎先寫入重作日誌文件1,當文件被寫滿時,會切換到重作日誌文件2,再當重作日誌文件2也被寫滿時,再切換到重作日誌文件1。

 用戶可使用innodb_log_file_size來設置重作日誌文件的大小,這對InnoDB存儲引擎的性能有着很是大的影響。

 若是重作日誌文件設置的太大,數據丟失時,恢復時可能須要很長的時間;另外一方面,若是設置的過小,重作日誌文件過小會致使依據checkpoint的檢查須要頻繁刷新髒頁到磁盤中,致使性能的抖動。  重作日誌相關和Checkpoint的機制能夠閱讀我以前文章的相應章節。MySQL探祕(三):InnoDB的內存結構和特性

重作日誌的落盤機制

 InnoDB對於數據文件和日誌文件的刷盤遵照WAL(Write ahead redo log) 和Force-log-at-commit兩種規則,兩者保證了事務的持久性。WAL要求數據的變動寫入到磁盤前,首先必須將內存中的日誌寫入到磁盤;Force-log-at-commit要求當一個事務提交時,全部產生的日誌都必須刷新到磁盤上,若是日誌刷新成功後,緩衝池中的數據刷新到磁盤前數據庫發生了宕機,那麼重啓時,數據庫能夠從日誌中恢復數據。

寫入機制

 如上圖所示,InnoDB在緩衝池中變動數據時,會首先將相關變動寫入重作日誌緩衝中,而後再按時或者當事務提交時寫入磁盤,這符合Force-log-at-commit原則;當重作日誌寫入磁盤後,緩衝池中的變動數據纔會依據checkpoint機制擇時寫入到磁盤中,這符合WAL原則。  在checkpoint擇時機制中,就有重作日誌文件寫滿的判斷,因此,如前文所述,若是重作日誌文件過小,常常被寫滿,就會頻繁致使checkpoint將更改的數據寫入磁盤,致使性能抖動。

 操做系統的文件系統是帶有緩存的,當InnoDB向磁盤寫入數據時,有可能只是寫入到了文件系統的緩存中,沒有真正的「落袋爲安」。  InnoDB的innodb_flush_log_at_trx_commit屬性能夠控制每次事務提交時InnoDB的行爲。當屬性值爲0時,事務提交時,不會對重作日誌進行寫入操做,而是等待主線程按時寫入;當屬性值爲1時,事務提交時,會將重作日誌寫入文件系統緩存,而且調用文件系統的fsync,將文件系統緩衝中的數據真正寫入磁盤存儲,確保不會出現數據丟失;當屬性值爲2時,事務提交時,也會將日誌文件寫入文件系統緩存,可是不會調用fsync,而是讓文件系統本身去判斷什麼時候將緩存寫入磁盤。日誌的刷盤機制以下圖所示。

log刷盤機制

 innodb_flush_log_at_commit是InnoDB性能調優的一個基礎參數,涉及InnoDB的寫入效率和數據安全。當參數值爲0時,寫入效率最高,可是數據安全最低;參數值爲1時,寫入效率最低,可是數據安全最高;參數值爲2時,兩者都是中等水平。通常建議將該屬性值設置爲1,以得到較高的數據安全性,並且也只有設置爲1,才能保證事務的持久性。

後記

 咱們後續還會學習binlog文件以及數據文件的落盤機制,還有InnoDB事務相關的其餘知識,請你們持續關注。

相關文章
相關標籤/搜索