MySQL 查询缓存保存查询返回的完整结果。当查询命中该缓存,会立刻返回结果,跳过了解析,优化和执行阶段。
查询缓存会跟踪查询中涉及的每个表,如果这写表发生变化,那么和这个表相关的所有缓存都将失效。
但是随着服务器功能的强大,查询缓存也可能成为整个服务器的资源竞争单点。
查看当前版本是否支持 QC 功能:
SHOW VARIABLES LIKE 'have_query_cache';
若显示 YES,则支持;反之不支持
# Variable_name, Value 'have_query_cache', 'YES'
查看是否已开启:
SHOW VARIABLES LIKE '%query_cache%';
若 query_cache_size 不为 0,query_cache_type = ON 则已开启
MariaDB [(none)]> 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 | | query_cache_strip_comments | OFF | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+-----------+
若未开启,则在 my.cnf(linux)或 my.ini(windows)的 [mysqld] 下添加:
query_cache_size=128M query_cache_type=1
重启服务使设置生效。
命令:
MariaDB [(none)]> show status like '%qcache%'; +-------------------------+-----------+ | Variable_name | Value | +-------------------------+-----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 134137272 | | Qcache_hits | 5 | | Qcache_inserts | 3 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 6 | | Qcache_queries_in_cache | 3 | | Qcache_total_blocks | 8 | +-------------------------+-----------+ 8 rows in set (0.00 sec)
字段含义:
解析:
Qcache_free_blocks:表示查询缓存中目前还有多少剩余的blocks,如果该值显示较大,则说明查询缓存中的内存碎片过多了,可能在一定的时间进行整理。
减少碎片:
合适的query_cache_min_res_unit可以减少碎片,这个参数最合适的大小和应用程序查询结果的平均大小直接相关,可以通过内存实际消耗(query_cache_size - Qcache_free_memory)除以Qcache_queries_in_cache计算平均缓存大小。
可以通过Qcache_free_blocks来观察碎片,这个值反应了剩余的空闲块,如果这个值很多,但是
Qcache_lowmem_prunes却不断增加,则说明碎片太多了。可以使用flush query cache整理碎片,重新排序,但不会清空,清空命令是reset query cache。整理碎片期间,查询缓存无法被访问,可能导致服务器僵死一段时间,所以查询缓存不宜太大。
Qcache_free_memory:查询缓存的内存大小,通过这个参数可以很清晰的知道当前系统的查询内存是否够用,是多了,还是不够用,DBA可以根据实际情况做出调整。
Qcache_hits:表示有多少次命中缓存。我们主要可以通过该值来验证我们的查询缓存的效果。数字越大,缓存效果越理想。
Qcache_inserts: 表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的情况的次 数,次数越多,表示查询缓存应用到的比较少,效果也就不理想。当然系统刚启动后,查询缓存是空的, 这很正常。
Qcache_lowmem_prunes:该参数记录有多少条查询因为内存不足而被移除出查询缓存。通过这个值,用户可以适当的调整缓存大小。
Qcache_not_cached: 表示因为query_cache_type的设置而没有被缓存的查询数量。
Qcache_queries_in_cache:当前缓存中缓存的查询数量。
Qcache_total_blocks:当前缓存的block数量。四、使用说明
打开 Qcache 对读和写都会带来额外的消耗:
a、读查询开始之前必须检查是否命中缓存。
b、如果读查询可以缓存,那么执行完之后会写入缓存。
c、当向某个表写入数据的时候,必须将这个表所有的缓存设置为失效,如果缓存空间很大,则消耗也会很大,可能使系统僵死一段时间,因为这个操作是靠全局锁操作来保护的。
对 InnoDB 表,当修改一个表时,设置了缓存失效,但是多版本特性会暂时将这修改对其他事务屏蔽,在这个事务提交之前,所有查询都无法使用缓存,直到这个事务被提交,所以长时间的事务,会大大降低查询缓存的命中
一个表可以被许多类型的语句更改,例如 INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE 或 DROP DATABASE。
对于 InnoDB 而言,事物的一些特性还会限制查询缓存的使用。当在事物 A 中修改了 B 表时,因为在事物提交之前,对 B 表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB 采取的措施让所有涉及到该 B 表的查询在事物 A 提交之前是不可缓存的。如果 A 事物长时间运行,会严重影响查询缓存的命中率
查询缓存的空间不要设置的太大。
因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况