Query Cache 是 MySQL 基於 SQL 文本精確匹配 的結果集緩存機制。僅針對 SELECT 語句生效,其他(SHOW, USE 等)不緩存。
-- 這三條語句在 QC 中佔用三個獨立槽位
select * FROM people where name='surfchen';
select * FROM people where /*hey~*/name='surfchen';
SELECT * FROM people where name='surfchen';
任一涉及表發生 UPDATE/DELETE/INSERT/TRUNCATE/ALTER 等寫操作,**該表相關的所有 QC 條目全部失效**。頻繁寫入的表開啟 QC 反而會增加開銷(內存分配/釋放、鎖競爭、失效掃描)。
query_cache_min_res_unit 控制(默認 4KB)| 參數 | 說明 | 建議 |
|---|---|---|
| query_cache_type | 0=關閉, 1=開啟(可用 SQL_NO_CACHE 禁用), 2=按需(需 SQL_CACHE 啟用) | 生產環境建議 2,精確控制 |
| query_cache_size | QC 總內存,0 即禁用。需 ≥40KB 結構開銷,單位 1024 字節對齊 | 視命中率調整,典型 64M-256M |
| query_cache_limit | 單個查詢結果超過此值不緩存 | 1M-4M,防止大結果集佔滿池 |
| query_cache_min_res_unit | 每次分配塊大小 | 見下文調優策略 |
SHOW STATUS LIKE 'Qcache%';
| 變量 | 含義 | 異常信號 |
|---|---|---|
| Qcache_hits | 命中次數 | 過低說明 QC 無效 |
| Qcache_inserts | 新增緩存次數 | — |
| Qcache_lowmem_prunes | 因內存不足被剔除的條目數 | 快速增長 → 增加 query_cache_size |
| Qcache_free_memory | 剩餘可用內存 | 過小 → 擴容 |
| Qcache_free_blocks | 空閒塊數(碎片指標) | 過大 → 碎片嚴重,執行 FLUSH QUERY CACHE |
| Qcache_total_blocks | 總塊數 | 配合 Qcache_queries_in_cache 看平均塊數 |
| Qcache_queries_in_cache | 當前緩存查詢數 | — |
| Qcache_not_cached | 未緩存的只讀查詢數 | 含不可緩存類型、SQL_NO_CACHE、超大結果等 |
query_cache_sizequery_cache_min_res_unit(如 16K-32K)減少分配次數query_cache_min_res_unitFLUSH QUERY CACHE 整理碎片(不清空條目)SELECT pwd FROM user WHERE name='xxx',每用戶 SQL 文本不同)NOW(), RAND(), UUID(), CONNECTION_ID() 等-- 默認關閉 QC,關鍵只讀業務顯式啟用
SET SESSION query_cache_type = 2;
-- 熱點配置查詢、字典表查詢、報表聚合查詢
SELECT SQL_CACHE * FROM config WHERE type='payment';
SELECT SQL_CACHE id, name FROM dict_category WHERE parent_id=0;
-- 寫操作、高頻變更、個性化查詢顯式禁用
SELECT SQL_NO_CACHE * FROM user_log WHERE uid=123 ORDER BY time DESC LIMIT 20;
MySQL 8.0 完全移除了 Query Cache。官方理由:
替代方案:應用層引入 Redis/Memcached,按業務語義緩存對象/列表/聚合結果,配合 TTL、主動失效、標籤組失效等策略,遠優於 SQL 文本級的被動緩存。
Query Cache 曾是 MySQL 5.x 時代簡單場景下的「免費加速器」,但其**粗粒度失效、字面匹配、全局鎖**三大硬傷決定了它無法適應高併發寫入場景。現代架構應將緩存策略前置至應用層,MySQL 專注於存儲與索引優化。若維護 5.7 及以下舊系統,請嚴格遵循「默認關、按需開、監控調、定期清」原則。