
SQL_NO_CACHE 不能强制跳过“过时的缓存结果”,它只对早已废弃的查询缓存(query cache)起作用,而该缓存已在 MySQL 8.0 中彻底移除,在 5.7 中默认关闭且基本不可用。
SQL_NO_CACHE 在当前 MySQL 版本中是否生效?
几乎不生效。MySQL 8.0 完全删除了 query cache 相关代码,SQL_NO_CACHE 被解析器静默丢弃;MySQL 5.7 虽保留语法,但默认 query_cache_type = 0,且官方编译时常禁用 have_query_cache = NO。你执行 SELECT SQL_NO_CACHE ... 后:
- 不会报错,也不会警告
-
SHOW STATUS LIKE 'Qcache_hits'始终为 0 或直接提示Unknown system variable 'query_cache_type' - 即使手动开启(极罕见),只要表发生一次
INSERT/UPDATE,所有关联缓存立即失效,SQL_NO_CACHE失去意义
你以为的“过时缓存”,其实根本不是 query cache
用户常抱怨“查不到最新数据”,实际原因几乎从不是 query cache——它早在事务提交后就清空了。真正影响可见性的层级是:
-
innodb_buffer_pool:缓存的是页(page),不是结果集;修改后脏页刷盘前,其他事务能否看到取决于隔离级别(如READ COMMITTED可见,REPEATABLE READ不可见) - 操作系统页缓存(
page cache):缓存文件系统读取的磁盘块,SELECT仍走正常 InnoDB 路径,不受SQL_NO_CACHE控制 - 客户端或中间件缓存(如 ORM、ProxySQL、Redis):这些完全在 MySQL 之外,
SQL_NO_CACHE对它们零影响
想验证/绕过真实的数据延迟,该查什么?
不要碰 SQL_NO_CACHE,直接定位真正瓶颈:
- 确认事务隔离级别:
SELECT @@transaction_isolation;;若为REPEATABLE READ,同一事务内多次SELECT必然返回快照,与缓存无关 - 检查主从延迟:
SHOW SLAVE STATUS\G中的Seconds_Behind_Master - 观察缓冲池热度:
SELECT * FROM information_schema.INNODB_BUFFER_POOL_STATS;,但注意这不等于“缓存结果” - 排除应用层缓存:在 MySQL 命令行直连执行相同语句,对比应用返回结果
如果真要“强制读磁盘”做性能测试
这是极少数合理场景(如压测 I/O 瓶颈),但必须清楚代价:
- 清 OS 缓存(仅限 Linux 测试机):
sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"—— 会清空所有文件缓存,影响全局 - 挤压 InnoDB 缓冲池:执行大范围扫描(如
SELECT COUNT(*) FROM t FORCE INDEX (PRIMARY) WHERE id > 0),把目标页挤出innodb_buffer_pool - 临时调小再恢复 buffer pool(需 SUPER 权限):
SET GLOBAL innodb_buffer_pool_size = 128*1024*1024; SET GLOBAL innodb_buffer_pool_size = 2048*1024*1024;—— 触发重载,开销巨大
这些操作都不该出现在生产环境,也和 SQL_NO_CACHE 没有任何关系。真正需要控制的是事务行为、复制延迟或应用缓存策略,而不是一个被 MySQL 官方亲手埋掉十多年的语法。











