日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

分页缓冲池占用很高怎么解决_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理...

發(fā)布時(shí)間:2025/3/20 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分页缓冲池占用很高怎么解决_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

緩沖池的用處

對于使用 InnoDB 作為存儲引擎的表來說,不管是用于存儲用戶數(shù)據(jù)的索引,還是各種系統(tǒng)數(shù)據(jù),都是以頁的形式存放在表空間中的,而所謂的表空間只是 InnoDB 對文件系統(tǒng)上一個(gè)或幾個(gè)實(shí)際文件的抽象,也就實(shí)際數(shù)據(jù)說到底還是存儲在磁盤上的。

磁盤的速度很慢,怎么能配得上“快如閃電”的CPU 呢?

InnoDB 存儲引擎在處理客戶端的請求時(shí),當(dāng)需要訪問某個(gè)頁的數(shù)據(jù)時(shí),就會(huì)把完整的頁的數(shù)據(jù)全部加載到內(nèi)存中。

也就是說即使我們只需要訪問一個(gè)頁的一條記錄,那也需要先把整個(gè)頁的數(shù)據(jù)加載到內(nèi)存中。

緩沖池內(nèi)部組成

緩沖池中默認(rèn)的緩存頁大小和在磁盤上默認(rèn)的頁大小是一樣的,一般是16KB。

為了更好的管理這些在緩沖池中的緩存頁,InnoDB為每一個(gè)緩存頁都創(chuàng)建了一些所謂的控制信息。

這些控制信息包括該頁所屬的表空間編號、頁號、緩存頁在緩沖池中的地址、鏈表節(jié)點(diǎn)信息、一些鎖信息。

緩沖池的一些參數(shù): SHOW VARIABLES LIKE 'innodb_buffer_pool%'; free 鏈表 當(dāng)最初啟動(dòng)MySQL服務(wù)器的時(shí)候,此時(shí)并沒有真實(shí)的磁盤頁被緩存到緩沖池中,之后隨著程序的運(yùn)行,會(huì)不斷的有磁盤上的頁被緩存到緩沖池中。

從磁盤上讀取一個(gè)頁到緩沖池中的時(shí)候該放到哪個(gè)緩存頁的位置呢?

思路:區(qū)分緩沖池中哪些緩存頁是空閑的,哪些已經(jīng)被使用了。

把所有空閑的緩存頁對應(yīng)的控制塊作為節(jié)點(diǎn)放到一個(gè)鏈表中,這個(gè)鏈表叫作 free 鏈表。

flush 鏈表

如果我們修改了緩沖池中某個(gè)緩存頁的數(shù)據(jù),那它就和磁盤上的頁不一致了,這樣的緩存頁也被稱為臟頁(dirty page)。

最簡單的做法就是每發(fā)生一次修改就立即同步到磁盤上對應(yīng)的頁上,但是頻繁的往磁盤中寫數(shù)據(jù)會(huì)嚴(yán)重的影響程序的性能。

所以,Innodb 創(chuàng)建了一個(gè)存儲臟頁的鏈表,凡是修改過的緩存頁對應(yīng)的控制塊都會(huì)作為一個(gè)節(jié)點(diǎn)加入到一個(gè)鏈表中,在未來的某個(gè)時(shí)間點(diǎn)進(jìn)行同步。這個(gè)鏈表叫做 flush 鏈表。

緩存不夠的窘境

緩沖池對應(yīng)的內(nèi)存大小畢竟是有限的,如果需要緩存的頁占用的內(nèi)存大小超過了緩沖池大小,也就是已經(jīng)沒有多余的空閑緩存頁的時(shí)候怎么辦?

把某些舊的緩存頁從緩沖池中移除,然后再把新的頁放進(jìn)來。

移除哪些緩存頁?這就需要引入緩存淘汰機(jī)制了。

緩存淘汰機(jī)制

緩存淘汰有以下兩個(gè)目的:

  • 實(shí)現(xiàn)淘汰
  • 使緩存命中率高

緩存淘汰機(jī)制比較常用的是用 LRU (Least recently used)算法。

傳統(tǒng)LRU

LRU 的兩種情況:

(1)頁已經(jīng)在緩沖池里,那就只做“移至”LRU頭部的動(dòng)作,而沒有頁被淘汰;

(2)頁不在緩沖池里,除了做“放入”LRU頭部的動(dòng)作,還要做“淘汰”LRU尾部頁的動(dòng)作;

在 InnoDB 中,傳統(tǒng)的 LRU 會(huì)遇到兩個(gè)問題:

(1)預(yù)讀失效;

(2)緩沖池污染;

什么是預(yù)讀失效?

由于預(yù)讀 (Read-Ahead),提前把頁放入了緩沖池,但最終 MySQL 并沒有從頁中讀取數(shù)據(jù),稱為預(yù)讀失效。

如何對預(yù)讀失效進(jìn)行優(yōu)化?

要優(yōu)化預(yù)讀失效,思路是:

(1)讓預(yù)讀失敗的頁,停留在緩沖池 LRU 里的時(shí)間盡可能短;

(2)讓真正被讀取的頁,才挪到緩沖池 LRU 的頭部;以保證,真正被讀取的熱數(shù)據(jù)留在緩沖池里的時(shí)間盡可能長。

具體方法是:

(1)將LRU分為兩個(gè)部分:

  • new 區(qū)(new sublist)
  • old 區(qū)(old sublist)

(2)兩個(gè)區(qū)首尾相連,即:new 區(qū)的尾(tail)連接著 old 區(qū)的頭(head);

(3)新頁(例如被預(yù)讀的頁)加入緩沖池時(shí),只加入到 old 區(qū)頭部: 如果數(shù)據(jù)真正被讀取(預(yù)讀成功),才會(huì)加入到 new 區(qū)的頭部 如果數(shù)據(jù)沒有被讀取,則會(huì)比 new 區(qū)里的“熱數(shù)據(jù)頁”更早被淘汰出緩沖池

改進(jìn)版緩沖池LRU能夠很好的解決“預(yù)讀失敗”的問題。

查看系統(tǒng)變量 innodb_old_blocks_pct 的值來確定old區(qū)域在LRU鏈表中所占的比例 SHOW VARIABLES LIKE 'innodb_old_blocks_pct';

什么是 MySQL 緩沖池污染? 當(dāng)某一個(gè)SQL語句,要批量掃描大量數(shù)據(jù)時(shí),可能導(dǎo)致把緩沖池的所有頁都替換出去,導(dǎo)致大量熱數(shù)據(jù)被換出,MySQL性能急劇下降,這種情況叫緩沖池污染。

例如,有一個(gè)數(shù)據(jù)量較大的用戶表,當(dāng)執(zhí)行 select * from user where name like "%test%";

要優(yōu)化緩沖池污染,思路是:

(1)不讓批量掃描的大量數(shù)據(jù)進(jìn)入到 new 區(qū);

(2)讓真正被讀取的頁,才挪到緩沖池 LRU 的頭部;

具體實(shí)現(xiàn): 加入了一個(gè)“old 區(qū)停留時(shí)間”的機(jī)制: 在 old 區(qū)域的緩存頁進(jìn)行第一次訪問時(shí)就在它對應(yīng)的控制塊中記錄下來這個(gè)訪問時(shí)間,如果后續(xù)再次訪問的時(shí)間與第一次訪問的時(shí)間在某個(gè)時(shí)間間隔內(nèi)(即該緩存頁在 old 區(qū)的存在時(shí)間在某個(gè)時(shí)間間隔內(nèi)),那么該頁面就不會(huì)被從old 區(qū)移動(dòng)到 new 區(qū)的頭部。

上述的全表掃描執(zhí)行:

(1)掃描過程中,需要新插入的數(shù)據(jù)頁,都被放到old區(qū)

(2)一個(gè)數(shù)據(jù)頁會(huì)有多條記錄,因此一個(gè)數(shù)據(jù)頁會(huì)被訪問多次

(3)由于是順序掃描,數(shù)據(jù)頁的第一次被訪問和最后一次被訪問的時(shí)間間隔不會(huì)超過1S,因此還是會(huì)留在old區(qū)

(4) 繼續(xù)掃描,之前的數(shù)據(jù)頁再也不會(huì)被訪問到,因此也不會(huì)被移到 new 區(qū),最終很快被淘汰這個(gè)間隔時(shí)間是由系統(tǒng)變量 innodb_old_blocks_time 控制的。SHOW VARIABLES LIKE 'innodb_old_blocks_time';配置緩沖池時(shí)的注意事項(xiàng) innodb_buffer_pool_size
innodb_buffer_pool_chunk_size ×
innodb_buffer_pool_instances 的倍數(shù)(這主要是想保證每一個(gè) 緩沖池 實(shí)例中包含的 chunk 數(shù)量相同)。

查看Buffer Pool的狀態(tài)信息

SHOW ENGINE INNODB STATUSG

一些參數(shù)如下:

  • Total memory allocated :代表 Buffer Pool 向操作系統(tǒng)申請的連續(xù)內(nèi)存空間大小,包括全部控制塊、緩存頁、以及碎片的大小。
  • Buffer pool size:代表該 Buffer Pool 可以容納多少緩存頁,單位是頁
  • Free buffers:代表當(dāng)前 Buffer Pool 還有多少空閑緩存頁,也就是 free 鏈表中還有多少個(gè)節(jié)點(diǎn)。
  • Database pages:代表 LRU 鏈表中的頁的數(shù)量,包含 new 和 old 兩個(gè)區(qū)域的節(jié)點(diǎn)數(shù)量。
  • Old database pages:代表 LRU 鏈表 old 區(qū)域的節(jié)點(diǎn)數(shù)量。
  • Modified db pages:代表臟頁數(shù)量,也就是 flush 鏈表中節(jié)點(diǎn)的數(shù)量。

總結(jié)

1、磁盤太慢,用內(nèi)存作為緩存很有必要。
2、緩沖池本質(zhì)上是InnoDB向操作系統(tǒng)申請的一段連續(xù)的內(nèi)存空間,可以通過innodb_buffer_pool_size 來調(diào)整它的大小。
3、InnoDB 使用了許多鏈表來管理緩沖池。
4、緩沖池的常見管理算法是 LRU
5、InnoDB 對普通 LRU 進(jìn)行了優(yōu)化:分為 new 區(qū)和 old 區(qū),加入“停留時(shí)間”機(jī)制。

作者:JeffreyC鏈接:https://juejin.im/post/5eccf7c3f265da76f525d333

總結(jié)

以上是生活随笔為你收集整理的分页缓冲池占用很高怎么解决_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。