MySQL 的缓存体系并不是由单个开关控制的,它至少包含查询缓存、InnoDB 缓冲池、表定义缓存和线程缓存等几个层级。日常运维中提到清除 MySQL 缓存,通常是对查询缓存和表缓存执行刷新操作。要判断查询缓存的健康程度,可以先从参数和状态计数入手,再根据命中率决定是否清理。

一、查看查询缓存的状态与命中率
在 MySQL 5.7 及更早版本中,查询缓存默认可能开启,相关参数以 query_cache 开头。执行 SHOW VARIABLES LIKE 'query_cache%'; 可以查看缓存类型、大小和单结果上限。其中 query_cache_type 为 ON 时缓存所有符合条件的 SELECT,为 DEMAND 时只缓存带 SQL_CACHE 提示的查询。
判断查询缓存是否真正有效,不能只看参数是否开启,还需要查看 Qcache 开头的状态计数。Qcache_hits 表示命中次数,Qcache_inserts 表示插入缓存的次数,Qcache_lowmem_prunes 表示因内存不足被移除的查询数量。命中率可以用 Qcache_hits 除以 Com_select 计算,删除次数过高则说明 query_cache_size 设置偏小。
-- 查看查询缓存参数 SHOW VARIABLES LIKE 'query_cache%'; -- 查看查询缓存命中与碎片情况 SHOW STATUS LIKE 'Qcache%'; -- 查看 SELECT 语句执行总数 SHOW STATUS LIKE 'Com_select';
如果查询缓存命中率长期低于 20%,且 Qcache_lowmem_prunes 持续增长,说明缓存空间不足或业务写入过于频繁,继续保留查询缓存可能得不偿失。此时可以选择关闭查询缓存,或通过 RESET QUERY CACHE 释放空间。
二、使用 RESET QUERY CACHE 和 FLUSH QUERY CACHE 清除查询缓存
RESET QUERY CACHE 的作用是删除查询缓存中的所有缓存结果,并重置相关状态计数。它不会改变 query_cache_type 或 query_cache_size 参数,也不会关闭表。执行该命令通常用于测试环境或需要立即让旧查询结果失效的场景。
FLUSH QUERY CACHE 与 RESET 不同,它不会删除缓存内容,只是对查询缓存进行碎片整理。如果缓存中频繁插入和删除小块结果,内存中会出现碎片,FLUSH QUERY CACHE 可以让缓存空间更紧凑。需要注意,该命令不会强制 MySQL 重新计算结果,已有缓存依然有效。
-- 删除查询缓存中的所有结果 RESET QUERY CACHE; -- 整理查询缓存碎片,不删除缓存内容 FLUSH QUERY CACHE; -- 查看清理后的查询缓存状态 SHOW STATUS LIKE 'Qcache_free_memory';
在 MySQL 8.0 中,查询缓存模块被正式移除,执行 RESET QUERY CACHE 会返回语法错误。如果使用 8.0 及以上版本,应把优化重心放到 InnoDB 缓冲池和索引设计上,而不是依赖查询缓存。
三、清除表缓存和 InnoDB 缓冲池的相关命令
除了查询缓存,MySQL 还会把打开的表结构、表数据和索引页缓存在内存中。FLUSH TABLES 命令会关闭所有打开的表,释放表缓存,同时会等待正在执行的语句完成。该命令在需要清空表定义缓存或进行一致性备份前经常使用。
InnoDB 缓冲池是 MySQL 中最主要的缓存区域,保存数据页和索引页。通过 SHOW STATUS LIKE 'Innodb_buffer_pool%'; 可以查看读取请求和缓冲池命中情况。Innodb_buffer_pool_read_requests 表示逻辑读取次数,Innodb_buffer_pool_reads 表示从磁盘物理读取的次数,两者差值越大说明缓冲池命中率越高。
-- 关闭所有打开的表,释放表缓存 FLUSH TABLES; -- 关闭指定表并释放相关缓存 FLUSH TABLES orders, users; -- 查看 InnoDB 缓冲池读写与命中情况 SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
InnoDB 缓冲池没有提供直接清空全部数据页的命令,因为脏页需要先写回磁盘。如果确实需要冷启动测试,可以重启 MySQL 服务让缓冲池重新加载,或者使用 SET GLOBAL innodb_buffer_pool_dump_now=ON 保存当前缓冲池状态,SET GLOBAL innodb_buffer_pool_load_now=ON 恢复。但这些命令属于状态管理,不属于清除缓存。
四、结合业务特点选择缓存清理策略
清除 MySQL 缓存不是性能优化的常规手段,更像是一种故障排查或测试手段。频繁执行 RESET QUERY CACHE 或 FLUSH TABLES 会带来短暂的锁等待和缓存重建成本。生产环境中建议先收集 Qcache 和 Innodb_buffer_pool 的状态数据,确认命中率过低或碎片过多后再操作。
对于读多写少的业务,查询缓存命中率较高,可以适当增大 query_cache_size 并保留缓存。对于写入频繁、表数据变化快的业务,查询缓存会频繁失效,反而增加维护开销,关闭查询缓存通常更合适。InnoDB 缓冲池则应尽量大于热数据总量,让数据页尽量留在内存中。
如果发现某些慢查询总是没有命中查询缓存,可以检查 SQL 是否包含 NOW()、RAND() 等非确定性函数,或者表是否频繁更新。这些情况都会导致查询缓存无法复用。