原理
MySQL 服务收到到查询请求时,会先在内存中找是否有完全一致的查询语句数据,有直接返回,无才经过一系列步骤查询数据,注意是语句完全一致才能被查询缓存命中。

如下:

  1. 请求字符不同(例如, 空格、注释、大小写、别名等)
    SELECT * FROM tbl;
    SELECT * from tbl;
    这两条语句因 FROM 和 from 不同而被视为不同的查询。
  2. 系统函数,可能会不同(例如NOW())

缓存失效
对缓存涉及的表使用了INSERT、UPDATE、DELETE、TRUNCATETABLE、ALTER TABLE、DROP TABLE或DROP TABLE或者DROP DATABASE

开启

# 查询查询缓存的信息
SHOW VARIABLES LIKE 'have_query_cache';  
# have_query_cache  是否支持查询缓存,MySQL8之后不支持查询缓存了
SHOW VARIABLES LIKE 'query_cache_type';
query_cache_type    是否已开启查询缓存,MySQL5.6之后默认关闭
# (可见MySQL似乎不太建议我们使用查询缓存,关于查询缓存的优劣见仁见智)
# 打开 >>> vi /etc/my.cnf
# 在[mysqld]下添加:
query_cache_size = 20M
query_cache_type = ON
# 重启 mysqld
# 查询查询缓存的信息
SHOW VARIABLES LIKE 'have_query_cache';  
# have_query_cache  是否支持查询缓存,MySQL8之后不支持查询缓存了
SHOW VARIABLES LIKE 'query_cache_type';
query_cache_type    是否已开启查询缓存,MySQL5.6之后默认关闭
# (可见MySQL似乎不太建议我们使用查询缓存,关于查询缓存的优劣见仁见智)
# 打开 >>> vi /etc/my.cnf
# 在[mysqld]下添加:
query_cache_size = 20M
query_cache_type = ON
# 重启 mysqld

测试

SELECT * FROM users WHERE id = 1;

第一次执行:

mysql8空查询缓存 mysql8 查询缓存_查询缓存


可见 Qcache_hits(缓存命中数): 0,Qcache_inserts(插入缓存数):1,再次执行完全相同的语句:

mysql8空查询缓存 mysql8 查询缓存_mysql8空查询缓存_02


可见 Qcache_hits(缓存命中数): 1,Qcache_inserts(插入缓存数):0,查询缓存被命中

扩展
0. 查询缓存的总体使用情况

SHOW STATUS LIKE 'qcache%';
  1. 执行不查询缓存的语句
SELECT SQL_NO_CACHE * FROM users WHERE id = 1;
  1. 清除缓存
RESET QUERY CACHE
  1. 查询缓存失效

在表的结构或数据发生改变时,查询缓存中的数据不再有效。所以查询缓存适合有大量相同查询的应用,不适合有大量数据更新的应用。

  1. 临时的禁用缓存
    set global query_cache_size=0
    set global query_cache_type=0
  2. 永久的修改配置文件my.cnf ,添加下面的配置即可。
    query_cache_type=0
    query_cache_size=0
  3. 为什么MySQL5.6之后默认关闭查询缓存,MySQL8之后甚至移除此功能?

MySQL 服务器团队:缓存建议使用MySQL外部一些数据库如Redis/Memcache等,效率会更高。参考:https://mysqlserverteam.com/mysql-8-0-retiring-support-for-the-query-cache/