天天看點

InnoDB體系結構之記憶體篇Innodb buffer poolChange buffer(Insert buffer)Double write buffer

    前言,對于計算機來說,CPU的運算速率要比記憶體讀寫速率快的多,記憶體的讀寫效率比磁盤的讀寫要快得多。為了解決CPU 

 運作效率與記憶體讀寫速度不比對的問題,就出現了CPU緩存。将記憶體中的一小部分資料在CPU中緩存起來,這樣就加快了CPU

處理資料的能力。其實在任意兩種速度相差較大的硬體/軟體之間的,都可以通過緩存來協調兩者資料傳輸速度的差異。

對于Innodb存儲引擎來說,也是通過這種緩存技術,将大部分的記憶體用作緩沖池,緩存熱點資料,提高其I/O的性能。

Innodb的緩沖池包括innodb buffer pool、change buffer,double write buffer、log buffer(放到後面的innodb的日志裡)

Innodb buffer pool

①  Innodb buffer pool是innodb裡空間最大,功能最重要的一個緩沖池。一般情況下,我們可以将其大小設定到實體記憶體的

50%~80%。通過innodb_buffer_pool_size來設定,5.7可以動态修改此參數,不需要重新開機mysqld程序。如果innodb buffer pool的

大小超過1個G,可以通過innodb_buffer_pool_instances來設定多個buffer pool執行個體,來提高buffer pool的管理性能。正常情況下

如果buffer pool小于16G,可以将其設定為4;大于16G,可以設定為8 。

innodb buffer pool中對資料頁的管理是通過三個連結清單來實作的,分别為FREE list、FLUSH list,LRU list。

FREE list :存儲空閑頁的連結清單

FLUSH list:對于已經修改過将要刷到磁盤的頁面

LRU list:緩存所有的熱點資料

show engine innodb status裡關于這幾個參數的對比:

InnoDB體系結構之記憶體篇Innodb buffer poolChange buffer(Insert buffer)Double write buffer

buffer pool size:表示緩沖池中有多少個page

free buffers:對應free list上的page

database pages:對應lru list上的page

old database pages:對應old隊列上的page

modified db pages:對應flush list上的髒頁數

② 接着,來看一下LRU list上的資料頁具體如何實作的

字面上LRU即Least Recently Used,最近最少使用。Innodb buffer pool就是通過這種最近最少使用(LRU)算法來實作對資料

頁的管理。首先,LRU list上面兩個list,young list和old list,通過參數innodb_old_block來控制兩個

表的比列。預設值是37%,即old list占3/8,前面5/8屬于young list。然後,當有新的資料頁被通路時,那麼該資料頁被插入

midpoint位置,即old list的頭部。然後通過參數innodb_old_blocks_time的值來控制新的資料頁是否能

被移到young list或者繼續留在old list裡。預設值1000ms。意思就是當新的資料頁在old list停留超過1s,1s之後又被通路,那麼

該資料頁就從old list轉移到young list .如下圖所示:

young list head ….. young list tail old list head …. old list tail

                                                                                                                      ↑

                                                                                                                 Midpoint

這樣就可以實作最經常通路的頁面在最前面,最不經常通路的頁面在最後面。

此外,當free list沒有空閑頁的時候,此時innodb會去掃描lru list,通過參數innodb_lru_scan_depth來控制掃描lru list上的髒頁

數,預設值是1024.這個是由page cleaner線程在背景異步的每秒重新整理一次,每秒重新整理的髒頁數就是

innodb_lru_scan_depth*innodb_buffer_pool_instances;當innodb裡面的髒頁數量達到innodb_max_dirty_page_pct該參數的值

時,也會觸發髒頁的重新整理,該參數預設值時75%。生産環境盡可能将這個值設為小于50%。

Change buffer(Insert buffer)

change buffer主要針對普通的非唯一索引來産生作用的。(對于查詢操作來說兩者性能其實是差不多的,主要對兩者的更新操作

來比較一下)

如果資料頁本身就在buffer pool中,那麼此時直接對記憶體頁進行操作,其實是用不到change buffer的;

如果資料頁不在buffer pool中,因為唯一索引要確定鍵值的唯一性,肯定是要先把該資料頁讀到記憶體中做一緻性判斷;但是普通

索引就可以直接在change buffer中記錄下相應的操作,事務就可以結束。然後等待merge線程去做合并資料頁的操作。merge的

具體實作就是将資料頁讀入buffer pool中,然後change buffer中記錄的操作應用到資料頁上。是以對于寫多讀少的業務來說,選

擇普通索引并且開啟change buffer可以明顯提高資料庫的性能。

InnoDB體系結構之記憶體篇Innodb buffer poolChange buffer(Insert buffer)Double write buffer

主要通過這兩個參數來控制。前者是change buffer占buffer pool的比列,後者是針

對的操作

Double write buffer

    由于innodb預設的的data page是16K,而磁盤的一次性寫入是按扇區的大小512個位元組。那麼innodb buffer pool中的資料頁在

往磁盤上刷盤的時候,就無法保證一次資料頁寫的完整性。為了解決寫入的完整性,innodb就通過double write buffer來保證數

據頁寫入的完整性。5.7中可以通過innodb_parallel_doublewrite_path來設定double write buffer檔案的位置,同時通過

innodb_doublewrite_batch_size來設定批量刷入double write buffer檔案的緩存大小。目前SSD硬碟的最小寫入機關塊的大小已

經有4K的了,而innodb的page size也可以調整為4K,如果硬碟能保證資料頁寫的完整性,也可以關閉double write buffer減少

I/O.。

繼續閱讀