前言
MySQL的查询缓存(Query Cache)是一个在内存中存储SELECT语句及其结果集的机制,目的是避免对相同的查询进行重复的解析、编译和执行,从而提高数据库性能。
Mysql 结构图如下:
查询缓存的工作流程大致如下:
- 当一个SELECT查询发送到MySQL时,MySQL首先检查查询缓存中是否已经存在该查询的结果。
- 如果查询缓存中存在,并且查询条件和参数完全匹配,MySQL将直接从缓存中返回结果,无需进行进一步的处理。
- 如果查询缓存中不存在,MySQL将执行查询,并将结果存入查询缓存中,以便后续相同查询可以直接使用。
- 当查询缓存达到其最大容量时,MySQL会根据一定的策略淘汰旧的缓存条目。
缓存规则
- 查询缓存会将查询语句和结果集保存到内存(一般是 key-value 的形式,key 是查询语句,value 是查询的结果集),下次再查直接从内存中取。
- 缓存的结果是通过 sessions 共享的,所以一个 client 查询的缓存结果,另一个 client 也可以使用。
- SQL 必须完全一致才会导致查询缓存命中(大小写、空格、使用的数据库、协议版本、字符集等必须一致)。
- 检查查询缓存时,MySQL Server 不会对 SQL 做任何处理,它精确的使用客户端传来的查询。
- 不缓存查询中的子查询结果集,仅缓存查询最终结果集。不确定的函数将永远不会被缓存, 比如 now()、curdate()、last_insert_id()、rand() 等。
- 不缓存产生告警(Warnings)的查询。太大的结果集不会被缓存 (< query_cache_limit)。
- 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果也不会被缓存。
- 缓存建立之后,MySQL 的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。
- MySQL 缓存在分库分表环境下是不起作用的。不缓存使用 SQL_NO_CACHE 的查询。
缺点
如果查询缓存使用了很大量的内存,缓存失效操作就可能成为一个非常严重的问题瓶颈。如果缓存中存放了大量的查询结果,那么缓存失效操作时整个系统都可能会僵死一会儿。因为这个操作是靠一个全局锁操作保护的,所有需要该操作的查询都要等待这个锁,而且无论是检测是否命中缓存、还是缓存失效检测都需要等待这个全局锁。
注意
需要注意的是,从MySQL 5.7.20开始,查询缓存已被标记为废弃,并且在MySQL 8.0中已经被完全移除。这是因为随着硬件的发展和优化的存储引擎,查询缓存带来的性能提升已经不如以前明显,而且它还增加了系统的复杂性。因此,对于新的MySQL版本,建议使用其他优化手段,如索引优化、查询优化等,来提高数据库性能。
Reference
- https://javaguide.cn/database/mysql/mysql-query-cache.html#mysql-%E6%9F%A5%E8%AF%A2%E7%BC%93%E5%AD%98%E7%AE%A1%E7%90%86%E5%92%8C%E9%85%8D%E7%BD%AE