天天看點

【mysql】InnoDB關鍵特性---兩次寫、自适應哈希和異步IO

上篇部落格總結了InnoDB的插入緩沖特性,這篇部落格總結關于InnoDB的另外三個特性兩次寫,自适應哈希和異步IO

兩次寫

Insert Buffer帶給InnoDB存儲引擎是性能上的提升,而double write帶給InnoDB的則是資料頁的可靠性。

産生背景

當InnoDB引擎正在寫入某個頁到表中時,這個頁隻寫了一部分發生了當機,這種情況被稱為部分寫失效。這種情況下,可以通過重做日志進行恢複,但是我們必須清楚的知道,重做日志中記錄的是對頁的實體操作,如偏移量800,寫’aaa’記錄。如果這個頁本身已經發生了損壞,在對其重做是沒有意義的。

【mysql】InnoDB關鍵特性---兩次寫、自适應哈希和異步IO

出現上面的問題,解決方案就是在應用重做日志之前,使用者需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁,再進行重做,這就是doublewrite.

double write實作

doublewrite有兩部分組成,一部分是記憶體中的doublewrite buffer,大小為2MB,另一部分是實體磁盤上共享表空間中連續的128個頁,即2個區,大小同樣為2MB。在對緩沖池的髒頁進行重新整理時,并不直接寫磁盤,而是會通過memcpy函數将髒頁先複制到記憶體中的doublewrite buffer,之後通過doublewrite buffer再分兩次,每次1MB順序的寫入共享表空間的實體磁盤上,然後馬上調用fsync函數,同步磁盤,避免緩沖寫帶來的問題。在這個過程中,因為doublewrite頁是連續的,是以這個過程是順序寫的,開銷并不是很大。在完成doublewrite頁的寫入後,再将doublewrite buffer中的頁寫入各個表空間中,此時的寫入是離散的。

【mysql】InnoDB關鍵特性---兩次寫、自适應哈希和異步IO

當寫時發生當機時,可以從共享表空間中的doublewrite找到該頁的一個副本,将其複制到表空間檔案(.ibd),再應用重做日志。

自适應哈希

哈希是一種非常快的查找方法,在一般情況下這種查找時間複雜度為O(1),即一般隻需要一次查找就能定位資料。而B+樹的查找次數,取決于B+樹的高的。

InnoDB存儲引擎會監控對表上的各索引頁的查詢,如果觀察到建立哈希索引可以帶來速度提升,則建立哈希索引,稱之為自适應哈希。

存儲引擎會根據通路的頻率和模式來自動地為某些熱點頁建立哈希索引。

通路模式一般指查詢條件如:

  • where a=xxx;
  • where a=xxx and b=xxx

會根據條件建立哈希索引,每個模式就是key值,根據hashcode,來指向不同的位址。

| 模式 | hashcode | 位址

| a=xxx | 0001 | 指向第一行

| a=xxx and b=xxx| 0002 | 指向第二行

每次通路的模式必須一樣, 以上兩種模式交替出現則不會建立自适應哈希。

當每個模式通路了100次,或者頁通過該模式通路了N次,其中N=頁中記錄*1/16時,也會建立自适應哈希。

可以通過innodb_adaptive_hash_index來考慮禁用或啟動此特性。

異步IO

為了提高磁盤操作性能,目前的資料庫系統都采用異步IO(AIO)的方式來處理磁盤操作。

異步IO提高磁盤性能舉例:

  • 當使用者進行索引掃描查詢時,這條sql語句可能需要掃描多個索引頁,也就是進行多次IO操作,如果是同步SIO,需要在每掃描一個頁并等待其完成後再進行下一次的掃描,這是沒有必要的,使用者可用在發出一個IO請求之後,再發出另一個IO請求,當全部IO請求發送完畢後,等待所有的IO操作完成即可。
  • 另一個優勢是IO Merge操作。也就是将多個IO合并為一個IO,可用提高IOPS性能。例如使用者需要通路(space,page_no)為:

    (8,6) (8,7) (8,8)

    每個頁大小為16KB,那麼同步IO需要進行3此IO操作。而AIO會判斷到這三個頁是連續的,是以可以發送一個IO請求,直接讀取48KB的頁。

異步IO的使用條件

  • 系統支援Native AIO,目前windows和linux都支援,但是MAC OSX不支援
  • 通過參數innodb_use_native_aio控制是否啟用。

以上是關于INNODB存儲引擎的三個特性的相關介紹。

插入緩沖詳見:

【mysql】InnoDB關鍵特性—插入緩沖

繼續閱讀