MySQL Query Cache 自 4.0 版本引入,旨在將完全相同的 SELECT 結果集緩存於記憶體,下次相同查詢直接返回,繞過解析、優化、執行全流程。然而,預設關閉、配置陷阱多、高併發寫入場景反成累贅,導致許多 DBA 望而卻步。本文將系統梳理啟用流程、關鍵參數、驗證方法與適用邊界,助您精準決策「用還是不用」。
have_query_cache=YES ≠ 已啟用執行 SHOW VARIABLES LIKE '%query_cache%' 時,have_query_cache 僅表示**當前版本支援**該功能,**真正開關**取決於:
query_cache_size > 0(預設為 0,即禁用)query_cache_type = 1 (ON) 或 2 (DEMAND)[mysqld]
query_cache_size = 128M # 建議 1024 倍數,視查詢結果集大小調整
query_cache_type = 1 # 1=緩存所有 SELECT;2=僅緩存 SQL_CACHE 指定查詢
query_cache_limit = 2M # 單個查詢結果超過此值不緩存
query_cache_min_res_unit = 2K # 緩存塊最小單位,減少碎片(小結果集場景可調小)
重啟生效:修改配置後需 systemctl restart mysqld。
query_cache_type 三種模式詳解| 值 | 別名 | 行為 | 適用場景 |
|---|---|---|---|
| 0 | OFF | 禁用緩存,不分配記憶體 | 高寫入、低重複查詢系統 |
| 1 | ON | 緩存所有 SELECT,除非 SQL_NO_CACHE | 讀多寫少、高重複查詢業務 |
| 2 | DEMAND | 僅緩存 SQL_CACHE 指定的 SELECT | 精細控制,混合負載系統 |
注意:query_cache_type 僅接受數字 0/1/2,不可寫 ON/OFF。
mysql> SHOW VARIABLES LIKE '%query_cache%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| have_query_cache | YES |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit| 4096 |
| query_cache_size | 134217728 | # 128M = 128*1024*1024
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+-------------------------+-----------+
-- 1. 基線快照
mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 134208800 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 2 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+-----------+
-- 2. 首次執行查詢(未命中 -> 插入緩存)
mysql> SELECT * FROM user WHERE id = 2;
mysql> SHOW STATUS LIKE 'Qcache%';
-- 觀察:Qcache_inserts=1, Qcache_hits=0, Qcache_queries_in_cache=1
-- 3. 再次執行相同查詢(命中)
mysql> SELECT * FROM user WHERE id = 2;
mysql> SHOW STATUS LIKE 'Qcache%';
-- 觀察:Qcache_hits=1, Qcache_inserts=1 (不變),驗證緩存生效!
| 變量 | 含義 | 健康判讀 |
|---|---|---|
Qcache_free_memory | 剩餘可用記憶體 | 過大說明分配過剩;接近 0 需擴容或清理碎片 |
Qcache_hits | 命中次數 | 核心效能指標,越高越好 |
Qcache_inserts | 未命中插入次數 | 過高說明重複查詢少或緩存失效頻繁 |
Qcache_lowmem_prunes | 因記憶體不足被剔除的查詢數 | > 0 持續增長,需增大 query_cache_size |
Qcache_free_blocks | 空閒塊數量 | 過大(> 總塊 20%)表明碎片嚴重,執行 FLUSH QUERY CACHE 整理 |
Qcache_not_cached | 因 query_cache_type 策略未緩存的查詢數 | 輔助判斷策略是否合理 |
Qcache_queries_in_cache | 當前緩存查詢條數 | 配合 Qcache_total_blocks 估算平均塊大小 |
Qcache_hits / (Qcache_hits + Qcache_inserts) × 100% —— **目標 > 80%**Qcache_free_blocks / Qcache_total_blocks × 100% —— **目標 < 20%**(query_cache_size - Qcache_free_memory) / query_cache_size × 100% —— **25%~80% 為健康區間**Qcache_not_cached 高企,緩存利用率極低,純增開銷。query_cache_limit 不緩存,佔用緩存管理結構卻無產出。一鍵禁用:SET GLOBAL query_cache_size = 0; SET GLOBAL query_cache_type = 0;(運行時生效,重啟需改配置)。
FLUSH QUERY CACHE(不清空內容)或 RESET QUERY CACHE(清空)。Qcache_lowmem_prunes 連續 5 分鐘 > 100/分 觸發擴容告警。Query Cache 是把「雙刃劍」:用對場景(靜態數據、高重複讀)、配對參數(Size/Type/Limit/Min_Unit)、建對監控(Hit/Prune/Fragment),才能真正化身加速器。對於現代高併發、頻寫業務,**大膽關閉、外部緩存**往往是更優選擇。願本文助您在「開與關」間,做出最理性的技術決策。