tft每日頭條

 > 科技

 > 數據庫緩存方案大全

數據庫緩存方案大全

科技 更新时间:2024-11-30 03:27:40
Buffer Pool 概述

Buffer Pool 是什麼?從字面上看是緩存池的意思,沒錯,它其實也就是緩存池的意思。它是 MySQL 當中至關重要的一個組件,可以這麼說,MySQL的所有的增删改的操作都是在 Buffer Pool 中執行的。

但是數據不是在磁盤中的嗎?怎麼會和緩存池又有什麼關系呢?那是因為如果 MySQL的操作都在磁盤中進行,那很顯然效率是很低的,效率為什麼低?因為數據庫要從磁盤中拿數據啊,那肯定就需要IO啊,并且數據庫并不知道它将要查找的數據是磁盤的哪個位置,所以這就需要進行随機IO,那這個性能簡直就别玩了。所以 MySQL對數據的操作都是在内存中進行的,也就是在 Buffer Pool 這個内存組件中。

實際上他就好比是 Redis,因為 Redis 是一個内存是數據庫,他的操作就都是在内存中進行的,并且會有一定的策略将其持久化到磁盤中。那 Buffer Pool 的内存結構具體是什麼樣子的,那麼多的增删改操作難道數據要一直在内存中嗎?既然說類似 redis 緩存,那是不是也像 redis 一樣也有一定的淘汰策略呢?

本篇文章,會詳細的介紹 Buffer Pool 的内存結構,讓大家徹底明白這裡面的每一步執行流程。我們先看一下 MySQL從加載磁盤文件到完成提交一個事務的整個流程。我們先來看一個總體的流程圖,從數據在磁盤中被加載到緩存池中,然後經過一些列的操作最終又被刷入到磁盤的一個過程,都經曆了哪些事情,這個圖不明白沒有關系,因為本文重點是 Buffer Pool 這個整體的流程就是讓大家稍微有個印象。

數據庫緩存方案大全(什麼是數據庫的)1

image

2、Buffer Pool 有多大

Buffer Pool 是 InnoDB 中的一塊内存區域,他一定是有自己的大小的,且大小默認是 128M,不過這個容量似乎有點小了,大家的自己的生産環境可以根據實際的内存大小進行調整,參數為:innodb_buffer_pool_size=2147483648 單位是字節,

# 查看和調整innodb_buffer_pool_size 1\. 查看@@innodb_buffer_pool_size大小,單位字節 SELECT @@innodb_buffer_pool_size/1024/1024/1024; #字節轉為G 2\. 在線調整InnoDB緩沖池大小,如果不設置,默認為128M set global innodb_buffer_pool_size = 4227858432; ##單位字節

他在 InnoDB 中的整體結構大概是這樣子的

數據庫緩存方案大全(什麼是數據庫的)2

image

3、數據頁

剛剛介紹到 MySQL在執行增删改的時候數據是會被加載到 Buffer Pool 中的,既然這樣數據是怎麼被加載進來的,是一條一條還是說是以其他的形式呢。我們操作的數據都是以表 行的方式,而表 行僅僅是邏輯上的概念,MySQL并不會像我們一樣去操作行數據,而是抽象出來一個一個的數據頁概念,每個數據頁的大小默認是 16KB,這些參數都是可以調整的。但是建議使用默認的就好,畢竟 MySQL能做到極緻的都已經做了。每個數據頁存放着多條的數據,MySQL在執行增删改首先會定位到這條數據所在數據頁,然後會将數據所在的數據頁加載到 Buffer Pool 中。

數據庫緩存方案大全(什麼是數據庫的)3

4、緩存頁

當數據頁被加載到緩沖池中後,Buffer Pool 中也有叫緩存頁的概念與其一一對應,大小同樣是 16KB,但是 MySQL還為每個緩存也開辟額外的一些空間,用來描述對應的緩存頁的一些信息,例如:數據頁所屬的表空間,數據頁号,這些描述數據塊的大小大概是緩存頁的15%左右(約800B)。

# 緩存頁是什麼時候被創建的? 當 MSql 啟動的時候,就會初始化 Buffer Pool,這個時候 MySQL 會根據系統中設置的 innodb_buffer_pool_size 大小去内存中申請一塊連續的内存空間,實際上在這個内存區域比配置的值稍微大一些,因為【描述數據】也是占用一定的内存空間的,當在内存區域申請完畢之後, MySql 會根據默認的緩存頁的大小(16KB)和對應`緩存頁*15%`大小(800B左右)的數據描述的大小,将内存區域劃分為一個個的緩存頁和對應的描述數據

數據庫緩存方案大全(什麼是數據庫的)4

5、Free鍊表

上面是說了每個數據頁會被加載到一個緩存頁中,但是加載的時候 MySQL是如何知道那個緩存頁有數據,那個緩存頁沒有數據呢?換句話說, MySQL是怎麼區分哪些緩存頁是空閑的狀态,是可以用來存放數據頁的。

為了解決這個問題, MySQL 為 Buffer Pool 設計了一個雙向鍊表— free鍊表,這個 free 鍊表的作用就是用來保存空閑緩存頁的描述塊(這句話這麼說其實不嚴謹,換句話:每個空閑緩存頁的描述數據組成一個雙向鍊表,這個鍊表就是free鍊表)。之所以說free鍊表的作用就是用來保存空閑緩存頁的描述數據是為了先讓大家明白 free 鍊表的作用,另外 free 鍊表還會有一個基礎節點,他會引用該鍊表的頭結點和尾結點,還會記錄節點的個數(也就是可用的空閑的緩存頁的個數)。

這個時候,他可以用下面的圖片來描述:

數據庫緩存方案大全(什麼是數據庫的)5

當加載數據頁到緩存池中的時候, MySQL會從 free 鍊表中獲取一個描述數據的信息,根據描述節點的信息拿到其對應的緩存頁,然後将數據頁信息放到該緩存頁中,同時将鍊表中的該描述數據的節點移除。這就是數據頁被讀取 Buffer Pool 中的緩存頁的過程。

但 MySQL是怎麼知道哪些數據頁已經被緩存了,哪些沒有被緩存呢。實際上數據庫中還有後一個哈希表結構,他的作用是用來存儲表空間号 數據頁号作為數據頁的key,緩存頁對應的地址作為其value,這樣數據在加載的時候就會通過哈希表中的key來确定數據頁是否被緩存了。

數據庫緩存方案大全(什麼是數據庫的)6

6、Flush鍊表

MySql 在執行增删改的時候會一直将數據以數據頁的形式加載到 Buffer Pool 的緩存頁中,增删改的操作都是在内存中執行的,然後會有一個後台的線程數将髒數據刷新到磁盤中,但是後台的線程肯定是需要知道應該刷新哪些啊。

針對這個問題,MySQL設計出了 Flush 鍊表,他的作用就是記錄被修改過的髒數據所在的緩存頁對應的描述數據。如果内存中的數據和數據庫和數據庫中的數據不一樣,那這些數據我們就稱之為髒數據,髒數據之所以叫髒數據,本質上就是被緩存到緩存池中的數據被修改了,但是還沒有刷新到磁盤中。

同樣的這些已經被修改了的數據所在的緩存頁的描述數據會被維護到 Flush 中(其實結構和 free 鍊表是一樣的),所以 Flush 中維護的是一些髒數據數據描述(準确地說是髒數據的所在的緩存頁的數據描述)

另外,當某個髒緩存頁被刷新到磁盤後,其空間就騰出來了,然後又會跑到 Free 鍊表中了。

數據庫緩存方案大全(什麼是數據庫的)7

7、LRU鍊表

如果系統一直在進行數據庫的增删改操作,數據庫内部的基本流程就是:

數據庫緩存方案大全(什麼是數據庫的)8

我們還拿 redis 類做類比,以便更好地幫助大家明白其原理。Flush 的作用其實類似 redis 的 key 設置的過期時間,所以一般情況下,redis 内存不會不夠使用,但是總有特殊的情況,問題往往就是在這種極端和邊邊角角的情況下産生的。

如果 redis 的内存不夠使用了,是不是自己還有一定的淘汰策略?最基本的準則就是淘汰掉不經常使用到的key。Buffer Pool 也類似,它也會有内存不夠使用的情況,它是通過 LRU 鍊表來維護的。LRU 即 Least Recently Uesd(最近最少使用)。

MySql 會把最近使用最少的緩存頁數據刷入到磁盤去,那 MySql 如何判斷出 LRU 數據的呢?為此 MySql 專門設計了 LUR 鍊表,還引入了另一個概念:緩存命中率

# 緩存命中率 可以理解為緩存被使用到的頻率,舉個例子來說:現在有兩個緩存頁,在100次請求中A緩存頁被命中了20次,B緩存頁被命中了2次,很顯然A緩存頁的命中率更高,這也就意味着A在未來還會被使用到的可能性比較大,而B就會被 MySQL 認為基本不會被使用到;

說到這裡,那LRU究竟是怎麼工作的。假設 MySQL在将數據加載到緩存池的時候,他會将被加載進來的緩存頁按照被加載進來的順序插入到LRU鍊表的頭部(就是鍊表的頭插法),假設 MySQL現在先後分别加載A、B、C數據頁到緩存頁A、B、C中,然後 LRU 的鍊表大緻是這樣子的。

數據庫緩存方案大全(什麼是數據庫的)9

現在又來了一個請求,假設查詢到的數據是已經被緩存在緩存頁B中,這時候 MySQL就會将B緩存頁對應的描述信息插入到LRU鍊表的頭部,如下圖:

數據庫緩存方案大全(什麼是數據庫的)10

然後又來了一個請求,數據是已經被緩存在了緩存頁C中,然後LRU會變成這樣子:

數據庫緩存方案大全(什麼是數據庫的)11

說到底,每次查詢數據的時候如果數據已經在緩存頁中,那麼就會将該緩存頁對應的描述信息放到LRU鍊表的頭部,如果不在緩存頁中,就去磁盤中查找,如果查找到了,就将其加載到緩存中,并将該數據對應的緩存頁的描述信息插入到LRU鍊表的頭部。也就是說最近使用的緩存頁都會排在前面,而排在後面的說明是不經常被使用到的。

最後,如果 Buffer Pool 不夠使用了,那麼 MySQL就會将 LRU 鍊表中的尾節點刷入到磁盤中,用來給 Buffer Pool 騰出内存空間。把整體的流程圖給大家看下

數據庫緩存方案大全(什麼是數據庫的)12

8、LRU鍊表帶來的麻煩

這裡的麻煩指的是就是 MySQL本身的預讀機制帶來的問題

# 預讀機制 MySQL 在從磁盤加載數據的的時候,會将數據頁的相鄰的其他的數據頁也加載到緩存中。 # MySQL 為什麼要這麼做 因為根據經驗和習慣,一般查詢數據的時候往往還會查詢該數據相鄰前後的一些數據,有人可能會反問:一個數據頁上面不是就會存在該條數據相鄰的數據嗎?這可不一定,某條數據可能很大,也可能這條數據是在數據頁在頭部,也可能是在數據頁的尾部,所以 MySQL 為了提高效率,會将某個數據頁的相鄰的數據頁也加載到緩存池中。

數據庫緩存方案大全(什麼是數據庫的)13

image

上圖能夠看到B的相鄰也被加載到了C描述數據的前面,而實際上C的命中率比B的相鄰頁高多了,這就是LRU本身帶來的問題。

# 哪些情況會觸發預讀機制 1\. 有一個參數是 innodb_read_ahead_threshold, 他的默認值是56,意思就是如果順序的訪問了一個區裡的多個數據頁,訪問的數據頁的數量超過了這個阈值,此時就會觸發預讀機制,把下一個相鄰區中的所有數據頁都加載到緩存裡去(這種就是:線性預讀) 2\. 如果 Buffer Pool 裡緩存了一個區裡的13個連續的數據頁,而且這些數據頁都是比較頻繁會被訪問的,此時就會直接觸發預讀機制,把這個區裡的其他的數據頁都加載到緩存裡去(這種就是:随機預讀)随機預讀是通過:innodb_random_read_ahead 來控制的,默認是OFF即關閉的(MySQL 5.5已經基本飛起該功能,應為他會帶來不必要的麻煩,這裡也不推薦大家開啟,說出來的目的是讓大家了解下有這麼個東西)

還有一種情況是 SELECT * FROM students 這種直接全表掃描的,會直接加載表中的所有的數據到緩存中,這些數據基本是加載的時候查詢一次,後面就基本使用不到了,但是加載這麼多數據到鍊表的頭部就将其他的經常命中的緩存頁直接全擠到後面去了。

以上種種迹象表明,預讀機制帶來的問題還是蠻大的,既然這麼大,那 MySQL為什麼還要進入預讀機制呢,說到底還是為了提高效率,****一種新的技術的引進,往往帶來新的挑戰****,下面我們就一起來看下 MySQL是如何解決預加載所帶來的麻煩的。

9、基于冷熱數據分離的LRU鍊表

所謂的冷熱分離,就是将 LRU 鍊表分成兩部分,一部分是經常被使用到的熱數據,另一部分是被加載進來但是很少使用的冷數據。通過參數innodb_old_blocks_pct 參數控制的,默認為37,也就是 37% 。用圖表示大緻如下:

數據庫緩存方案大全(什麼是數據庫的)14

image

數據在從磁盤被加載到緩存池的時候,首先是會被放在冷數據區的頭部,然後在一定時間之後,如果再次訪問了這個數據,那麼這個數據所在的緩存頁對應描述數據就會被放轉移到熱數據區鍊表的頭部。

那為什麼說是在一定的時間之後呢,假設某條數據剛被加載到緩存池中,然後緊接着又被訪問了一次,這個時候假設就将其轉移到熱數據區鍊表的頭部,但是以後就再也不會被使用了,這樣子是不是就還是會存在之前的問題呢?

所以 MySQL通過innodb_old_blocks_time來設置數據被加載到緩存池後的多少時間之後再次被訪問,才會将該數據轉移到熱數據區鍊表的頭部,該參數默認是1000單位為:毫秒,也就是1秒之後,如果該數據又被訪問了,那麼這個時候才會将該數據從 LRU 鍊表的冷數據區轉移到熱數據區。

現在再回頭看下上面的問題

# 通過預加載(加載相鄰數據頁)進來的數據 1\. 這個時候就很好理解了,反正數據會被放在LRU鍊表的冷數據區的(注意:這裡說的放在鍊表中的數據都是指的是<緩存頁中的數據所對應的描述數據>),當在指定時候之後,如果某些緩存頁被訪問了那麼就将該緩存頁的描述數據放到熱數據區鍊表的頭部 # 全表掃描加載進來的數據頁 1\. 和上面一樣,數據都是先在冷數據區,然後在一定時間之後,再次被訪問到的數據頁才會轉移到熱數據區的鍊表的頭結點,所以這也就很好的解決了全表掃描所帶來的問題

再來思考下 Buffer Pool 内存不夠的問題

# Buffer Pool 内存空間不夠使用了怎麼辦?也就是說沒有足夠使用的空閑的緩存頁了。 1\. 這個問題在這個時候就顯得非常簡單了,直接将鍊表冷數據區的尾節點的描述數據多對應的緩存頁刷到磁盤即可。

但是這樣子還不是足夠完美,為什麼這麼說,剛剛我們一直在讨論的是冷數據區的數據被訪問,然後在一定規則之下會被加載到熱數據鍊表的頭部,但是現在某個請求需要訪問的數據就在熱數據區,那是不是直接把該數據所在的緩存頁對應的描述數據轉移到熱數據區鍊表頭部呢?

很顯然不是這樣子的,因為熱數據區的數據本身就是會被頻繁訪問的,這樣子如果每次訪問都去移動鍊表,勢必造成性能的下降(影響再小極端情況下也可能會不可控),所以 MySQL針對熱數據區的數據的轉移也有相關的規則。

該規則就是:如果被訪問的數據所在的緩存頁在熱數據區的前25%,那麼該緩存頁對應的描述數據是不會被轉移到熱數據鍊表的頭部的,隻有當被訪問的緩存頁對應的描述數據在熱數據區鍊表的後75%,該緩存頁的描述數據才會被轉移到熱數據鍊表的頭部

舉個例子來說,假設熱數據區有100個緩存頁(這裡的緩存頁還是指的是緩存頁對應的描述數據,再強調下,鍊表中存放的是緩存頁的描述數據,為了方便有時候會直接說緩存頁。希望朋友們注意),當被訪問的緩存頁在前25個的時候,熱數據區的鍊表是不會有變化的,當被訪問的緩存頁在26~100(也就是數據在熱數據區鍊表的後75%裡面)的時候,這個時候被訪問的緩存頁才會被轉移到鍊表的頭部。

到此為止, MySQL對于LUR 鍊表的優化就堪稱完美了。是不是看到這裡瞬間感覺很多東西都明朗了,好了,對于 LRU 鍊表我們就讨論到這裡了。

10、Buffer Pool 中的鍊表小結

# free鍊表 用來存放空閑的緩存頁的描述數據,如果某個緩存頁被使用了,那麼該緩存頁對應的描述數據就會被從free鍊表中移除 # flush鍊表 被修改的髒數據都記錄在 Flush 中,同時會有一個後台線程會不定時的将 Flush 中記錄的描述數據對應的緩存頁刷新到磁盤中,如果某個緩存頁被刷新到磁盤中了,那麼該緩存頁對應的描述數據會從 Flush 中移除,同時也會從LRU鍊表中移除(因為該數據已經不在 Buffer Pool 中了,已經被刷入到磁盤,所以就也沒必要記錄在 LRU 鍊表中了),同時還會将該緩存頁的描述數據添加到free鍊表中,因為該緩存頁變得空閑了。 # LRU鍊表 數據頁被加載到 Buffer Pool 中的對應的緩存頁後,同時會将緩存頁對應的描述數據放到 LRU 鍊表的冷數據的頭部,當在一定時間過後,冷數據區的數據被再次訪問了,就會将其轉移到熱數據區鍊表的頭部,如果被訪問的數據就在熱數據區,那麼如果是在前25%就不會移動,如果在後75%仍然會将其轉移到熱數據區鍊表的頭部

後台線程将冷數據區的尾節點的描述數據對應的緩存頁刷入磁盤文件中

數據庫緩存方案大全(什麼是數據庫的)15

image

11、Buffer Pool 的并發性能

我們平時的系統絕對不可能每次隻有一個請求來訪問的,說白了就是如果多個請求同時來執行增删改,那他們會并行的去操作 Buffer Pool 中的各種鍊表嗎?如果是并行的會不會有什麼問題。

實際上 MySQL在處理這個問題的時候考慮的非常簡單,就是: Buffer Pool 一次隻能允許一個線程來操作,一次隻有一個線程來執行這一系列的操作,因為MySQL 為了保證數據的一緻性,操作的時候必須緩存池加鎖,一次隻能有一個線程獲取到鎖

這個時候,大家這時候肯定滿腦子問号。串行那還談什麼效率?大家别忘記了,這一系列的操作都是在内存中操作的,實際上這是一個瞬時的過程,在内存中的操作基本是幾毫秒的甚至微妙級别的事情。

但是話又說回來,串行執行再怎麼快也是串行,雖然不是性能瓶頸,這還有更好的優化辦法嗎?那肯定的 MySQL早就設計好了這些規則。那就是 Buffer Pool 是可以有多個的,可以通過 MySQL的配置文件來配置,參數分别是:

# Buffer Pool 的總大小 innodb_buffer_pool_size=8589934592 # Buffer Pool 的實例數(個數) innodb_buffer_pool_instance=4

一般在生産環境中,在硬件不緊張的情況下,建議使用此策略。這個時候大家是不是又會有一個疑問(如果沒有那說明你沒認真思考哦),大家應該有這樣的疑問:

# 問:多個 Buffer Pool 所帶來的問題思考 在多個線程訪問不同的 Buffer Pool 那不同的線程加載的數據必然是在不同的 Buffer Pool 中,假設 A 線程加載數據頁A到 Buffer Pool A 中,B 線程加載數據頁B到 Buffer Pool B 中,然後兩個都執行完了,這個時候 C 線程來了,他到達的是 Buffer Pool B中,但是 C 要訪問的數據是在 Buffer Pool A中的數據頁上了,這個時候 C 還會去加載數據頁A嗎?,這種情況會發生嗎?在不同的 Buffer Pool 緩存中會去緩存相同的數據頁嗎? # 答:多個 Buffer Pool 所帶來的問題解答 這種情況很顯然不會發生,既然不會發生,那 MySql 是如何解決這種問題的?其實前面已經提到過了,那就是 數據頁緩存哈希表(看下圖),裡面存放的是表空間号 數據頁号 = 緩存頁地址,所以 MySQL 在加載數據所在的數據頁的時候根據這一系列的映射關系判斷數據頁是否被加載,被加載到了那個緩存頁中,所以 MySQL 能夠精确的确定某個數據頁是否被加載,被加載的到了哪個緩存頁,絕不可能出現重複加載的情況。

數據庫緩存方案大全(什麼是數據庫的)16

image

12、動态調整 Buffer Pool 的大小

到此為止,本文已經詳細的介紹了 Buffer Pool 的内存結構,它的數據是如何存放的,如何刷磁盤的,又是如何加載的,以什麼樣的形式存在的等等知識點,下面我們繼續挖掘,将 Buffer Pool 的相關知識點一次說個夠。我們現在來讨論下 Buffer Pool 的大小能否動态調整。

假設我們現在的 Buffer Pool 的大小是 2GB大小,現在想将其擴大到 4GB,現在說一下如果真的要這麼做,我們的 MySq 需要做哪些事情。首先 ,MySQL 需要向操作系統申請一塊大小為 4G 的連續的地址連續的内存空間,然後将原來的 Buffer Pool 中的數據拷貝到新的 Buffer Pool 中。

這樣可能嗎?如果原來的是8G,擴大到 16G,那這個将原來的數據複制到新的 Buffer Pool 中是不是極為耗時的,所以這樣的操作 MySQL必然是不支持的。但實際上這樣的需求是客觀存在的,那 MySQL是如何解決的呢?

為了處理這種情況,MySQL設計出 chunk (http 協議中也有使用到這個思想,所以我們會發現很多技術的優秀思想都是在相互借鑒)機制來解決的

# 什麼是chunk機制 chunk是 MySQL 設計的一種機制,這種機制的原理是将 Buffer Pool 拆分一個一個大小相等的 chunk 塊,每個 chunk 默認大小為 128M(可以通過參數innodb_buffer_pool_chunk_size 來調整大小),也就是說 Buffer Pool 是由一個個的chunk組成的 假設 Buffer Pool 大小是2GB,而一個chunk大小默認是128M,也就是說一個2GB大小的 Buffer Pool 裡面由16個 chunk 組成,每個chunk中有自己的緩存頁和描述數據,而 free 鍊表、flush 鍊表和 lru 鍊表是共享的

數據庫緩存方案大全(什麼是數據庫的)17

image

如果說有多個 Buffer Pool ,那就是這樣

數據庫緩存方案大全(什麼是數據庫的)18

image

說到這裡好像還是沒有說到 MySQL到底是如何通過 chunk 機制來調整大小的。實際上是這樣的,假設現在 Buffer Pool 有 2GB,裡面有16個chunk,現在想要擴大到 4GB,那麼這個時候隻需要新申請一個個的 chunk 就可以了。

這樣不但不需要申請一塊很大的連續的空間,更不需要将複制數據。這樣就能達到動态調整大小了(不會還有人問:這隻是擴大,怎麼縮小呢?gun)。不得不說 MySQL真機智。

13、生産環境如何設置 Buffer Pool 大小

Buffer Pool 是不是越大越好,理論上是的。那如果一個機器内存是16GB那分配給 Buffer Pool 15GB,這樣很顯然是不行的,因為操作系統要占内存,你的機器上總會運行其他的進行的吧?那肯定也是需要占用内存的。根據很多實際生産經驗得出得比較合理的大小是機器内存大小的(50%~60%)。

最後一起來看看你的 INNODB 的相關參數,命令是show engine innodb status

show engine innodb status; ---------------------- Buffer Pool AND MEMORY ---------------------- -- Buffer Pool 的最終大小 Total memory allocated -- Buffer Pool 一共有多少個緩存頁 Buffer Pool size -- free 鍊表中一共有多少個緩存也是可以使用的 Free buffers -- lru鍊表中一共有多少個緩存頁 Database pages -- lru鍊表鍊表中的冷數據區一共有多少個緩存頁 Old database pages -- flush鍊表中的緩存頁的數量 Modified db pages -- 等待從磁盤上加載進來的緩存頁的數量 Pending reads -- 即将從lru鍊表中刷入磁盤的數量,flush鍊表中即将刷入磁盤的緩存頁的數量 Pending writes: LRU 0, flush list 0, single page 0 -- lru鍊表的冷數據區的緩存頁被訪問之後轉移到熱數據區的緩存頁的數量,以及冷數據區裡1s之内被訪問但是沒有進入到熱數據區的緩存頁的數量 Pages made young 260368814, not young 0 -- 每秒從冷數據轉移到熱數據區的緩存頁的數量,以及每秒在冷數據區被訪問但是沒有進入熱數據區的緩存頁的數量 332.69 youngs/s, 0.00 non-youngs/s -- 已經讀取創建和寫入的緩存頁的數量,以及每秒讀取、創建和寫入的緩存頁的數量 Pages read 249280313, created 1075315, written 32924991 359.96 reads/s, 0.02 creates/s, 0.23 writes/s -- 表示1000次訪問中,有多少次是命中了BufferPool緩存中的緩存頁,以及每1000次訪問有多少數據從冷數據區轉移到熱數據區,以及沒有轉移的緩存頁的數量 Buffer Pool hit rate 867 / 1000, young-making rate 123 / 1000 not 0 / 1000 -- lru鍊表中緩存頁的數量 LRU len: 8190 -- 最近50s讀取磁盤頁的總數,cur[0]表示現在正在讀取的磁盤頁的總數 I/O sum[5198]:cur[0],

14、結束語

本篇文章我們詳細讨論了 Buffer Pool 的内存結構,從 free 鍊表到 lru 鍊表,從 Buffer Pool 到 chunk,從磁盤中加載一個數據頁到 Buffer Pool 到最後該數據頁又被刷回到磁盤中的一整個過程,他的每一步都做了什麼。

我們一起讨論完本文以後,是不是瞬間有種看頭來了 MySQL的感覺,但是這個僅僅是前提,學習這些的目的是為了更好的理解 MySQL讓我們能夠在工作中更加遊刃有餘地使用它。因為隻有在知道了底層原理的情況下,才能熟悉他的工作原理,遇到問題才能對症下藥。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved