MySQL Query Cache 曾是提升讀密集型應用效能的「銀彈」,但在 MySQL 5.7 中被標記為 deprecated,並在 MySQL 8.0 中完全移除。理解其原理與局限,對於維護舊版本系統、設計緩存策略、避免踩坑仍有重要價值。本文深度剖析 Query Cache 的鍵值生成機制、失效觸發條件、配置參數與最佳實踐。
Key 生成:SELECT 語句文本 → 標準化處理 → Hash 計算 → 唯一 Key Value 存儲:查詢結果集 (Result Set) → 內存塊分配 → 緩存存儲 -- 關鍵特性: -- 1. 區分大小寫:"SELECT * FROM t" ≠ "select * from t" -- 2. 區分空格/換行:"SELECT * FROM t" ≠ "SELECT * FROM t" -- 3. 必須字節級完全一致才能命中
核心規則:只要查詢涉及的表發生任何數據變更(INSERT/UPDATE/DELETE/TRUNCATE),該表相關的所有 Query Cache 條目全部失效並被刪除。
-- 示例場景 Session 1: SELECT * FROM users WHERE id = 1; -- 緩存結果 Session 2: UPDATE users SET name = 'New' WHERE id = 2; -- 更新同表不同行 Session 3: SELECT * FROM users WHERE id = 1; -- 必須重新執行,緩存已失效
| 場景特徵 | Query Cache 效果 | 建議 |
|---|---|---|
| 數據極少變更,讀請求極高(配置表、字典表、靜態內容) | 極佳,命中率 90%+ | ✅ 開啟 |
| 讀寫比例約 1:1,中等並發 | 一般,鎖競爭抵消收益 | ⚠️ 謹慎評估 |
| 高頻寫入、高並發 OLTP | 災難性,全局鎖成為瓶頸 | ❌ 禁用 |
| 大結果集、BLOB/TEXT 欄位 | 內存碎片嚴重,碎片整理開銷大 | ❌ 禁用 |
| 值 | 含義 | SQL 語法控制 |
|---|---|---|
| 0 / OFF | 完全禁用 | 無效 |
| 1 / ON | 全局啟用(預設行為) | SELECT SQL_NO_CACHE * FROM t 可跳過緩存 |
| 2 / DEMAND | 按需啟用(推薦) | SELECT SQL_CACHE * FROM t 顯式使用緩存 |
-- 預設為 0(禁用),必須顯式設置 > 0 才生效 SET GLOBAL query_cache_size = 100M; -- 運行時動態調整 -- 內存結構: -- 1. 查詢緩存塊:存儲結果集數據 -- 2. 索引塊:存儲 Key -> Value 映射 -- 3. 空閒塊:內存碎片區域
query_cache_limit:單個查詢結果最大緩存大小(預設 1MB),超過不緩存query_cache_min_res_unit:內存分配最小單元(預設 4KB),影響碎片程度query_cache_wlock_invalidate:寫鎖時是否失效緩存(預設 ON)# my.cnf 推薦配置(僅適用讀多寫少場景) [mysqld] query_cache_type = 2 # DEMAND 模式,按需使用 query_cache_size = 256M # 視內存大小調整,建議不超過 512M query_cache_limit = 2M # 單查詢結果限制 query_cache_min_res_unit = 2K # 減少碎片(小結果集多時) # 監控命令 SHOW VARIABLES LIKE '%query_cache%'; SHOW STATUS LIKE '%Qcache%';
SHOW STATUS LIKE 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | -- 空閒塊數(碎片指標) | Qcache_free_memory | 100M | -- 剩餘內存 | Qcache_hits | 100000 | -- 命中次數 | Qcache_inserts | 5000 | -- 插入次數 | Qcache_lowmem_prunes | 200 | -- 內存不足淘汰次數 | Qcache_not_cached | 1000 | -- 未緩存查詢數 | Qcache_queries_in_cache | 4500 | -- 當前緩存查詢數 | Qcache_total_blocks | 9001 | -- 總塊數 +-------------------------+----------+
FLUSH QUERY CACHE原 Query Cache 場景 現代替代方案 優勢 靜態配置/字典表查詢 應用啟動加載到本地內存 / Redis Hash 零網路延遲、無鎖競爭 熱點數據查詢(用戶信息、商品詳情) Redis/Memcached + Cache-Aside 模式 分佈式、可水平擴展、TTL 控制 複雜報表聚合查詢 物化視圖 / 預計算表 / ClickHouse 查詢效能穩定、不影響主庫 會話級重複查詢 應用層請求級緩存 最輕量、無序列化開銷 總結
MySQL Query Cache 是一個「時代的眼淚」:在單核、低併發、讀多寫少的早期場景下極其有效,但在多核、高併發、微服務架構下成為效能殺手。對於仍在使用 MySQL 5.6/5.7 的系統,建議採用 DEMAND 模式(query_cache_type=2)精準控制緩存範圍,並密切監控命中率與碎片指標。對於新架構設計,應堅決選擇應用層分佈式緩存方案,從架構層面解決讀擴展問題。