首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 查詢緩存機制深度解析:命中條件、工作流程、失效機制、記憶體管理與 InnoDB 交互

     編輯:MySQL 資料庫相關知識

MySQL 查詢緩存(Query Cache)在 5.7 仍可用、8.0 已移除。本文深度剖析其命中條件(Hash 表 Key 構成)、工作流程、失效觸發條件、記憶體塊管理與碎片問題、InnoDB 事務隔離下的緩存可見性規則、配置參數與監控指標解讀,並附實測驗證案例。

一、命中條件:嚴格的精確匹配

  • 緩存 Key = SQL 文本(含大小寫、空格、註釋)+ 查詢資料庫 + 客戶端協議版本 + 默認字符集。
  • MySQL 不解析 SQL 直接 Hash 查找,任何字符差異(多一空格、換行、註釋)均導致未命中。
  • 包含不確定函數(NOW(), RAND(), UUID(), CURRENT_DATE())的查詢不緩存、不命中。

二、工作流程

  1. 接收 SQL,構造 Key 查找緩存 Hash 表(額外 CPU)。
  2. 命中 → 直接返回結果集(跳過解析/優化/執行,極快)。
  3. 未命中 → 正常解析/優化/執行(額外 CPU)。
  4. 執行完成 → 將結果集寫入緩存(額外記憶體/CPU)。

三、失效機制:寫入即失效

  • 表級粒度:INSERT/UPDATE/DELETE/TRUNCATE/ALTER/DROP TABLE/DATABASE 觸發該表所有緩存條目失效。
  • InnoDB 事務:修改表的事務提交前,該表緩存不可用(不可命中、不可寫入);提交後失效舊條目。
  • 鎖表:LOCK TABLES 視 query_cache_wlock_invalidate 設定。
  • 結果集超過 query_cache_limit 不緩存。

四、記憶體管理與碎片

  • 總空間 query_cache_size(預設 0,關閉),約 40KB 用於元數據。
  • 劃分為固定塊 query_cache_min_res_unit(預設 4KB)。
  • 查詢開始預分配塊,結束釋放多餘 → 碎片。
  • 碎片過多導致分配鎖競爭、Qcache_lowmem_prunes 增長。
  • 整理:FLUSH QUERY CACHE(阻塞其他連接使用緩存)。
  • 清空:RESET QUERY CACHE。

五、InnoDB 與查詢緩存的特殊交互

  • 每表維護事務計數器(最大事務 ID)。
  • 只有事務 ID > 表計數器的事務可使用緩存;較小 ID 事務不可用(MVCC 可見性)。
  • 所有加鎖讀(SELECT ... LOCK IN SHARE MODE, FOR UPDATE)不使用緩存。

六、配置參數與監控指標

SHOW VARIABLES LIKE '%query_cache%';
參數含義建議
query_cache_typeOFF/ON/DEMAND讀多寫少開 ON,寫多關 OFF
query_cache_size總記憶體 (bytes, 1024 倍數)64M~256M,視命中率調整
query_cache_limit單查詢最大緩存1M~4M
query_cache_min_res_unit最小塊大小大結果集調大 (16K~64K)
query_cache_wlock_invalidate鎖表時是否仍返緩存OFF
SHOW STATUS LIKE 'Qcache%';
指標健康判斷
Qcache_hits / Qcache_inserts > 3:1緩存有效
> 10:1緩存優秀
Qcache_lowmem_prunes 持續增長記憶體不足/碎片嚴重
Qcache_free_blocks 過大碎片多,需 FLUSH QUERY CACHE

七、實測驗證案例

SET GLOBAL query_cache_size = 600000;
SET SESSION query_cache_type = ON;
USE test;
SELECT COUNT(*) FROM animals;  -- 首次執行
SHOW STATUS LIKE 'Qcache_hits';  -- 0
SELECT COUNT(*) FROM animals;  -- 二次執行
SHOW STATUS LIKE 'Qcache_hits';  -- 1 (命中)
INSERT INTO animals VALUES (9, 'test');  -- 寫入導致失效
SELECT COUNT(*) FROM animals;  -- 再次執行
SHOW STATUS LIKE 'Qcache_hits';  -- 仍為 1 (未命中,重新執行)
SELECT COUNT(*) FROM animals;  -- 三次執行
SHOW STATUS LIKE 'Qcache_hits';  -- 2 (命中新緩存)

八、MySQL 8.0 移除後的替代方案

  1. Redis / Memcached: 應用層緩存,支援複雜數據結構、TTL、集群。
  2. PreparedStatement: 復用執行計畫,減少解析/優化開銷。
  3. ProxySQL: 中間件層查詢緩存,透明於應用。
  4. 物化視圖/摘要表: 定時預聚合,查詢直接讀結果。

九、總結

查詢緩存以「精確 SQL 匹配 + 表級失效」為核心,適合「靜態數據、高頻重複查詢、結果集小」場景。InnoDB MVCC 與加鎖讀繞過緩存,保證一致性。MySQL 8.0 移除後,建議遷移至應用層/中間件緩存架構,配合 PreparedStatement 與讀寫分離,獲得更可控、可擴展的效能提升。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved