MySQL查询缓存已废弃,PHP应改用Redis缓存SELECT结果,key用语句哈希+参数拼接,值用json_encode序列化并设TTL,写操作后主动删除对应key;SQLite仅适用于CLI或低频本地缓存。

PHP 直接用 MySQL 查询缓存(query_cache)已失效
MySQL 8.0 已彻底移除 query_cache,5.7 默认关闭且不推荐启用;PHP 层调用 mysql_query()(早已废弃)或 mysqli::query() 时,即使服务端曾开启过查询缓存,现在也完全不起作用。别再查“如何开启 MySQL 查询缓存”——这条路已经堵死。
用 Redis 缓存 SELECT 结果最常用也最可控
把 SELECT 的结果序列化后存进 Redis,是当前 PHP 项目中最主流、最易落地的数据库查询缓存法。关键不是“能不能缓”,而是“缓什么”和“怎么过期”:
-
key建议用查询语句哈希 + 关键参数拼接,比如'user_profile_' . md5("uid=123"),避免硬编码或含敏感字段 - 缓存值建议用
json_encode()或serialize(),但注意后者在 PHP 版本升级时可能反序列化失败,生产环境优先选json - 必须设
TTL(如 300 秒),不能依赖“永不过期”,否则数据脏读风险高;对强一致性要求高的场景(如用户余额),干脆跳过缓存 - 写操作(
INSERT/UPDATE/DELETE)后,要主动del对应 key,而不是等它自然过期
用 PDO + SQLite 做本地轻量缓存适合 CLI 或低频查询
如果只是临时缓存一些配置、地区列表、字典项这类极少变动的数据,又不想引入 Redis,可以用 SQLite 文件做本地缓存层:
- 建一张
cache表:CREATE TABLE cache (key TEXT PRIMARY KEY, value TEXT NOT NULL, expires INTEGER NOT NULL) - 查询前先查
SELECT value FROM cache WHERE key = ? AND expires > ?,命中则直接返回json_decode($row['value']) - 写入时用
REPLACE INTO cache VALUES (?, ?, ?),避免手动判断存在与否 - 注意 SQLite 文件权限和并发写入问题;CLI 脚本可用,Web 请求频繁时容易锁表,不推荐用于高并发接口
别缓存整个 PDOStatement 对象或未 fetch 的结果集
有人试图把 $stmt 对象或未执行 fetch() 的游标直接 serialize() 存起来,这是无效的:
立即学习“PHP免费学习笔记(深入)”;
-
PDOStatement是资源型对象,序列化后无法还原执行状态 - MySQL 的结果集在 PHP 中是按需获取的,没
fetch就缓存,实际只存了个空壳 - 真正该缓存的是最终结构化数据,比如
$stmt->fetchAll(PDO::FETCH_ASSOC)返回的数组
setex 和 get 配合得当,能扛住大多数读多写少场景;但缓存逻辑一旦嵌进业务代码深处,就容易漏掉更新路径。最常被忽略的,是“写完数据库后忘记删缓存”——这比不缓存更危险。











