MySQL 內建 Query Cache 將「完全相同的 SELECT 文本」與結果集綁定緩存,命中時繞過解析、優化、執行直接返回。但其大小寫敏感、含非確定性函數不緩存、失效機制激進 等特性導致高併發寫入場景下反成累贅。本文梳理核心參數、啟用判斷、監控指標、最佳實踐。
| 參數 | 作用 | 典型值/建議 |
|---|---|---|
have_query_cache | 是否編譯支援(只讀) | YES/NO |
query_cache_type | 啟用模式 | OFF(0)/ON(1)/DEMAND(2) |
query_cache_size | 緩存總內存(0=禁用) | 64MB-512MB,**勿超 1GB**(鎖競爭劇增) |
query_cache_limit | 單個結果集最大緩存 | 1MB-4MB,防大結果集佔滿 |
query_cache_min_res_unit | 分配最小塊(影響碎片) | 4KB-8KB |
SELECT * FROM t ≠ select * from t ≠ SELECT * FROM t (尾隨空格)。應用層必須統一 SQL 格式化。NOW()、RAND()、UUID()、CURRENT_DATE 等導致不緩存。INSERT/UPDATE/DELETE/TRUNCATE 觸發該表所有緩存條目失效,**鎖住 query_cache_lock**,高寫入場景成熱點。IF (讀寫比 > 10:1) AND (表數據相對靜態) AND (SQL 文本高度可復用)
THEN 啟用 query_cache_type=DEMAND, 關鍵查詢用 SQL_CACHE
ELSE IF (寫入頻繁 OR 表數據高度動態 OR SQL 參數化差)
THEN 關閉 query_cache_type=OFF, query_cache_size=0
ELSE 保持關閉,觀察 Qcache_hit_rate 指標再決策
SHOW STATUS LIKE 'Qcache%';
-- 關鍵指標:
Qcache_hits / (Qcache_hits + Qcache_inserts + Qcache_not_cached) -- 命中率
Qcache_lowmem_prunes -- 因內存不足淘汰次數(持續增長 = 容量不足或碎片嚴重)
Qcache_free_blocks / Qcache_total_blocks -- 碎片率(> 0.3 需 FLUSH QUERY CACHE)
Qcache_queries_in_cache -- 當前緩存條目數
FLUSH QUERY CACHE:整理碎片,**不清空內容**。RESET QUERY CACHE / FLUSH TABLES:**清空所有緩存**。SELECT SQL_CACHE ... / SELECT SQL_NO_CACHE ...:DEMAND 模式下顯式控制單條語句緩存行為。query_cache_type=OFF, query_cache_size=0),MySQL 8.0 已移除該功能。DEMAND 模式。FLUSH QUERY CACHE 整理碎片,監控 Qcache_lowmem_prunes 趨勢。SQL_NO_CACHE,避免污染緩存池。Query Cache 是把雙刃劍:命中即極速,失效即開銷。MySQL 5.7 仍保留但已棄用,8.0 徹底移除。現代架構應轉向應用層緩存,利用 Redis/Memcached 實現業務感知的緩存策略(TTL、主動失效、標籤分組),而非依賴數據庫層面的粗暴文本匹配。