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

MySQL InnoDB中的Buffer Pool用法及說(shuō)明

 更新時(shí)間:2025年06月26日 11:18:30   作者:在成都搬磚的鴨鴨  
這篇文章主要介紹了MySQL InnoDB中的Buffer Pool用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

1、背景

mysql數(shù)據(jù)是存儲(chǔ)在磁盤上的,但是從磁盤上讀取數(shù)據(jù)的速度太慢,所以就需要把數(shù)據(jù)從磁盤讀取在內(nèi)存中,申請(qǐng)的這塊內(nèi)存就叫Buffer Pool,也就是緩存池的意思,接下來(lái)我們就來(lái)講一下Buffer Pool。

2、Buffer Pool

【1】含義

在mysql服務(wù)啟動(dòng)時(shí)會(huì)申請(qǐng)一塊存儲(chǔ)頁(yè)的連續(xù)內(nèi)存,這快內(nèi)存就叫Buffer Pool,Buffer Pool的大小可以通過(guò)配置文件指定,linux上的配置文件為my.cnf,windows上的配置文件為my.ini,windows上的默認(rèn)配置如下,可以根據(jù)內(nèi)存大小進(jìn)行修改,最小值為5M:

cat my.ini | grep 'innodb_buffer_pool_size'
innodb_buffer_pool_size=128M

【2】組成

Buffer Pool是由控制塊和緩存頁(yè)組成,一個(gè)控制塊對(duì)應(yīng)一個(gè)緩存頁(yè),控制塊包含對(duì)應(yīng)緩存頁(yè)的表空間編號(hào)、頁(yè)號(hào)、緩存頁(yè)在Buffer Pool中的地址、鏈表節(jié)點(diǎn)信息、鎖、LSN信息, innodb_buffer_pool_size的大小并不包含控制塊的空間,所以再給Buffer Pool申請(qǐng)一塊連續(xù)的內(nèi)存時(shí)會(huì)額外申請(qǐng)5%的空間用于存儲(chǔ)控制塊,其組成圖如下:

在這里插入圖片描述

如果申請(qǐng)的連續(xù)內(nèi)存剩余空間不足以方法一個(gè)控制塊和對(duì)應(yīng)的緩存頁(yè),這個(gè)剩余的空間就叫碎片,如果剛好能放下控制塊和對(duì)應(yīng)的緩存,碎片就不存在。

【3】free鏈表

從磁盤讀數(shù)據(jù)寫到Buffer Pool中時(shí),需要從Buffer Pool中找到空閑的緩存頁(yè)去寫入,為了方便快速找到哪些緩存頁(yè)是空閑的,就有了free鏈表,也就是所有空閑緩存頁(yè)對(duì)應(yīng)的控制塊組成的鏈表,其組成圖如下:

在這里插入圖片描述

free鏈表由鏈表基節(jié)點(diǎn)和控制塊組成,鏈表基節(jié)點(diǎn)是額外的空間,不屬于Buffer Pool,鏈表基節(jié)點(diǎn)存儲(chǔ)了空閑緩存頁(yè)對(duì)應(yīng)的控制塊的首地址和尾地址,還有空閑緩存頁(yè)的個(gè)數(shù),所有空閑緩存頁(yè)對(duì)應(yīng)的控制塊組成一個(gè)雙向鏈表。

通過(guò)free鏈表就可以很方便從中取出一個(gè)空閑緩存頁(yè),將其對(duì)應(yīng)的控制塊填入對(duì)應(yīng)信息,然后從free鏈表中移除,再寫數(shù)據(jù)到緩存頁(yè)。

【4】哈希查找緩存頁(yè)

查找數(shù)據(jù)時(shí)需要判斷數(shù)據(jù)所在的頁(yè)是否在Buffer Pool上,為了方便查找,將表空間編號(hào)和頁(yè)號(hào)作為key與對(duì)應(yīng)的控制模塊做一個(gè)哈希表,這樣就能很方便判斷緩存頁(yè)是否在Buffer Pool。

【5】flush鏈表

修改了Buffer Pool中緩存頁(yè)的數(shù)據(jù),就需要更新磁盤,每次都更新磁盤就對(duì)性能有損耗,所以可以把要更新緩存頁(yè)收集起來(lái)一次性更新,需要更新的緩存頁(yè)就叫臟頁(yè),所有的臟頁(yè)對(duì)應(yīng)的控制塊可以組成一個(gè)鏈表叫flush鏈表,和free鏈表類似,都是由基節(jié)點(diǎn)和控制塊組成,參考上面的free鏈表圖。

【6】LRU鏈表

當(dāng)free鏈表中找不到空閑緩存頁(yè)時(shí),就需要釋放不經(jīng)常使用的頁(yè),所以可以把使用評(píng)率高的緩存頁(yè)放在前面,頻率低的緩存頁(yè)放在后面組成一個(gè)LRU鏈表,這個(gè)鏈表的插入和更新方式如下:

1、如果訪問的頁(yè)不在Buffer Pool中,就從磁盤加載到Buffer Pool中時(shí),把緩存頁(yè)對(duì)應(yīng)的控制塊放到鏈表的頭部,

2、如果訪問的頁(yè)在Buffer Pool中,就直接把緩存頁(yè)對(duì)應(yīng)的控制塊移動(dòng)鏈表的頭部。

但是有兩種情況,

  • 第一是InnoDB提供了預(yù)讀功能,會(huì)提前讀取認(rèn)為可能會(huì)訪問的頁(yè)到Buffer Pool中,但可能最終都沒被訪問;
  • 另一種情況全表掃描會(huì)把所有頁(yè)都加載到Buffer Pool,但很多頁(yè)后面可能不會(huì)被訪問。

所以為了解決這兩種情況把LRU鏈表分為兩部分:熱數(shù)據(jù)和冷數(shù)據(jù),也可以叫young區(qū)域和old區(qū)域,young區(qū)域存儲(chǔ)使用頻率高的緩存頁(yè),old區(qū)域存儲(chǔ)使用頻率不是很高的緩存頁(yè),如圖:

在這里插入圖片描述

LRU鏈表中的young區(qū)域和old區(qū)域的比例系統(tǒng)變量innodb_old_blocks_pct的值來(lái)確定,innodb_old_blocks_pct值代表old區(qū)域的百分比比例,如下:

mysql> SHOW VARIABLES LIKE 'innodb_old_blocks_pct';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_old_blocks_pct | 37    |
+-----------------------+-------+
1 row in set, 1 warning (0.00 sec)

通過(guò)young區(qū)域和old區(qū)域我們就可以對(duì)預(yù)讀和全表掃描進(jìn)行優(yōu)化,預(yù)讀優(yōu)化如下:

當(dāng)磁盤上的某個(gè)頁(yè)初次加載到Buffer Pool時(shí),就會(huì)放到old區(qū)域的頭部,如果該頁(yè)的訪問頻率低就會(huì)在old后移最終被移除。

全表掃描優(yōu)化如下:

全表掃描一樣也是初次會(huì)將所有頁(yè)放到old區(qū)域的頭部,但是后續(xù)讀取所有記錄代表訪問了頁(yè)多次,就會(huì)將頁(yè)放到y(tǒng)oung區(qū)域,但是全表掃描的數(shù)據(jù)讀取是一次性的,間隔很短,所以需要設(shè)置一個(gè)時(shí)間間隔,此間隔內(nèi)的訪問不會(huì)將頁(yè)移動(dòng)young區(qū)域。

時(shí)間間隔配置為innodb_old_blocks_time,單位為毫秒,配置如下:

mysql> SHOW VARIABLES LIKE 'innodb_old_blocks_time';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_old_blocks_time | 1000  |
+------------------------+-------+
1 row in set, 1 warning (0.00 sec)

【7】刷新臟頁(yè)到磁盤

后臺(tái)會(huì)有專門的線程會(huì)將Buffer Pool上修改過(guò)頁(yè),也就是臟頁(yè)刷新到磁盤,刷新方式有兩種:

第一種是BUF_FLUSH_LRU

就是定時(shí)從LRU鏈表尾部掃描一些頁(yè),發(fā)現(xiàn)臟頁(yè)就更新到磁盤,掃描頁(yè)的數(shù)量可以通過(guò)innodb_lru_scan_depth來(lái)指定。

查看配置如下:

mysql> SHOW VARIABLES LIKE 'innodb_lru_scan_depth';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_lru_scan_depth | 1024  |
+-----------------------+-------+
1 row in set, 1 warning (0.00 sec)

第二種刷新方式叫BUF_FLUSH_LIST

也就是定時(shí)從flush鏈表中刷新一部分頁(yè)到磁盤。

【8】Buffer Pool實(shí)例

可以通過(guò)innodb_buffer_pool_instances配置Buffer Pool的實(shí)例,提高并發(fā)處理速度,配置如下:

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)

每個(gè)Buffer Pool實(shí)例的大小為:

innodb_buffer_pool_size/innodb_buffer_pool_instances。

【9】chunk

一個(gè)Buffer Pool實(shí)例可以由多個(gè)chunk組成,一個(gè)chunk的大小可以如下查看,單位是字節(jié):

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_chunk_size';
+-------------------------------+-----------+
| Variable_name                 | Value     |
+-------------------------------+-----------+
| innodb_buffer_pool_chunk_size | 134217728 |
+-------------------------------+-----------+
1 row in set, 1 warning (0.00 sec)

需要注意的是innodb_buffer_pool_size的大小得是innodb_buffer_pool_instances*innodb_buffer_pool_chunk_size的整數(shù)倍。

【10】Buffer Pool狀態(tài)信息

可以通過(guò)show engine innodb statu語(yǔ)句來(lái)查看InnoDB運(yùn)行過(guò)程中的一些狀態(tài)信息,其中就有Buffer Pool的狀態(tài),如下:

mysql> show engine innodb status;
...
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 1107296256
Dictionary memory allocated 6746952
Buffer pool size   64832
Free buffers       55706
Database pages     9126
Old database pages 3348
Modified db pages  8971
Percent of dirty pages(LRU & free pages): 13.837
Max dirty pages percent: 90.000
Pending reads 0
Pending writes: LRU 0, flush list 0
Pages made young 14, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 165, created 8961, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 9126, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
...

各個(gè)字段含義如下:

Buffer Pool狀態(tài)字段含義
Total memory allocated給Buffer Pool向操作系統(tǒng)申請(qǐng)的連續(xù)內(nèi)存空間大小,由控制塊、碎片、緩存頁(yè)組成
Dictionary memory allocated給數(shù)據(jù)字典信息分配的內(nèi)存空間大小,和Buffer Pool沒什么關(guān)系
Buffer pool sizeBuffer Pool可以存儲(chǔ)緩存頁(yè)的數(shù)量
Free buffers空閑緩存頁(yè)數(shù)量,也就是free鏈表節(jié)點(diǎn)數(shù)量
Database pagesLRU鏈中節(jié)點(diǎn)數(shù)量,包含young區(qū)域和old區(qū)域的節(jié)點(diǎn)
Old database pagesold區(qū)域節(jié)點(diǎn)的數(shù)量
Modified db pages臟頁(yè)數(shù)量,也就是flush鏈表節(jié)點(diǎn)數(shù)量
Pending reads正在等待從磁盤上加載到Buffer Pool中的頁(yè)面數(shù)量
Pending writes: LRU從LRU鏈表刷新到磁盤中的頁(yè)數(shù)
Pending writes: flush list從flush鏈表刷新到磁盤中的頁(yè)數(shù)
Page made youngLRU鏈表中從old區(qū)域移動(dòng)到y(tǒng)oung區(qū)域頭部的節(jié)點(diǎn)數(shù)量
Page made not young訪問old區(qū)域在innodb_old_blocks_time時(shí)間間隔內(nèi)訪問不能移動(dòng)到y(tǒng)oung區(qū)域的數(shù)量
young/s每秒從old區(qū)域移動(dòng)到y(tǒng)oung區(qū)域頭部節(jié)點(diǎn)數(shù)量
non-young/s每秒由于不滿足時(shí)間限制不能從old區(qū)域移動(dòng)到y(tǒng)oung區(qū)域節(jié)點(diǎn)數(shù)量
Page read從磁盤讀取寫的Buffer Pool中的頁(yè)數(shù)
Page createdBuffer Pool中創(chuàng)建的頁(yè)數(shù)
Page written刷新臟頁(yè)到磁盤的頁(yè)數(shù)
reads/s、creates/s、writes/s相關(guān)速度
Buffer pool hit rate某段時(shí)間平均訪問1000次頁(yè)面,有多少次頁(yè)面已經(jīng)被緩存到了Buffer Pool中
young-making rate某段時(shí)間平均訪問1000次頁(yè)面,有多少次訪問使頁(yè)面移動(dòng)到了young區(qū)域,包含old、young區(qū)域移動(dòng)到y(tǒng)oung區(qū)域
not某段時(shí)間平均訪問1000次頁(yè)面,有多少次訪問沒有使頁(yè)面移動(dòng)到了young區(qū)域
LRU sumLRU鏈表中節(jié)點(diǎn)數(shù)量
I/O sum最近50s讀取磁盤頁(yè)的總數(shù)
I/O cur正在讀取的磁盤頁(yè)數(shù)量

3、總結(jié)

Buffer Pool用作緩存,主要用于數(shù)據(jù)寫入、數(shù)據(jù)讀取、數(shù)據(jù)刷新,目的是為了減少磁盤I/O,增加讀寫速率,提高數(shù)據(jù)的訪問速度和系統(tǒng)性能。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Mysql兩表?join?查詢方式

    詳解Mysql兩表?join?查詢方式

    這篇文章主要介紹了Mysql兩表?join?查詢方式,主要包括SQL基本語(yǔ)法格式j(luò)i3種join方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • MySQL用戶和權(quán)限及破解root口令的方法示例

    MySQL用戶和權(quán)限及破解root口令的方法示例

    這篇文章主要介紹了詳解MySQL用戶和權(quán)限及破解root口令,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • Mysql主從GTID與binlog的區(qū)別及說(shuō)明

    Mysql主從GTID與binlog的區(qū)別及說(shuō)明

    MySQL GTID(全局事務(wù)標(biāo)識(shí)符)與binlog(二進(jìn)制日志)是搭建主從復(fù)制的兩種機(jī)制,GTID為每個(gè)事務(wù)分配唯一標(biāo)識(shí),確保復(fù)制無(wú)數(shù)據(jù)沖突或丟失,便于復(fù)制配置和管理;binlog記錄所有數(shù)據(jù)庫(kù)更改,用于數(shù)據(jù)恢復(fù)和復(fù)制,GTID基于事務(wù)標(biāo)識(shí)
    2024-10-10
  • Mysql ERROR 1577錯(cuò)誤解決方法

    Mysql ERROR 1577錯(cuò)誤解決方法

    這篇文章主要介紹了Mysql ERROR 1577錯(cuò)誤解決方法,一般是在升級(jí)mysql后會(huì)發(fā)生這個(gè)錯(cuò)誤,錯(cuò)誤原因是需要升級(jí)MySQL系統(tǒng)表,需要的朋友可以參考下
    2014-08-08
  • MySQL敏感數(shù)據(jù)進(jìn)行加密的幾種方法小結(jié)

    MySQL敏感數(shù)據(jù)進(jìn)行加密的幾種方法小結(jié)

    本文介紹了在MySQL中對(duì)敏感數(shù)據(jù)進(jìn)行加密的幾種方法,每種方法都有其適用場(chǎng)景和特點(diǎn),可以根據(jù)具體需求選擇合適的方法來(lái)保護(hù)數(shù)據(jù)安全,感興趣的可以了解一下
    2024-11-11
  • 詳解MySQL的用戶密碼過(guò)期功能

    詳解MySQL的用戶密碼過(guò)期功能

    這篇文章主要為大家詳細(xì)介紹了MySQL的用戶密碼過(guò)期功能的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • 使用Dify訪問mysql數(shù)據(jù)庫(kù)詳細(xì)代碼示例

    使用Dify訪問mysql數(shù)據(jù)庫(kù)詳細(xì)代碼示例

    這篇文章主要介紹了使用Dify訪問mysql數(shù)據(jù)庫(kù)的相關(guān)資料,并詳細(xì)講解了如何在本地搭建數(shù)據(jù)庫(kù)訪問服務(wù),使用ngrok暴露到公網(wǎng),并創(chuàng)建知識(shí)庫(kù)、數(shù)據(jù)庫(kù)訪問工作流和智能體,需要的朋友可以參考下
    2025-03-03
  • 如何使用MySQL一個(gè)表中的字段更新另一個(gè)表中字段

    如何使用MySQL一個(gè)表中的字段更新另一個(gè)表中字段

    這篇文章主要介紹了如何使用MySQL一個(gè)表中的字段更新另一個(gè)表中字段,需要的朋友可以參考下
    2018-11-11
  • MySQL實(shí)現(xiàn)數(shù)據(jù)更新的示例詳解

    MySQL實(shí)現(xiàn)數(shù)據(jù)更新的示例詳解

    這篇文章主要為大家詳細(xì)介紹了MySQL實(shí)現(xiàn)數(shù)據(jù)更新的相關(guān)資料,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 將舊版MySQL替換為8.0及以上版本保姆級(jí)教學(xué)

    將舊版MySQL替換為8.0及以上版本保姆級(jí)教學(xué)

    在部署項(xiàng)目的時(shí)候MySQL就會(huì)報(bào)錯(cuò),這個(gè)時(shí)候就要換MySQL的版本了,這篇文章主要給大家介紹了關(guān)于將舊版MySQL替換為8.0及以上版本的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05

最新評(píng)論