mysql-innodb-內存結構

Buffer Pool

緩衝池是主內存中的一個區域,在InnoDB訪問表和索引數據時會在其中進行 緩存。緩衝池允許直接從內存中直接處理經常使用的數據,從而加快了處理速度。在專用服務器上,通常將多達80%的物理內存分配給緩衝池。

爲了提高大容量讀取操作的效率,緩衝池被分爲多個頁面,這些頁面可能包含多個行。爲了提高緩存管理的效率,緩衝池被實現爲page的鏈接列表。使用LRU算法的變體將很少使用的數據從緩存中老化掉 。

知道如何利用緩衝池將經常訪問的數據保留在內存中是MySQL優化的重要方面。

LRU算法

使用最近最少使用(LRU)算法的變體,將緩衝池作爲列表進行管理。當需要空間以將新頁面添加到緩衝池時,將驅逐最近使用最少的頁面,並將新頁面添加到列表的中間。此中點插入策略將列表視爲兩個子列表:

最前面是最近訪問過的新頁面(“ 年輕 ”) 的子列表

在末尾,是最近訪問的舊頁面的子列表
在這裏插入圖片描述

該算法將大量頁面保留在新的子列表中。舊的子列表包含較少使用的頁面。這些頁面是驅逐的候選對象 。

默認情況下,該算法的運行方式如下:

3/8的緩衝池專用於舊的子列表。

列表的中點是新子列表的尾部與舊子列表的頭相交的邊界。

當InnoDB將頁面讀入緩衝池時,它首先將其插入中點(舊子列表的頭部)。可以讀取頁面,因爲它是用戶啓動的操作(例如SQL查詢)所必需的,或作爲的自動執行的預讀操作的一部分 InnoDB。

訪問舊子列表中的頁面 使其變爲“ 年輕 ”,將其移至新子列表的頭部。如果由於用戶啓動的操作而需要讀取頁面,則將立即進行首次訪問,並使頁面年輕。如果由於預讀操作而讀取了該頁面,則第一次訪問不會立即發生,並且在退出該頁面之前可能根本不會發生。

隨着數據庫的運行,通過移至列表的尾部,緩衝池中未被訪問的頁面將“ 老化 ”。新的和舊的子列表中的頁面都會隨着其他頁面的更新而老化。隨着將頁面插入中點,舊子列表中的頁面也會老化。最終,未使用的頁面到達舊子列表的尾部並被逐出。

默認情況下,查詢讀取的頁面會立即移入新的子列表,這意味着它們在緩衝池中的停留時間更長。例如,針對mysqldump操作或SELECT不帶WHERE子句的 語句 執行的表掃描可以將大量數據帶入緩衝池,並驅逐同等數量的舊數據,即使不再使用新數據也是如此。同樣,由預讀後臺線程加載且僅訪問一次的頁面將移到新列表的開頭。這些情況可能會將常用頁面推送到舊的子列表,在此它們會被逐出。有關優化此行爲的信息,請參見 第14.8.3.3節“使緩衝池掃描具有抵抗力”和 第14.8.3.4節“配置InnoDB緩衝池預取(預讀)”。

InnoDB標準監視器輸出在BUFFER POOL AND MEMORY有關緩衝池LRU算法操作的部分中包含幾個字段。有關詳細信息,請參閱使用InnoDB Standard Monitor監視緩衝池。

緩衝池配置

理想情況下,您可以將緩衝池的大小設置爲與實際一樣大的值,從而爲服務器上的其他進程留出足夠的內存以運行而不會進行過多的分頁。緩衝池越大,就越InnoDB像內存數據庫一樣,從磁盤讀取一次數據,然後在後續讀取期間從內存訪問數據。請參見 第14.8.3.1節“配置InnoDB緩衝池大小”。

在具有足夠內存的64位系統上,可以將緩衝池分成多個部分,以最大程度地減少併發操作之間的內存結構爭用。有關詳細信息,請參見第14.8.3.2節“配置多個緩衝池實例”。

您可以將頻繁訪問的數據保留在內存中,而不必考慮操作突然導致的活動高峯,這些操作會將大量不經常訪問的數據帶入緩衝池。有關詳細信息,請參見 第14.8.3.3節“使緩衝池掃描具有抵抗力”。

您可以控制何時以及如何執行預讀請求,以異步方式將頁面預取到緩衝池中,從而預期很快將需要這些頁面。有關詳細信息,請參見第14.8.3.4節“配置InnoDB緩衝池預取(預讀)”。

您可以控制何時進行後臺沖洗,以及是否根據工作負荷動態調整沖洗速率。有關詳細信息,請參見 第14.8.3.5節“配置緩衝池刷新”。

您可以配置如何InnoDB保留當前緩衝池狀態,以免在服務器重新啓動後進行冗長的預熱。有關詳細信息,請參見 第14.8.3.6節“保存和恢復緩衝池狀態”。

配置buffer pool大小

您可以InnoDB在服務器運行時脫機(啓動時)或聯機配置緩衝池大小。本節中描述的行爲適用於兩種方法。有關在線配置緩衝池大小的更多信息,

當增加或減
少時 innodb_buffer_pool_size,將按塊執行操作。塊大小由innodb_buffer_pool_chunk_size 配置選項定義 ,其默認值爲 128M。有關更多信息,請參見 配置InnoDB緩衝池塊大小。

緩衝池大小必須始終等於innodb_buffer_pool_chunk_size* 或* 的倍數 innodb_buffer_pool_instances。如果配置 innodb_buffer_pool_size爲不等於innodb_buffer_pool_chunk_size* 或 * innodb_buffer_pool_instances的值,則緩衝池大小將自動調整爲等於innodb_buffer_pool_chunk_size* 或 *的值 innodb_buffer_pool_instances。

在以下示例中, innodb_buffer_pool_size設置爲8G,並且 innodb_buffer_pool_instances設置爲16。 innodb_buffer_pool_chunk_size 是128M,這是默認值。

8G是有效值, innodb_buffer_pool_size因爲它是 * 8G的倍數 ,即。 innodb_buffer_pool_instances=16innodb_buffer_pool_chunk_size=128M2G

在線配置InnoDB緩衝池大小

該innodb_buffer_pool_size 配置選項可以動態使用設置 SET聲明,讓您調整緩衝池無需重新啓動服務器。例如:

mysql> SET GLOBAL innodb_buffer_pool_size=402653184;
活動交易和通過執行的操作 InnoDB在調整緩衝池大小之前,應先完成API。啓動調整大小操作時,該操作直到所有活動事務完成後纔開始。調整大小操作正在進行後,需要訪問緩衝池的新事務和操作必須等待直到調整大小操作完成。該規則的例外是,在對緩衝池進行碎片整理時,允許併發訪問緩衝池;在減小緩衝池大小時,將撤回頁面。允許併發訪問的缺點是,在撤回頁面時,這可能會導致可用頁面的暫時短缺。

注意
如果在緩衝池調整大小操作開始後啓動嵌套事務,則事務可能失敗。

Change Buffer

更改緩衝區是一種特殊的數據結構,當二級索引頁不在緩衝池中時,它們 會緩存這些更改 。當頁面通過其他讀取操作加載到緩衝池中時,可能由INSERT, UPDATE或 DELETE操作(DML)導致的緩衝更改 將在以後合併。

圖14.3更改緩衝區
在這裏插入圖片描述
內容在周圍的文字中描述。

與聚簇索引不同,二級索引通常是非唯一的,並且二級索引中的插入以相對隨機的順序發生。同樣,刪除和更新可能會影響索引樹中不相鄰的二級索引頁。當稍後通過其他操作將受影響的頁讀入緩衝池時,合併緩存的更改將避免從磁盤將輔助索引頁讀入緩衝池所需的大量隨機訪問I / O。

在系統大部分處於空閒狀態或緩慢關閉期間運行的清除操作會定期將更新的索引頁寫入磁盤。與將每個值立即寫入磁盤相比,清除操作可以更有效地爲一系列索引值寫入磁盤塊。

當有許多受影響的行和許多輔助索引要更新時,更改緩衝區合併可能需要幾個小時。在此期間,磁盤I / O會增加,這可能會導致磁盤綁定查詢的速度大大降低。提交事務之後,甚至在服務器關閉並重新啓動之後,更改緩衝區合併也可能繼續發生( 有關更多信息,請參見第14.22.2節“強制InnoDB恢復”)。

在內存中,更改緩衝區佔用了緩衝池的一部分。在磁盤上,更改緩衝區是系統表空間的一部分,當數據庫服務器關閉時,索引更改將存儲在其中。

更改緩衝區中緩存的數據類型由 innodb_change_buffering變量控制。有關更多信息,請參見 配置變更緩衝。您還可以配置最大更改緩衝區大小。有關更多信息,請參見 配置更改緩衝區最大大小。

如果索引包含降序索引列或主鍵包含降序索引列,則輔助索引不支持更改緩衝。

有關更改緩衝區的常見問題的答案,請參見第A.16節“ MySQL 5.7 FAQ:InnoDB更改緩衝區”。

哪些類型的操作會修改二級索引並導致更改緩衝?

INSERT,,UPDATE和 DELETE操作可以修改二級索引。如果受影響的索引頁不在緩衝池中,則可以將更改緩衝在更改緩衝區中。

  • InnoDB更改緩衝區 的好處是什麼?

當二級索引頁不在緩衝池中時,對二級索引更改進行緩衝可以避免昂貴的隨機訪問I / O操作,該操作可能需要立即從磁盤中讀取受影響的索引頁。當頁面被其他讀取操作讀取到緩衝池中時,緩衝的更改可以稍後批量應用。

-更改緩衝區是否支持其他類型的索引?

否。更改緩衝區僅支持二級索引。不支持聚簇索引,全文索引和空間索引。全文索引具有自己的緩存機制。

  • InnoDB更改緩衝區使用 多少空間?

innodb_change_buffer_max_size 在MySQL 5.6中 引入配置選項之前, 系統表空間中磁盤更改緩衝區的最大大小爲InnoDB緩衝池大小的1/3 。

在MySQL 5.6和更高版本中, innodb_change_buffer_max_size 配置選項將更改緩衝區的最大大小定義爲總緩衝池大小的百分比。默認情況下, innodb_change_buffer_max_size 設置爲25。最大設置爲50。

InnoDB 如果會導致磁盤上的更改緩衝區超過定義的限制,則不會緩衝操作。

更改緩衝區頁不需要保留在緩衝池中,並且可以由LRU操作逐出。

  • 如何確定更改緩衝區的當前大小?

標題SHOW ENGINE INNODB STATUS \G下的 會報告更改緩衝區的當前大小 INSERT BUFFER AND ADAPTIVE HASH INDEX。例如:

  • 插入緩衝區和自適應哈希索引

Ibuf:大小1,空閒列表len 0,seg大小2,0合併
相關數據點包括:

size:更改緩衝區內使用的頁數。更改緩衝區的大小等於seg size - (1 + free list len)。該1 +值表示更改緩衝區標題頁。

seg size:更改緩衝區的大小(以頁爲單位)。

有關監視更改緩衝區狀態的信息,請參見 第14.5.2節“更改緩衝區”。

  • 何時發生更改緩衝區合併?

將頁面讀入緩衝池時,在頁面可用之前,緩衝的更改會在讀取完成後合併。

更改緩衝區合併作爲後臺任務執行。該 innodb_io_capacity 參數設置由InnoDB後臺任務執行的I / O活動的上限,例如合併來自更改緩衝區的數據。

在崩潰恢復期間執行更改緩衝區合併。當將索引頁讀入緩衝池時,更改將從更改緩衝區(在系統表空間中)應用於輔助索引的葉頁。

更改緩衝區是完全耐用的,並且可以在系統崩潰後倖免。重新啓動後,更改緩衝區合併操作將恢復爲正常操作的一部分。

可以使用強制將更改緩衝區完全合併爲緩慢的服務器關閉的一部分 --innodb-fast-shutdown=0。

  • 更改緩衝區何時刷新?

更新的頁面將通過與刷新佔用緩衝池的其他頁面相同的刷新機制進行刷新。

  • 何時應使用更改緩衝區?

更改緩衝區是一項旨在減少隨索引變大而不再適合InnoDB緩衝池的二級索引的隨機I / O的功能。通常,當整個數據集不能容納到緩衝池中時,當大量的DML活動會修改二級索引頁面時,或者當許多二級索引因DML活動而定期更改時,都應使用更改緩衝區。

  • 什麼時候不應該使用更改緩衝區?

如果整個數據集都適合InnoDB緩衝池,或者二級索引相對較少,或者您使用的是固態存儲(其中隨機讀取的速度與順序讀取的速度差不多),則可以考慮禁用更改緩衝區。在進行配置更改之前,建議您使用具有代表性的工作負載運行測試,以確定禁用更改緩衝區是否可以帶來任何好處。

配置變更緩衝
在表上執行,和 操作時INSERT, 索引列的值(尤其是輔助鍵的值)通常處於未排序的順序,需要大量的I / O才能使輔助索引保持最新狀態。當相關頁面不在 緩衝池中時,更改緩衝區將 更改緩存到輔助索引條目 ,從而避免了不立即從磁盤讀取頁面而避免了昂貴的I / O操作。當頁面加載到緩衝池中時,緩衝的更改將合併,更新的頁面隨後將刷新到磁盤。的UPDATEDELETEInnoDB當服務器接近空閒時以及在緩慢關閉期間,主線程會合並緩衝的更改 。

由於更改緩衝區功能可以減少磁盤讀寫操作,因此它對於受I / O約束的工作負載(例如,具有大量DML操作的應用程序,例如批量插入)最有價值。

但是,更改緩衝區佔用了緩衝池的一部分,從而減少了可用於緩存數據頁的內存。如果工作集幾乎適合緩衝池,或者您的表具有相對較少的二級索引,則禁用更改緩衝可能很有用。如果工作數據集完全適合緩衝池,則更改緩衝不會帶來額外的開銷,因爲它僅適用於不在緩衝池中的頁面。

您可以InnoDB 使用innodb_change_buffering 配置參數來控制執行更改緩衝 的程度。您可以爲插入,刪除操作(最初將索引記錄標記爲刪除)和清除操作(物理刪除索引記錄)啓用或禁用緩衝。更新操作是插入和刪除的組合。默認 innodb_change_buffering值爲 all。

允許的innodb_change_buffering 值包括:

all

默認值:緩衝區插入,刪除標記操作和清除。

none

不要緩衝任何操作。

inserts

緩衝區插入操作。

deletes

緩衝區刪除標記操作。

changes

緩衝插入和刪除標記操作。

purges

緩衝在後臺發生的物理刪除操作。

您可以innodb_change_buffering在MySQL選項文件(my.cnf或 my.ini)中設置 參數,或使用SET GLOBAL 語句動態更改參數,該 語句需要足夠的權限來設置全局系統變量。請參見 第5.1.8.1節“系統變量特權”。更改設置會影響新操作的緩衝。現有緩衝條目的合併不受影響。

配置更改緩衝區最大大小
該innodb_change_buffer_max_size 變量允許將更改緩衝區的最大大小配置爲緩衝池總大小的百分比。默認情況下, innodb_change_buffer_max_size設置爲25。最大設置爲50。

考慮innodb_change_buffer_max_size在具有大量插入,更新和刪除活動的MySQL服務器上進行增加 ,其中更改緩衝區合併不能跟上新的更改緩衝區條目,從而導致更改緩衝區達到其最大大小限制。

考慮innodb_change_buffer_max_size在使用靜態數據進行報告的MySQL服務器上減少 ,或者如果更改緩衝區消耗了與緩衝池共享的太多內存空間,從而導致頁面比期望的更快地從緩衝池中老化。

使用代表性的工作負載測試不同的設置,以確定最佳配置。該 innodb_change_buffer_max_size 設置是動態的,允許在不重新啓動服務器的情況下修改設置。

Adaptive Hash Index

自適應哈希索引功能可以InnoDB 在不犧牲事務功能或可靠性的情況下,在工作負載和緩衝池有足夠內存的適當組合的系統上,更像是內存數據庫。自適應哈希索引功能由innodb_adaptive_hash_index 變量啓用 ,或在服務器啓動時由禁用 --skip-innodb-adaptive-hash-index。

根據觀察到的搜索模式,使用索引關鍵字的前綴構建哈希索引。該前綴可以是任何長度,並且可能是哈希樹索引中僅B樹中的某些值出現。哈希索引是根據對經常訪問的索引頁面的需求而建立的。

如果表幾乎完全適合主內存,則散列索引可以通過啓用直接查找任何元素的方式來加速查詢,從而將索引值轉換爲某種指針。InnoDB 具有監視索引搜索的機制。如果 InnoDB發現查詢可以從構建哈希索引中受益,它會自動這樣做。

在某些工作負載下,哈希索引查找的速度大大超過了監視索引查找和維護哈希索引結構的額外工作。在繁重的工作負載(例如多個併發連接)下,訪問自適應哈希索引有時可能會成爲爭用的源。與 LIKE運算符和% 通配符也往往不會受益。對於無法從自適應哈希索引功能中受益的工作負載,將其關閉可減少不必要的性能開銷。由於很難預先預測自適應哈希索引功能是否適合特定的系統和工作負載,因此請考慮啓用和禁用該功能的基準測試。與早期版本相比,MySQL 5.6中的體系結構更改使其更適合禁用自適應哈希索引功能。

在MySQL 5.7中,自適應哈希索引功能已分區。每個索引都綁定到一個特定的分區,並且每個分區都受到單獨的鎖存器的保護。分區由innodb_adaptive_hash_index_parts 變量控制 。在較早的版本中,自適應哈希索引功能受單個閂鎖的保護,在繁重的工作負載下,它可能成爲爭用點。該 innodb_adaptive_hash_index_parts 變量默認設置爲8。最大設置爲512。

您可以在輸出SEMAPHORES部分中 監視自適應哈希索引的使用和爭用 SHOW ENGINE INNODB STATUS。如果在中創建的RW鎖上有許多線程在等待btr0sea.c,請考慮增加自適應哈希索引分區的數量或禁用自適應哈希索引功能。

有關哈希索引的性能特徵的信息,請參見第8.3.8節“ B樹和哈希索引的比較”。

Log Buffer

日誌緩衝區是存儲區域,用於保存要寫入磁盤上的日誌文件的數據。日誌緩衝區大小由innodb_log_buffer_size變量定義 。默認大小爲16MB。日誌緩衝區的內容會定期刷新到磁盤。較大的日誌緩衝區使大型事務可以運行,而無需在事務提交之前將重做日誌數據寫入磁盤。因此,如果您有更新,插入或刪除許多行的事務,則增加日誌緩衝區的大小可以節省磁盤I / O。

該 innodb_flush_log_at_trx_commit 變量控制如何將日誌緩衝區的內容寫入並刷新到磁盤。該 innodb_flush_log_at_timeout 變量控制日誌刷新頻率。

有關相關信息,請參見“ 內存配置 ”和 第8.5.4節“優化InnoDB重做日誌”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章