MySQL 8.0 彻底移除查询缓存机制,包括 query_cache_type 等所有相关变量,启动时配置会报错;Redis 无法透明替代,需显式处理 key 生成、失效、序列化及一致性。

MySQL 8.0 确实彻底移除了 query_cache_type
是的,query_cache_type、query_cache_size 等所有查询缓存相关变量在 MySQL 8.0 中被完全删除,启动时若配置了这些参数会直接报错:Unknown system variable 'query_cache_type'。这不是禁用,而是代码级移除——连编译选项都去掉了。所以别再试图“调大缓存”或“设为 1 来开启”,它不存在了。
为什么不能简单用 Redis 替代 query_cache_type 的行为
原生查询缓存是服务端透明的:SQL 字符串哈希 → 直接返回结果集,对应用无感,也不需要改逻辑。Redis 是显式缓存,你得自己决定:
- 哪些 SQL 需要缓存(比如
SELECT * FROM users WHERE id = ?可缓,SELECT NOW()或带RAND()的绝对不能缓) - 缓存 key 怎么生成(建议包含 SQL 模板 + 参数哈希,而非原始 SQL 字符串,避免空格/换行干扰)
- 失效时机怎么控制(UPDATE/DELETE 后要主动删 Redis key,而原生查询缓存是自动失效的)
- 结果怎么序列化(MySQL 返回的是字段名+值的结构化数据,Redis 只存字符串或二进制,常用
JSON或MsgPack)
实际接入 Redis 缓存的最小可行路径
不要从“全量 SQL 自动缓存”开始,先锁定高读低写、结构稳定、延迟敏感的接口。例如用户资料页的 get_user_by_id:
- 在 DAO 层封装一个
cacheGetUserById($id)方法,先查redis.get("user:{$id}"),命中则json_decode返回;未命中则走 MySQL 查询,再redis.set("user:{$id}", json_encode($row), 300) - 在更新用户信息时,同步执行
redis.del("user:{$id}"),而不是等 TTL 过期 - 避免缓存空结果(如
user_id=999999不存在),可设短 TTL(如 60 秒)或用布隆过滤器预判 - 注意事务一致性:如果业务里有“查-改-查”流程,且中间修改没触发缓存清理,就会读到脏数据
容易被忽略的边界问题
很多人卡在看似简单的地方:
-
mysql_real_escape_string已废弃,但如果你还在拼接 SQL,参数未绑定就塞进缓存 key,可能引发哈希冲突(比如id='1 OR 1=1'和id='1'被当成同一 key) - Redis 的
SET默认不支持过期时间原子写入,要用SETEX或SET ... EX 300,否则先SET再EXPIRE可能失败导致永不过期 - MySQL 8.0 默认字符集是
utf8mb4,而 PHP 的json_encode默认不转义中文,Redis 存进去没问题,但某些客户端显示乱码——加JSON_UNESCAPED_UNICODE选项
缓存不是开关一开就提速,关键在粒度控制和失效精度。越想模拟原生 query cache 的“无感”,越容易掉进一致性陷阱。










