欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL中讀頁緩沖區(qū)buffer?pool詳解

 更新時間:2022年05月28日 15:11:47   作者:大隊長11  
這篇文章主要介紹了MySQL中讀頁緩沖區(qū)buffer?pool?,從磁盤中讀取數(shù)據(jù)到內(nèi)存的過程是十分慢的,所以我們讀取的頁面需要將其緩存起來,所以MySQL有這個buffer pool對頁面進(jìn)行緩存,需要的朋友可以參考下

Buffer pool

我們都知道我們讀取頁面是需要將其從磁盤中讀到內(nèi)存中,然后等待CPU對數(shù)據(jù)進(jìn)行處理。我們直到從磁盤中讀取數(shù)據(jù)到內(nèi)存的過程是十分慢的,所以我們讀取的頁面需要將其緩存起來,所以MySQL有這個buffer pool對頁面進(jìn)行緩存。

首先MySQL在啟動時會向操作系統(tǒng)申請一段連續(xù)的內(nèi)存空間,這一段空間就是作為buffer pool所用。將緩存的頁放入buffer pool中管理起來。

mysql> show variables like 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
1 row in set, 1 warning (0.00 sec)

我們可以看到默認(rèn)是134217728字節(jié),即128MB。一個頁面是16KB,我們申請16KB倍數(shù)的緩存區(qū)大小就不會產(chǎn)生碎片。

buffer pool組成

同時呢,在buffer pool中還有包含每個頁面的控制信息,即控制塊。每個控制塊對應(yīng)管理每一個頁面 (我們使用地址引用每一個頁面) ,控制塊用來存儲頁面的一些信息,控制塊的占用大小不包括在innodb_buffer_pool_size中。由MySQL在啟動時自己額外申請空間。

在控制塊和緩存頁中間會有部分碎片,就是空間無法全部利用的產(chǎn)生的碎片。因為MySQL向操作系統(tǒng)申請的內(nèi)存空間需要申請一定大小的控制塊空間,不能確定具體的大小,難免回有無法利用的空間。

free鏈表

free鏈表顧名思義,就是管理空閑的緩存頁的鏈表,如果緩存頁沒有被使用,其控制塊就會連接到free鏈表上。

通過一個基節(jié)點(diǎn)連接控制塊形成一個free鏈表,并存儲空閑頁的數(shù)量等基本信息。

當(dāng)我們從磁盤讀取一個頁到buffer pool中,就會取一個空閑的控制塊填上對應(yīng)緩存頁的基本信息。

緩存頁的哈希處理

MySQL在buffer pool中怎么快速存取一個頁,以及查看對應(yīng)頁有沒有被緩存到buffer pool中呢?

這就是用到哈希表,在Java中就是hashmap,通過表空間+頁號做處理形成一個hash的key值,然后value值就是緩存頁在buffer pool中的地址。

flush鏈表的管理

學(xué)習(xí)到這一章節(jié)的時候我震驚了,首先確實和我的理解是不一樣的,以及到后面的MVCC確實讓我大開眼界,這是我學(xué)習(xí)一遍后回頭做的總結(jié),所以比較言簡意賅哈。

我們使用SQL語句對某條記錄進(jìn)行修改的時候,就會修改某個頁面或者多個頁面,我們對于頁面的修改呢,并不會直接對磁盤進(jìn)行對應(yīng)的修改,因為對于磁盤IO實在是太慢了,我們首先會將修改的頁面(簡稱臟頁)鏈起來,就和free鏈表差不多,就是一個基節(jié)點(diǎn)將對應(yīng)臟頁的控制塊連接在一起。

這個flush鏈表就代表我們即將還沒有將頁面更新到磁盤的鏈表。

LRU鏈表

因為buffer pool的大小是有限的,所以我們對于緩存頁的大小是有限的,所以我們需要將不用的頁面進(jìn)行一個淘汰。MySQL采用的就是LRU的方式進(jìn)行淘汰。

LRU就是最久未使用淘汰的策略,我們使用一個鏈表將緩存頁面鏈起來,最近訪問的出現(xiàn)在最前面,最久未訪問的在鏈表末尾,當(dāng)LRU滿了新頁面都進(jìn)來機(jī)會淘汰鏈表尾部頁面。

我們直接使用LRU,當(dāng)MySQL進(jìn)行預(yù)讀或者全表掃描出現(xiàn)大量低頻頁面被讀進(jìn)LRU鏈表,會導(dǎo)致高頻的頁面直接被淘汰掉了,取而代之的是一些不經(jīng)常用的頁面。

預(yù)讀就是MySQL優(yōu)化器認(rèn)為當(dāng)前請求可能會讀取的頁面,預(yù)先將其加載到內(nèi)存的buffer pool中。可以分為兩種:

  • 線性預(yù)讀

當(dāng)讀取一個區(qū)的頁面超過系統(tǒng)變量innodb_read_ahead_threshold的值默認(rèn)為56,也就是說當(dāng)我們讀取一個區(qū)的頁面超過56頁,MySQL就會異步的讀取下一個區(qū)的所有頁面到內(nèi)存中。

  • 隨機(jī)預(yù)讀

如果buffer pool已經(jīng)緩存了某個區(qū)的13個頁面,不管是不是順序的,只要有13頁緩存了,就會觸發(fā)MySQL異步讀取本區(qū)的所有頁面到MySQL中。我們可以控制關(guān)閉隨機(jī)預(yù)讀,也就是系統(tǒng)變量innodb_random_read_ahead。默認(rèn)是OFF。

所以出現(xiàn)了改進(jìn)基于分區(qū)的LRU鏈表,將鏈表分為兩份。

一個是使用頻率非常高的young區(qū)域,一個是使用頻率不是很高的old區(qū)。

正常來說old區(qū)占比是37%,所以young區(qū)就占63%,我們可以通過innodb_old_blocks_pct來修改,默認(rèn)就是37。

我們來講講這個基于分區(qū)的LRU鏈表。

  1. 首先buffer pool初始化,會將讀取的頁面直接放進(jìn)old區(qū)。
  • 但是如果我們對于同一個頁面的多條記錄進(jìn)行訪問的話,我們就會多次訪問同一頁多次。但是如果我們是全表掃描的話,是可能會將所有頁面緩存進(jìn)緩存池中的,所以MySQL對于其進(jìn)行優(yōu)化。
  • 所以MySQL對于當(dāng)頁面第一次讀入old區(qū)并在一定時間間隔(innodb_old_blocks_pct)內(nèi)的多次訪問來說是不會將其放入young區(qū)進(jìn)行緩存的。innodb_old_blocks_pct的值默認(rèn)為1000,就是剛來的來一秒內(nèi)的多次訪問是不會將其轉(zhuǎn)移到y(tǒng)oung區(qū)的。
  1. 如果多次訪問就會將old區(qū)的頁升級到y(tǒng)oung區(qū)。當(dāng)young區(qū)的頁面被訪問,只有young鏈表后1/4的頁面被訪問時才會將其轉(zhuǎn)置到y(tǒng)oung區(qū)鏈表頭,不然就不會改動,減少一些調(diào)整鏈表的性能損失。

刷新臟頁

MySQL會啟動后臺線程進(jìn)行臟頁,也就是修改的頁面進(jìn)行刷新到磁盤。

以下有兩種方式刷新臟頁:

  • 從LRU的尾部掃描一些頁面,刷新其中的臟頁到磁盤中。
    • 后臺線程會從LRU鏈表中old區(qū)域尾部,即不經(jīng)常使用的頁面中查找有沒有臟頁,有就更新到磁盤。可以更改系統(tǒng)變量innodb_lru_scan_depth來控制掃描區(qū)域尾部的數(shù)量。
  • 從flush鏈表中更新到磁盤。
    • 我們上面說了flush連接這臟頁的控制塊,我們就可以將連接這flush鏈表的臟頁進(jìn)行更新。

疑問:為什么要兩種方式更新呢?我剛開始不懂這是我回過頭來看的時候就懂了

首先我們臟頁是緩存在buffer pool中的,但是我們buffer pool空間是有限的,又因為我們使用的是LRU的方式,又因為從flush鏈表將臟頁同步到磁盤效率實在不高,所以不會很經(jīng)常去更新臟頁。如果我們不更新直接將其從LRU的鏈表拋棄也就是從緩存池中直接扔了,但是它是臟頁就無法同步到磁盤了,同時flush鏈表鏈接的也會出現(xiàn)問題。

所以在LRU淘汰很久未使用的頁有個前提就是它不是一個臟頁。所以我們會去檢測LRU鏈表尾部有沒有臟頁,然后更新它,我們才能去淘汰掉這些頁。

flush鏈表更新那就是它的本職工作了,它存這個也是干這個的,應(yīng)該沒有什么問題。

當(dāng)系統(tǒng)十分繁忙,buffer pool使用量不足的時候,因為磁盤IO太慢了,所以會出現(xiàn)一種情況,就是大量的用戶線程也在進(jìn)行這個同步臟頁的活。不同步臟頁然后淘汰buffer pool的頁面,沒法讀取頁面啊。

多個buffer pool實例

我們可以設(shè)置多個buffer pool來實現(xiàn)多實例提高性能。

mysql> show variables like 'innodb_buffer_pool_instances';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| innodb_buffer_pool_instances | 1     |
+------------------------------+-------+
1 row in set, 1 warning (0.00 sec)

我們可以設(shè)置innodb_buffer_pool_instances系統(tǒng)變量來控制實例變量。

但是當(dāng)buffer pool的大小小于1G的時候,設(shè)置2個實例也是沒有用的(會被恢復(fù)成1個),多實例的情況是建立在大內(nèi)存的情況下的。

動態(tài)調(diào)整buffer pool大小

在MySQL5.7.5后,MySQL中的buffer pool的大小是以chunk來分配了,如下圖。

一個buffer pool是由多個chunk組成的,所以MySQL向操作系統(tǒng)申請連續(xù)的內(nèi)存空間,就是以chunk的方式來申請的,這樣我們可以在MySQL運(yùn)行時調(diào)整buffer pool的大小。但是chunk的大小是不能在運(yùn)行時更改的,這樣是很耗費(fèi)性能的。?

innodb_buffer_pool_size / innodb_buffer_pool_instances = 每個實例buffer pool的大小。

每個實例的大小 / innodb_buffer_pool_chunk_size = 每個實例由多少個chunk構(gòu)成。

不是弄很明白,怎么動態(tài)調(diào)整大小,我調(diào)整了但是mysqld占用內(nèi)存大小還是只能重啟才能生效,我不會。

查看buffer pool具體的信息

show engine innodb status;

到此這篇關(guān)于MySQL中讀頁緩沖區(qū)buffer pool的文章就介紹到這了,更多相關(guān)MySQL buffer pool內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mysql存儲過程之錯誤處理實例詳解

    mysql存儲過程之錯誤處理實例詳解

    這篇文章主要介紹了mysql存儲過程之錯誤處理,結(jié)合實例形式詳細(xì)分析了mysql存儲過程錯誤處理相關(guān)原理、操作技巧與注意事項,需要的朋友可以參考下
    2019-12-12
  • 一文掌握MySQL表的創(chuàng)建和約束

    一文掌握MySQL表的創(chuàng)建和約束

    這篇文章主要和大家分享一下數(shù)據(jù)庫的創(chuàng)建和銷毀語法以及詳細(xì)講解MySQL表的創(chuàng)建代碼和約束的使用,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-07-07
  • mysql 5.7.24 安裝配置方法圖文教程

    mysql 5.7.24 安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7.24 安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • mysql innodb的監(jiān)控(系統(tǒng)層,數(shù)據(jù)庫層)

    mysql innodb的監(jiān)控(系統(tǒng)層,數(shù)據(jù)庫層)

    這篇文章主要介紹了mysql innodb的監(jiān)控(系統(tǒng)層,數(shù)據(jù)庫層)的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 一文帶你理解MySql中explain結(jié)果filtered

    一文帶你理解MySql中explain結(jié)果filtered

    使用EXPLAIN關(guān)鍵字可以模擬優(yōu)化器執(zhí)行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的,下面這篇文章主要給大家介紹了關(guān)于MySql中explain結(jié)果filtered的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • 刪除MySQL表中重復(fù)數(shù)據(jù)詳解

    刪除MySQL表中重復(fù)數(shù)據(jù)詳解

    這篇文章主要為大家介紹了刪除MySQL表中重復(fù)數(shù)據(jù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • mysql日期處理函數(shù)實例解析

    mysql日期處理函數(shù)實例解析

    這篇文章主要介紹了mysql日期處理函數(shù)實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • mysql忘記密碼重置的方法實現(xiàn)

    mysql忘記密碼重置的方法實現(xiàn)

    本文主要介紹了mysql忘記密碼重置的方法實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • mysql基礎(chǔ)架構(gòu)教程之查詢語句執(zhí)行的流程詳解

    mysql基礎(chǔ)架構(gòu)教程之查詢語句執(zhí)行的流程詳解

    這篇文章主要給大家介紹了關(guān)于mysql基礎(chǔ)架構(gòu)教程之查詢語句執(zhí)行流程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2018-11-11
  • 如何解決docker無法啟動的問題

    如何解決docker無法啟動的問題

    這篇文章主要介紹了如何解決docker無法啟動的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評論