SQL_NO_CACHE对缓冲池完全无效,仅在MySQL 5.7及更早且query_cache_type=1时作用于已废弃的查询缓存,MySQL 8.0+中该提示被静默忽略。

SQL_NO_CACHE 对缓冲池(Buffer Pool)完全没影响,它只作用于早已被移除的查询缓存(Query Cache)。 你加了 SQL_NO_CACHE,但 MySQL 8.0+ 根本不认这个提示——它连 Query Cache 模块都没了。缓冲池的锁竞争、页面加载、LRU 管理,和这个关键字毫无关系。
SQL_NO_CACHE 在哪起作用?只在 MySQL 5.7 及更早且 query_cache_type=1 时
这个提示词的唯一生效场景是:MySQL 5.7 或更旧版本,且启用了 Query Cache(query_cache_type = 1)。它的作用只是告诉服务器“别把这次查询结果存进 Query Cache”,避免缓存污染或失效开销。
- 它不会跳过解析、优化、执行阶段,也不会绕过 Buffer Pool
- 它不影响
InnoDB的任何内存结构,包括innodb_buffer_pool_pages_data、innodb_buffer_pool_read_requests - 即使你用
SQL_NO_CACHE,查询仍会正常读取数据页 → 这些页照样进 Buffer Pool → 一样触发 LRU 链表操作和可能的 mutex 竞争
真正影响 Buffer Pool 锁竞争的是这些参数和行为
Buffer Pool 内部的并发瓶颈主要来自多线程同时访问共享结构(比如 LRU list、flush list),而 innodb_buffer_pool_instances 是关键开关:
-
innodb_buffer_pool_instances必须 > 1(默认是 1),才能把 Buffer Pool 拆成多个独立实例,降低单个 mutex 的争用 - 每个 instance 有自己的 LRU、free、flush list,线程按 page hash 分配到不同 instance,天然分流
- 推荐值:当
innodb_buffer_pool_size >= 1G时,设为 8;≥ 4G 时可设为 16(上限 64) - 注意:该参数只能在启动时设置,运行中不可动态修改
为什么你看到“加了 SQL_NO_CACHE 后性能变好”?其实是 Buffer Pool 预热或巧合
在 MySQL 5.7 的压测中,有人发现加 SQL_NO_CACHE 后第二次查询变快,误以为是它减少了锁。真实原因是:
- 第一次查询触发磁盘读 → 数据页加载进 Buffer Pool → 后续相同主键/索引范围查询直接命中内存
-
SQL_NO_CACHE只是让 Query Cache 不参与,掩盖了 Query Cache 失效带来的额外开销(比如写入缓存条目、校验哈希),让你更“纯粹”地观察到 Buffer Pool 的效果 - 如果你在 MySQL 8.0+ 上还写
SQL_NO_CACHE,MySQL 会静默忽略它——既不报错,也不起效
Buffer Pool 的锁问题不是靠 SQL 提示能绕开的,得从配置拆分(innodb_buffer_pool_instances)、减少大扫描(避免全表刷爆 LRU)、控制脏页刷新节奏(innodb_io_capacity)这些地方下手。别再在 SQL 里徒劳地加 SQL_NO_CACHE 了——它现在连语法高亮都懒得标红。


















