InnoDB體系結構之記憶體篇

2021-09-19 13:46:52 字數 3023 閱讀 9321

前言,對於計算機來說,cpu

的運算速率要比記憶體讀寫速率快的多,記憶體的讀寫效率比磁碟的讀寫要快得多。為了解決

cpu

執行效率與記憶體讀寫速度不匹配的問題,就出現了cpu

快取。將記憶體中的一小部分資料在

cpu中快取起來,這樣就加快了

cpu

處理資料的能力。其實在任意兩種

速度相差較大的硬體

/軟體之間的,都可以通過快取來協調兩者資料傳輸速度的差異。 對於

innodb

儲存引擎來說,也是通過這種快取技術,將大部分的記憶體用作緩衝池,快取熱點資料,提高其

i/o的效能。

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

①  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裡關於這幾個引數的對比:

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主要針對普通的非唯一索引來產生作用的。(對於查詢操作來說兩者效能其實是差不多的,主要對兩者的更新操作

來比較一下)

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

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

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

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

擇普通索引並且開啟change 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.。

Innodb的體系結構

mysql的體系結構,兩部分組成 mysql的server層和儲存引擎層。儲存引擎層innodb體系結構 innodb的整個體系結構就是由多個記憶體塊組成的緩衝池及多個後台程序組成。我們可以從三方面來介紹 記憶體 執行緒 磁碟 記憶體 包含insert buffer data buffer inde...

oracle體系結構三部曲之記憶體結構

還是想嘮叨一下,要想把oracle體系結構學深學透,必須結合備份與恢復的實驗及原理去學,這個我在後續也會寫相應的blog。在這裡我在介紹記憶體結構時,只是做些基礎性的了解。我們先看兩個容易混淆的概念。sid和oracle sid,其實吧,這兩個沒啥本質的區別。若真個想分一分的話。那麼,sid是站點識...

oracle體系結構三部曲之記憶體結構

還是想嘮叨一下,要想把oracle體系結構學深學透,必須結合備份與恢復的實驗及原理去學,這個我在後續也會寫相應的blog。在這裡我在介紹記憶體結構時,只是做些基礎性的了解。我們先看兩個容易混淆的概念。sid和oracle sid,其實吧,這兩個沒啥本質的區別。若真個想分一分的話。那麼,sid是站點識...