日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一、前言

下面讓我們就一起看下,當你執行CURD時,InnoDB的Buffer Pool中都發生了什么!以及Buffer Pool的優化!

二、介紹

你知道的,MySQL對數據的增刪改查都是內存中完成的,這塊內存就是Buffer Pool。

你可以像下面這樣查看下你的MySQL的Buffer的Buffer Pool的默認大小
 

 

上圖中的0.125單位為GB,轉換成MB就是 1024* 1/8 = 128MB

 

 

總結來說,就是MySQL啟動后就會為我們初始化好這塊Buffer Pool。如下圖:

 


 

你可以看著上圖,然后讀下面這段話:

 

 

MySQL以數據頁為單位,從磁盤中讀取數據。數據頁被讀取到內存中,所謂的內存其實就是Buffer Pool。

 

 

Buffer Pool中維護的數據結構是緩存頁,而且每個緩存頁都有它對應的描述信息。

 

 

由于MySQL剛啟動,還沒有從磁盤中讀取任何數據頁到內存(Buffer Pool)中,那此時Buffer Pool中所有的緩存頁其實都是空的。

 

 

除了緩存頁之外,你還能看到Buffer Pool中存在三個雙向鏈表。分別是FreeList、LRUList以及FlushList。這三個雙向鏈表中維護著緩存頁的描述信息。

 

 

二、好,假設你讀取出來了1個數據頁

 

 

當你通過select讀取出一個數據頁之后,是需要將這個數據頁加載進Buffer Pool中的緩存頁中的。

 

 

那問題來了,MySQL怎么知道該將你讀取出來的數據頁存放在哪個緩存頁中呢?相信你看了上圖應該也能想到答案了。FreeList這個雙向鏈表不是存放了空閑的緩存頁的描述信息嗎?那從FreeList中取出一個空間緩存頁的描述信息不就好了?于是得到了下面這張圖:

 


 

啰唆一點:對這張圖稍微做一下解讀:

 

 

InnoDB會將你讀取出來的數據頁加載進Buffer Pool中的緩存頁中,然后緩存頁的描述信息也會被維護進LRU鏈表中。鏈表做了冷熱數據分離優化,5/8的區域是熱數據區域,3/8的區域算是冷數據區域。(本質上它們都是雙向鏈表),而你新讀取的數據頁會被放在冷數據區的靠前的位置上。

 

 

如果你將該數據頁讀取出來加載進緩存頁中后,間隔沒到1s,就使用該緩存頁。那么InnoDB是不會將這個描述信息移動到5/8的熱數據區域的。

 

 

但是當超過1s后,你又去讀這個數據頁。那這個數據頁的描述信息就會被放到熱數據區域。如下圖:

 


 

三、假設你一次性讀取出來了好多數據頁

 

 

白日夢在第 6 篇文章中跟大家分享過,MySQL是存在預讀機制的,感興趣可關注公眾號閱讀。

 

 

假設觸發了MySQL的預讀機制。一次性從磁盤中讀取來N多個緩存頁。會得到下面這張圖:

 


 

因為發生了預讀,所以你的一次磁盤IO讀出了大量的數據頁,但是這些數據頁中很可能是有一些是你根本不需要的,僅僅是預讀把它們級聯查出來了。這時按老規矩,從FreeList中找到空閑的緩存頁信息,然后將其從FreeList中移除。根據找到的空閑緩存頁的描述信息,將從磁盤中讀取出來的數據頁加載進去。相應的該緩存頁的描述信息也會被維護進LRU鏈表的冷數據區域。

 

 

這時你就會發現這種冷熱數據分離的機制多么妙!即使發生了預讀又怎么樣?根本沒有機會將熱數據區的描述信息1擠下去。當內存不夠用了需要將部分緩存頁刷新到磁盤中時,那就從冷數據區域開始刷新好了,反正他們本來就不經常被使用。

 

 

同樣的,當你超過1s后又訪問了冷數據區的緩存頁,比如訪問了緩存頁66和數據頁67,該緩存頁對應的描述信息是會被提升到熱數據區,于是有了下面這張圖:

 


 

那,如果你訪問上圖中的數據頁67,它會移動到描述信息66所在節點的前面去嗎?

 

 

其實MySQL的LRU鏈表做了優化,數據67是不會往前跑的。

 

 

四、假設你修改了某數據頁

 

 

假設你執行了update xxx set xxx where id in (xxx,xxx,xxx,xxx);

 

 

而符合條件的數據行恰巧就在描述信息1、描述信息66、描述信息67所指向的緩存頁中,那BufferPool中會發生什么呢?

 

 

如下圖:

 


 

你會看到,被你修改了的緩存頁的描述信息,被添加到了FlushList這個雙向鏈表中。

 

 

想必看到這里你已經知道了,原來FlushList中的節點存放就是被修改了臟數據頁的描述信息塊。

 

 

隨著MySQL被使用的時間越來越長,BufferPool的大小就越來越小。等它不夠用的時候,就會將部分LRU中的數據頁描述信息移除出去,這時如果發現被移除出來的數據頁在FLushList中,就會觸發fsync的操作,觸發隨機寫磁盤。如果該數據頁是干凈的,那移除出去就好了。其他也不用干啥。

 

 

舉個例子:假設需要將描述信息66、描述信息67指向的緩存頁落盤。會得到下面這張腦圖:

 

 

描述信息66、67指向的緩存頁被刷新進磁盤。 同時從FlushList中將其移除,然后存入FreeList中。完成一個循環

 


 

當然,將臟數據頁刷新進磁盤的時機除了上圖中說的還有好多種情況。

 

 

下面再看一下關于Buffer Pool的設置和相關的優化。

 

 

五、配置Buffer Pool的大小

 

 

buffer pool越大,MySQL的性能就越強悍。你可以像下面這樣配置Buffer Pool的大小。

 

 

Copymysql> SET GLOBAL innodb_buffer_pool_size=402653184;

 

 

六、配置多個Buffer Pool的實例

 

 

你可以為MySQL實例配置多個Buffer Pool,每個Buffer Pool各自負責管理一部分緩存頁,并且有自己獨立的LRU、Free、Flush鏈表。

 

 

當有多線程并發請求過來時,線程可以在不同的Buffer Pool中執行自己的操作,MySQL性能就會得到很大的提升

 

 

在my.d中進行配置

 

 

Copy[server]
innodb_buffer_pool_size = xxx
innodb_buffer_pool_instances = 4

 

 

意思是將總容量為xxx的buffer pool劃分成4個實例。每個實例都有 xxx/4 的容量。

 

 

參數innodb_buffer_pool_instances的最大值為64,并且想讓該參數生效,innodb_buffer_pool_size容量至少是1G。

 

 

可以像下面這樣查看你的MySQL的Buffer Pool實例狀態。

 


 

七、揭秘BufferPool的真實結構

 

 

現實中Buffer Pool動輒就占用好幾G的內存,相對于直接申請幾G的內存完成擴容,MySQL有更優雅的實現方式。

 

 

為了實現動態調整Buffer Pool的大小。MySQL設計了chunk 機制。

 


 

可以看上圖腦補一下Buffer Pool 以及 Chunk長什么樣。

 

 

總的來說:就是將每一個 Buffer Pool Instance 更加細力度化。將Buffer Pool拆分成更小的獨立單元。

 

 

每個Buffer Pool劃分成多個chunnk,每個chunk中維護一部分緩存頁、緩存頁的描述信息。同屬于一個Buffer Pool的chunk共享該Buffer Pool的lru、free、flush鏈表。

 

 

塊大小由參數innodb_buffer_pool_chunk_size控制,默認值為 128M

 

 

該參數可以像下面這樣修改:

 

 

Copyshell> mysqld --innodb-buffer-pool-chunk-size=134217728

 

 

或者通過配置文件自定義

 

 

Copy[mysqld]
innodb_buffer_pool_chunk_size=13421772

 

 

八、看一看Buffer Pool相關的參數#

 

 

執行命令

 

 

Copy> mysql show engine innodb status

 


 

九、如何規劃你的Buffer Pool大小

 

 

推薦將Buffer Pool的總大小設置為服務器內存的 50%~60%左右

 

 

BufferPool總大小 = (chunkSize * bufferPoolInstanceNum)*2

 

 

十、Buffer Pool的預熱機制

 

 

這種機制實際上是想讓重啟后的MySQL快速適應大規模的流量請求。

 

 

InnoDB 在服務器關閉時為每個緩沖池保存一部分最近高頻使用的頁面,并在服務器啟動時恢復這些頁面。保存多大比例的緩存頁由參數innodb_buffer_pool_dump_pct控制。

 

 

在啟動時還原緩沖池,實際上會縮短預熱的時間。

 

 

你可以通過下面的方式配置該參數

 

 

Copy# 通過命令
SET GLOBAL innodb_buffer_pool_dump_pct=40;

# 通過文件
[mysqld]
=40

 

 

參數innodb_buffer_pool_dump_at_shutdown控制 MySQL關閉時保存緩沖池的狀態,默認為on的狀態。

 

 

啟動參數--innodb-buffer-pool-load-at-startup 表示啟動MySQL的時候恢復緩沖池中的狀態,默認也是開啟的。

 

分享到:
標簽:MySQL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定