MYSQL 緩存詳解 [myownstars] 經典博客



http://blog.itpub.net/15480802/viewspace-755582/

在服務器級別只提供了query cache,而在存儲引擎級別,MyISAMInnoDB分別引入了key cachebuffer pool

 

什么是query cache

Mysql沒有shared_pool緩存執行計划,但是提供了query cache緩存sql執行結果和文本,如果在生命周期內完全相同的sql再次運行,則連sql解析都免去了;

所謂完全相同,包含如下條件

Sql的大小寫必須完全一樣;

發起sql的客戶端必須使用同樣的字符集和通信協議;

sql查詢同一數據庫下的同一個表(不同數據庫可能有同名表)

Sql查詢結果必須確定,即不能帶有now()等函數;

當查詢表發生DMLDDL,其緩存即失效;

針對mysql/information_schema/performance_schema的查詢不緩存;

使用臨時表的sql也不能緩存;

 

開啟緩存后,每個select先檢查是否有可用緩存(必須對這些表有select權限),而每個寫入操作先執行查詢語句並使相關緩存失效;

5.5起可緩存基於視圖的查詢

 

Mysql維護一個hash表用來查找緩存,其keysql text,數據庫名以及客戶端協議的版本等

相應參數

Have_query_cache:服務器是否支持查詢緩存

Query_cache_type0(OFF)不緩存;1(ON)緩存查詢但不包括使用SQL_NO_CACHEsql2(DEMAND)只緩存使用SQL_CACHEsql

Query_cache_size:字節為單位,即使query_cache_type=0也會為分配該內存,所以應該一並設置為0

Query_cache_limit:允許緩存的最大結果集,大於此的sql不予緩存

Query_cache_min_res_limit:用於限定塊的最小尺寸,默認4K

 

緩存的metadata占有40K內存,其可分為大小不等的多個子塊,各塊之間使用雙向鏈表鏈接;根據其功能分別存儲查詢結果,基表和sql text等;

每個sql至少用到兩個塊:分別存儲sql文本和查詢結果,查詢引用到的表各占一個塊;

為了減少響應時間,每產生1行數據就發送給客戶端;

數據庫啟動時調用malloc()分配查詢緩存

 

查詢緩存擁有一個全局鎖,一旦有會話獲取就會阻塞其他訪問緩存的會話,因此當緩存大量sql時,緩存invalidation可能會消耗較長時間;

 

Innodb也可以使用查詢緩存,每個表在數據字典中都有一個事務ID計數器,ID小於此值的事務不可使用緩存;表如果有鎖(任何鎖)則也不可使用查詢緩存;

 

 狀態變量

有關query cache的狀態變量都以Qcache打頭

mysql> SHOW STATUS LIKE 'Qcache%';

+-------------------------+--------+

| Variable_name           | Value  |

+-------------------------+--------+

| Qcache_free_blocks      | 36     |

| Qcache_free_memory      | 138488 |

| Qcache_hits             | 79570  |

| Qcache_inserts          | 27087  |

| Qcache_lowmem_prunes    | 3114   |

| Qcache_not_cached       | 22989  |

| Qcache_queries_in_cache | 415    |

| Qcache_total_blocks     | 912    |

+-------------------------+--------+

Qcache_inserts—被加到緩存中query數目

Qcache_queries_in_cache—注冊到緩存中的query數目

緩存每被命中一次,Qcache_hits就加1

計算緩存query的平均大小=(query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache

Com_select = Qcache_not_cached + Qcache_inserts + queries with errors found during the column-privileges check

Select = Qcache_hits + queries with errors found by parser

 

 

Buffer pool

innodb即緩存表又緩存索引,還有設置多個緩沖池以增加並發,很像oracle

采用LRU算法:

所有buffer塊位於同一列表,其中后3/8old,每當新讀入一個數據塊時,先從隊尾移除同等塊數然后插入到old子列的頭部,如再次訪問該塊則將其移至new子列的頭部

Innodb_buffer_pool_size:  buffer pool大小

Innodb_buffer_pool_instances: buffer pool數量,buffer pool至少為1G時才能生效

Innodb_old_blocks_pct: 范圍5 – 95 默認為373/8,指定old子列的比重

Innodb_old_blocks_time: ms為單位,新插入old子列的buffer塊必須等待指定時間后才能移入new列,適用於one-time scan頻繁的操作,以避免經常訪問的數據塊被剔出buffer pool

 

可通過狀態變量獲知當前buffer pool的運行信息

Innodb_buffer_pool_pages_total:緩存池總頁數

Innodb_buffer_pool_bytes_data:當前buffer pool緩存的數據大小,包括臟數據

Innodb_buffer_pool_pages_data:緩存數據的頁數量

Innodb_buffer_pool_bytes_dirty:緩存的臟數據大小

Innodb_buffer_pool_pages_diry:緩存臟數據頁數量

Innodb_buffer_pool_pages_flush:刷新頁請求數量

Innodb_buffer_pool_pages_free:空閑頁數量

Innodb_buffer_pool_pages_latched:緩存中被latch的頁數量,這些頁此刻正在被讀或寫;然而計算此變量比較消耗資源,只有在UNIV_DEBUG被定義了才可用

相關源代碼如下

#ifdef UNIV_DEBUG
  {"buffer_pool_pages_latched",
  (char*) &export_vars.innodb_buffer_pool_pages_latched,  SHOW_LONG},
#endif /* UNIV_DEBUG */

 

Innodb_buffer_pool_pages_misc:用於維護諸如行級鎖或自適應hash索引的內存頁=總頁數-空閑頁-使用的頁數量

Innodb_buffer_pool_read_ahead:預讀入緩存的頁數量

Innodb_buffer_pool_read_ahead_evicted:預讀入但是1次都沒用就被剔出緩存的頁

Innodb_buffer_pool_read_requests:InnoDB的邏輯讀請求次數

Innodb_buffer_pool_reads:直接從磁盤讀取數據的邏輯讀次數

Innodb_buffer_pool_wait_free:緩存中沒有空閑頁滿足當前請求,必須等待部分頁回收或刷新,記錄等待次數

Innodb_buffer_pool_write_requests:向緩存的寫數量

 

 

可使用innodb standard monitor監控buffer pool的使用情況,主要有如下指標:

Old database pages: old子列中的頁數

Pages made young, not young: old子列移到new子列的頁數,old子列中沒有被再次訪問的頁數

Youngs/s  non-youngs/s: 訪問old並導致其移到new列的次數

 

 

 

Key cache

5.5僅支持一個結構化變量,即key cache,其包含4個部件

Key_buffer_size

Key_cache_block_size:單個塊大小,默認1k

Key_cache_division_limitwarm子列的百分比(默認100)key cache buffer列表的分隔點,用於分隔hostwarm子列表

Key_cache_age_threshold:頁在hot子列中的生命周期,值越小則越快的移至warm列表

 

MyISAM只緩存索引,

可創建多個key buffer—set global hot_cache.key_buffer_size=128*1024

索引指定key buffer—cache index t1 in hot_cache

可在數據庫啟動時load index into key_buffer提前加載緩存,也可通過配置文件自動把索引映射到key cache

 

key_buffer_size = 4G

hot_cache.key_buffer_size = 2G

cold_cache.key_buffer_size = 2G

init_file=/path/to/data-directory/mysqld_init.sql

mysqld_init.sql內容如下

CACHE INDEX db1.t1, db1.t2, db2.t3 IN hot_cache

CACHE INDEX db1.t4, db2.t5, db2.t6 IN cold_cache

 

默認采用LRU算法,也支持名為中間點插入機制midpoint insertion strategy

索引頁剛讀入key cache時,被放在warm列的尾部,被訪問3次后則移到hot列尾並循環移動,如果在hot列頭閑置連續N次都沒訪問到,則會被移到warm列頭,成為被剔出cache的首選;

N= block no* key_cache_age_threshold/100


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM