Mysql的innodb缓冲池管理(转)
原文地址:http://www.chentaoqian.com/archives/587,http://www.chentaoqian.com/archives/590
在數據庫數據處理中, 緩沖在改善性能方面扮演著很重要的角色, 為了保證性能, innodb 維護了自己的緩沖池。 文章大體介紹一下innodb緩沖區實現和管理策略。
在innodb中,需要用到數據頁(需要保存到磁盤的數據)均是從這個緩沖池里分配出來的, 因此,可以說,緩沖池在對innodb的性能有很大的影響。
幾個基本的概念
AWE:地址窗口化擴展,允許在 32 位版本的 Windows 操作系統上使用 4 GB 以上的物理內存。最多可支持 64 GB 的物理內存。更多信息請看 http://baike.baidu.com/view/1390438.htm; innodb是支持AWE內存管理的
Frame;幀,16K的虛擬地址空間, 在緩沖池的管理上,整個緩沖區是是以大小為16k的frame(可以理解為數據塊)為單位來進行的,frame是innodb中頁的大小。
Page: 頁,16K的物理內存, page上存的是需要保存到磁盤上的數據, 這些數據可能是數據記錄信息, 也可以是索引信息或其他的元數據等;
Control Block:控制塊,對于每個frame, 有一個block, block上的信息是專門用于進行frame控制的管理信息, 但是這些信息不需要記錄到磁盤,而是根據讀入數據塊在內存中的狀態動態生成的, 主要包括: 1. 頁面管理的普通信息,互斥鎖, 頁面的狀態, awe(windows平臺上awe機制的管理信息)等 2. 臟回寫(flush)管理信息3. lru控制信息 4. 快速查找的管理信息, 為了便于快速的超找某一個block或frame, 緩沖區里面的block被組織到一些hash表中; 緩沖區中的block的數量是一定得, innodb緩沖區對所管理的block用lru策略進行替換。
互斥訪問
緩沖池的整個緩沖區有一個數據結構buf_pool進行管理和控制, 有一個專門的mutex保護著, 這個mutex是用來保護buf_pool這個控制結構中的數據域的, 并不保護緩沖區中的數據frame以及用于管理的block, 緩沖區里block或者frame中的訪問是由專門的讀寫鎖來保護的, 每個block/frame有一個。在5.1以前, 每個block是沒有專門的mutex保護的,如果需要進行互斥保護,直接使用緩沖區的mutex, 結果導致很高的爭用; 5.1以后,每個block有一個mutex對其進行保護, 從而在很大程度上解緩了對buf_pool的mutex的爭用。
緩沖池管理用到的幾個重要的列表
在緩沖區的管理中, 有幾個重要的block列表(雙向鏈表):
LRU列表: 用來進行lru管理的列表, 列表里的每個block所控制的數據都是當前有效的數據;列表中的block基本是按照訪問的順序排列的;最近被訪問的放在最前面, 最先被方位的放在最后;lru列表中維護中維護了一個LRU_old, 大概指向整個列表的倒數3/8左右, 當增加一個新的block(主語與最近被訪問的block的區別)進來的時候, 把新的塊剛好放到這個點附近, 具體是前還是后取決于這個LRU_old目前的位置, 這么做的目的是使新增加進來的block放到一個合適的位置, 不至于放到最先(最近被使用過)或最后(最老)
flush列表: 列表block是那些所管理的數據被修改但是還沒有更新到磁盤的臟frame, 根據修改的先后順序排列的block列表, 最老的放最后。innodb起來后, 主線程會定期去檢查
緩沖區中可用空閑block的數量的比例, 一旦大于srv_max_buf_pool_modified_pct(90%), 就會試圖把一些臟頁flush到磁盤;除了主線程會定期做這個事情外,工作線程在進行數據操作時 ,如果發現沒有如果的block, 也會通過flush一些臟頁來騰出空間。
free list, 所有空閑block的列表, 當需要分配一個block時, 從中取出一個block。
awe_LRU_free_mapped: 用于方便awe的block列表, 這些block所管理的page已經映射到了frame(物理內存有對應的虛擬內存空間),其中的元素必定也處于free列表或lru列表中。 這個列表會在當分配一個awe頁面時用到。
adaptive hash search: 緩沖區中的頁面是通過雙向列表的方式組織起來的, 如果需要查找根據頁號查找某個頁面block的話, 速度不會快,尤其是數據塊多的時候; 為了加速查找過程,在用雙向列表組織block的時候,也采用了adaptive hash的數據組織, hash的鍵值(key)是頁號(數據頁在所在表空間的編號), 這個在一定程度上能加速block的查找, 但是當以awe方式管理內存的話,這種hash查找方式不會啟用。
頁面讀入機制
當讀入頁面的時候, 首先需要找到一個可用的block, 這個block或者來自于free list或者lru-list; 在讀入數據塊的時候, block會加上排他鎖以防止其他線程再次使用這個block,
會在block中標記出這個塊正處于io狀態, 然后把io請求加入到io調用請求對列; 完成讀入操作時, 再釋放block上的拍它鎖更新io狀態。
數據頁面的讀取寫入
緩沖池中的數據基本是采用同步aio的方式,這里的同步aio的意思是: 工作線程發出讀或寫請求后,請求會被放到一個讀寫請求隊列中,由專門的io線程負責寫盤和讀盤,而工作線程則等待io的完成,
注意, 這里是等待完成,而不會放棄執行,因而稱作為同步aio.
提前讀(預讀)機制
為了優化數據讀入性能, 緩沖區讀入采取了提前讀的機制(當然,這個機制可以配置成不激活),當然, 提前讀的機制是基于數據局部性的原理來的,
這就是為什么采用取值過于隨機的字段作為主鍵會導致性能降低的原因之一:過于隨機的主鍵會導致提前讀不起作用, 而且會導致更多的換頁行為; 這個預讀取對于上層的功能如索引管理是透明的,
對于上層的功能來說, 需要提供的信息是需要讀取的頁是否有后繼頁和前置頁。 有兩種預讀機制: 線性預讀和隨機預讀
線性預讀: 當第一讀緩沖區中某一個已經存在(注意,這里必須是已經存在于緩沖區額數據塊)的數據塊時, 會檢查這個數據塊是不是處于所謂的線性預讀區域(比如, 區域大小是64, 當前讀入的也是100,那么所在的預讀區域是65 ~ 128),如果是, 則統計一下這個區域中目前沒有被訪問過的頁面,如果數量多于預讀機制設定的預讀數量,則放棄本次預讀, 這個其實是檢查目前的區域是否還有大量的頁面沒有被訪問過, 如果是的話, 自然沒有必要去做預讀了; 否則, 取得讀取頁面的后繼頁和前置頁(按照數據頁的自然順序?,然后檢查后繼頁或者前置頁是否是一個新區域的邊界,如果是, 則發出讀取
該區域里面的數據頁面的異步請求。
隨機讀: 當讀取一個頁面時, 根據所讀取頁的位置計算出該頁面所在的隨機預讀區域, 區域的計算也基于設定的區域頁面數量來計算的(如前面關于線性預讀的例子), 然后根據lru對列的信息計算該區域中有多少塊最近被訪問到了, 如果被訪問的數量達到一定的額度(這個額度是根據預讀區域的大小計算出來的, 5 + 預讀區域大小 / 8),則預讀取該區域中目前還沒有讀取到緩沖區的塊.
show innodb status?中關于buffer pool的輸出
Buffer pool size 262144?整個緩沖池中的頁的數量,?包括flush列表中的和flush列表中的,以及被分配出去的頁的數量
Free buffers 0???????????free列表中的頁的數量
Database pages 258053????分配出去,?正在被使用頁的數量
Modified db pages 37491?flush列表中的數量
Pending reads 0??????????發出了請求但沒有完成的io讀個數
Pending writes: LRU 0, flush list 0, single page 0?發出了請求但沒有完成的io讀個數在各個列表上的體現
Pages read 57973114, created 251137, written 10761167,?從磁盤上讀取出來的頁數,?在內存中建立了頁面但是沒有從磁盤上讀取出來的頁面數以及寫入了的頁面數
9.79 reads/s, 0.31 creates/s, 6.00?在剛過去的時間間隔里,?平均每秒的讀取數和新建數
Buffer pool hit rate 999 / 1000???????命中率,?緩沖區中讀到的頁?/?總共發出的讀頁數
與緩沖池相關的狀態變量及含義
| Innodb_buffer_pool_pages_data??????分配出去,?正在被使用頁的數量
| Innodb_buffer_pool_pages_dirty?????臟頁但沒有被flush除去的頁面數
| Innodb_buffer_pool_pages_flushed?????已經flush的頁面數
| Innodb_buffer_pool_pages_free????????當前空閑頁面數
| Innodb_buffer_pool_pages_latched?????當前被鎖住的頁面數
| Innodb_buffer_pool_pages_misc????????用于管理功能的頁面數,?如adaptive hash等
| Innodb_buffer_pool_pages_total????緩沖區總共的頁面數
| Innodb_buffer_pool_read_ahead_rnd?????隨機預讀的次數
| Innodb_buffer_pool_read_ahead_seq?線性預讀的次數
| Innodb_buffer_pool_read_requests?總共從緩沖池中緩存的頁面中讀取出的頁數
| Innodb_buffer_pool_reads?????????????從磁盤上一頁一頁的讀取的頁數,從緩沖池中讀取頁面,?但緩沖池里面沒有,?就會從磁盤讀取
| Innodb_buffer_pool_wait_free????????緩沖池等待空閑頁的次數,?當需要空閑塊而系統中沒有時,?就會等待空閑頁面
| Innodb_buffer_pool_write_requests?緩沖池總共發出的寫請求次數
| Innodb_data_fsyncs????????????????????總共完成的fsync次數
| Innodb_data_pending_fsyncs???????????innodb當前等待的fsync次數
| Innodb_data_pending_reads??????????innodb當前等待的讀的次數
| Innodb_data_pending_writes???????????innodb當前等待的寫的次數
| Innodb_data_read???????????????????????|????總共讀入的字節數
| Innodb_data_reads??????????????????????innodb完成的讀的次數
| Innodb_data_writes???????????????????innodb完成的寫的次數
| Innodb_data_written?????????????????總共寫出的字節數
命中率=innodb_buffer_pool_read_requests / (innodb_buffer_pool_read_requests + innodb_buffer_pool_read_ahead + innodb_buffer_pool_reads)
??? 平均每次讀取的字節數= innodb_data_read / innodb_data_reads
注:innodb_buffer_pool_read_requests:從緩沖池中讀取頁的次數
?????????Innodb_buffer_pool_read_ahead:預讀的次數
?????????Innodb_buffer_pool_reads:從磁盤讀取頁的次數
?????????Innodb_data_read:讀入的字節數
?????????Innodb_data_reads:發起讀取請求的次數,每次讀取可能需要讀取多個頁
轉載于:https://www.cnblogs.com/xuegang/archive/2011/08/29/2158369.html
總結
以上是生活随笔為你收集整理的Mysql的innodb缓冲池管理(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL配置文件my.cnf中文版
- 下一篇: 如何做好项目规划,完成一个保质保量的软件