mysql 如何清理缓存
MySQL 缓存(Cache)是一种临时存储机制,用于存储常用或最近访问的数据,以减少从磁盘读取数据的次数,从而加快数据访问速度。常见的缓存包括查询缓存、表缓存、InnoDB缓冲池。当遇到 MySQL 内存使用率过高的场景,在不重启服务的情况下,可尝试如下方案,以最小代价降低mysql的内存占用。
清理 Query Cache 查询缓存
- MySQL 开启查询缓存,会将查询结果写入缓存,以降低查询执行的时间(但不能减少查询结果传输的网络消耗)
- 当表的数据发生变化(如 INSERT、UPDATE或UPDATE操作)时,相关的查询缓存会失效并被清除
[root@localhost ~]# cat /etc/my.cnf | egrep "(query_cache_type|query_cache_size|query_cache_limit)"
query_cache_type = 1
query_cache_size = 585K
query_cache_limit = 1M
[root@localhost ~]# mysql -uroot -p******
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| have_query_cache | YES | --.是否支持Query Cache
| query_cache_limit | 1048576 | --.MySQL能够缓存的最大查询结果(字节),查询结果大于该值时不会被缓存,默认1048576(1MB)
| query_cache_min_res_unit | 4096 | --.查询缓存分配的最小块的大小(字节),默认4096(4KB)
| query_cache_size | 599040 | --.为缓存查询结果分配的内存的大小(字节),默认0(禁用查询缓存)
| query_cache_type | ON | --.设置查询缓存类型,默认ON(启用查询缓存)
| query_cache_wlock_invalidate | OFF | --.如果某个表被锁住,是否返回缓存中的数据,默认关闭,也是建议的
+------------------------------+---------+
mysql> show status like 'Qcache%';
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_free_blocks | 1 | --.查询缓存中的闲置块,若该值比较大,则说明Query Cache中的内存碎片可能比较多
| Qcache_free_memory | 382742 | --.剩余缓存的大小
| Qcache_hits | 199 | --.缓存命中次数
| Qcache_inserts | 132 | --.缓存被插入的次数,也就是查询没有命中的次数
| Qcache_lowmem_prunes | 0 | --.由于内存低而被删除的缓存条数,如果这个数值不断增长,一般是QueryCache的空闲内存不足或内存碎片比较严重
| Qcache_not_cached | 164 | --.没有被缓存的条数
| Qcache_queries_in_cache | 125 | --.缓冲中有多少条查询语句
| Qcache_total_blocks | 243 | --.总块数
+-------------------------+--------+
- 针对 Query Cache 的几个计算指标,分析如下:
| 指标 |
计算公式 |
过大 |
过小 |
| 碎片率 |
Qcache_free_blocks / Qcache_total_blocks * 100% |
建议执行 reset query cache; 整理内存碎片 |
建议减小 query_cache_min_res_unit |
| 利用率 |
(query_cache_size - Qcache_free_memory) / query_cache_size * 100% |
说明 query_cache_size 过小或内存碎片过多 |
建议减小 query_cache_size |
| 命中率 |
Qcache_hits / (Qcache_hits + Qcache_inserts) * 100% |
说明缓存效率比较高 |
建议禁用查询缓存 |
MySQL 5.7 可清理 Query Cache
- 针对 QUERY CACHE 执行 RESET 与 FLUSH 操作,会对查询缓存造成不同的影响,具体区别如下:
| 命令 |
作用 |
影响 |
| RESET QUERY CACHE; |
重新组织查询缓存的内存碎片,释放查询缓存未使用的内存,但不清除缓存中的数据 |
性能开销较小,常用于优化缓存内存使用 |
| FLUSH QUERY CACHE; |
清空所有缓存的查询结果 |
会立即释放内存,短时间内性能下降 |
MySQL 8.0 已移除 Query Cache
| 参数名 |
MySQL 5.7 |
MySQL 8.0 |
| query_cache_size |
✅ 可配置缓存大小 |
❌ 已删除 |
| query_cache_type |
✅ 可设置 ON/OFF/DEMAND |
❌ 已删除 |
| query_cache_limit |
✅ 可配置单条结果上限 |
❌ 已删除 |
| Qcache_hits 等状态变量 |
✅ 存在 |
❌ 已删除 |
- 为什么 MySQL 要移除 Query Cache?
1、严重的全局锁争用
Query Cache 是一个全局共享内存区,任何写操作(INSERT/UPDATE/DELETE/DDL)都会锁住整个缓存区,在高并发下反而导致性能下降。
2、失效粒度粗
任意表的修改都会使所有涉及该表的缓存失效,对更新频繁的表几乎命中率为零。
3、内存碎片严重,维护复杂
大小不一的结果集插入会产生内存碎片,清理和整理耗时高。
👉 因此,MySQL 官方团队认为 "成本 > 收益",在 8.0 中彻底移除。
- MySQL 查询执行架构概览,注意 Buffer Pool 缓存的是数据页与索引页,并不是 Query Cache(查询结果缓存)

- 针对 MySQL 8.0,可借助 Redis 或 Memcached 等缓存服务,实现"查询缓存"效果

清理 Table Cache 表缓存
| 命令 |
作用 |
影响 |
| FLUSH TABLES; |
关闭所有当前已打开的表,并将其数据刷新到磁盘 |
它会清除表缓存(Table Cache) |
| FLUSH STATUS; |
重置服务器状态变量 |
- |
| FLUSH HOSTS; |
清空主机缓存,用于连接错误较多时 |
- |
| FLUSH LOGS; |
关闭并重新打开所有的日志文件,包括binlog日志、错误日志、通用查询日志、慢查询日志 |
常用于日志轮换 |
清理 InnnoDB 缓冲池
- 推荐通过调整 Buffer Pool 来清理 InnnoDB 缓冲池,在 MySQL 5.7.5以上版本即刻生效,效果立竿见影
#.确认当前Buffer Pool大小
SELECT @@innodb_buffer_pool_size,@@innodb_buffer_pool_chunk_size,@@innodb_buffer_pool_instances;
#.示例改为4GB
SET GLOBAL innodb_buffer_pool_size=1024*1024*1024*4;
注:所有变量的修改,记得同步到 /etc/my.cnf