首頁>技術>

快取的重要性

我們只需要訪問一個頁的一條記錄,那也需要先把整個頁的資料載入到記憶體中。將整個頁載入到記憶體中後就可以進行讀寫訪問了,在進行完讀寫訪問之後並不著急把該頁對應的記憶體空間釋放掉,而是將其快取起來,這樣將來有請求再次訪問該頁面時,就可以省去磁碟IO的開銷了。這樣能夠大大的增加效率。

InnoDB的Buffer PoolBuffer Pool的概念

設計InnoDB的大叔為了快取磁碟中的頁,在MySQL伺服器啟動的時候就向作業系統申請了一片連續的記憶體,他們給這片記憶體起了個名,叫做Buffer Pool(中文名是緩衝池)。那它有多大呢?這個其實看我們機器的配置,如果你是土豪,你有512G記憶體,你分配個幾百G作為Buffer Pool也可以啊,當然你要是沒那麼有錢,設定小點也行呀~ 預設情況下Buffer Pool只有128M大小。當然如果你嫌棄這個128M太大或者太小,可以在啟動伺服器的時候配置innodb_buffer_pool_size引數的值,它表示Buffer Pool的大小,就像這樣: [server] innodb_buffer_pool_size = 268435456 其中,268435456的單位是位元組,也就是我指定Buffer Pool的大小為256M。需要注意的是,Buffer Pool也不能太小,最小值為5M(當小於該值時會自動設定成5M)。

Buffer Pool內部結構

Buffer Pool中預設的快取頁大小和在磁碟上預設的頁大小是一樣的,都是16KB。為了更好的管理這些在Buffer Pool中的快取頁,設計InnoDB的大叔為每一個快取頁都建立了一些所謂的控制資訊,這些控制資訊包括該頁所屬的表空間編號、頁號、快取頁在Buffer Pool中的地址、連結串列節點資訊、一些鎖資訊以及LSN資訊。 每個快取頁對應的控制資訊佔用的記憶體大小是相同的,我們就把每個頁對應的控制資訊佔用的一塊記憶體稱為一個控制塊吧,控制塊和快取頁是一一對應的,它們都被存放到 Buffer Pool 中,其中控制塊被存放到 Buffer Pool 的前邊,快取頁被存放到 Buffer Pool 後邊,所以整個Buffer Pool對應的記憶體空間看起來就是這樣的:

每一個控制塊都對應一個快取頁,那在分配足夠多的控制塊和快取頁後,可能剩餘的那點兒空間不夠一對控制塊和快取頁的大小,自然就用不到嘍,這個用不到的那點兒記憶體空間就被稱為碎片了。當然,如果你把Buffer Pool的大小設定的剛剛好的話,也可能不會產生碎片~

free連結串列的管理

因為我們沒法得意buffer pool的那些記憶體被使用了,也沒有辦法哪些是空閒的能夠被使用的,所以我們用控制塊來管理快取頁,控制塊裡有一個free連結串列來管理快取頁的使用情況。

有了這個free連結串列之後事兒就好辦了,每當需要從磁碟中載入一個頁到Buffer Pool中時,就從free連結串列中取一個空閒的快取頁,並且把該快取頁對應的控制塊的資訊填上(就是該頁所在的表空間、頁號之類的資訊),然後把該快取頁對應的free連結串列節點從連結串列中移除,表示該快取頁已經被使用了~

快取頁的雜湊處理

我們如何去訪問某個資料呢,如果資料載入到buffer pool中,我們怎麼才能準確的知道,這個內容是不是已經載入到了beffer pool中呢,是這樣的,我們其實是透過表空間號+頁號當作key透過hash演算法來定位,快取頁就是一個value,透過hash表的方式,去定址如果有的話就直接使用,如果沒有的話,我們就把資料從磁碟中載入進來。

flush連結串列的管理

如果beffer pool其中某一頁的資料被修改,那麼她就和磁碟中的資料不一致了,我們給這種資料一個狀態,我們稱它是dirty,當然最簡單的方法是一被修改我們立刻重新整理到磁碟中保持高度的一致性,但是頻繁的刷盤會影響效能,所以一般情況下,我們都是到某一個時間點或者某一個條件然後去刷盤的。那麼我們如何才能快速的定位到需要刷盤的資料呢,也就是我們所說的dirty page。其實快取頁一被修改我們就把放到了一個專門放dirty page的連結串列中,我們稱它為flush連結串列,當需要刷盤的時候一起進行刷盤。

17
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Java設計模式教程釋出(文件和原始碼開源)