buffer pool是innodb专属缓存,用于缓存数据页和索引页;key buffer是myisam专属,仅缓存索引块,两者互不兼容、不可混用。

Buffer Pool 是 InnoDB 专属,Key Buffer 是 MyISAM 专属
两者根本不在一个存储引擎里工作,不能混用或互相替代。InnoDB 表的读写完全不走 key_buffer_size,MyISAM 表也完全不使用 innodb_buffer_pool_size。如果你用的是 InnoDB(99% 的现代业务都是),调大 key_buffer_size 不仅没用,还会白占内存。
常见错误现象:SHOW ENGINE INNODB STATUS 显示 Buffer Pool 命中率低,但你却在反复调 key_buffer_size;或者 SHOW STATUS LIKE 'Key_%' 发现 Key_reads 很高,误以为是缓存不够——其实只是你在用 InnoDB 表,这些指标压根不反映真实压力。
Buffer Pool 缓存「数据页 + 索引页」,Key Buffer 只缓存「索引块」
innodb_buffer_pool_size 管的是整块内存池,里面放的是从磁盘加载的 16KB 数据页(含表数据、聚集索引、二级索引),所有读写操作优先查这里。而 key_buffer_size 只缓存 MyISAM 的 .MYI 文件里的索引节点(B+Tree 的非叶子节点),不缓存任何表数据(.MYD 文件)——也就是说,MyISAM 即使命中了 key buffer,仍要额外一次磁盘读取才能拿到行数据。
性能影响很直接:同样 1GB 内存分配,给 Buffer Pool 能显著降低数据和索引的双重 I/O;给 Key Buffer 只能缓解索引查找的随机读,对数据读取无帮助。这也是为什么 MyISAM 在高并发写入下极易成为瓶颈。
默认值与线上调整逻辑完全不同
MySQL 5.7+ 在 Linux 上默认把 innodb_buffer_pool_size 设为物理内存的 50%–70%,且会自动按 innodb_buffer_pool_instances 拆分(比如设为 8,16GB 物理内存就分 8 个约 1GB 的子池)。而 key_buffer_size 默认固定为 8MB,无论机器多大都不会自适应——哪怕你有 128GB 内存,它还是 8MB,除非你手动改。
实操建议:
- 纯 InnoDB 环境:把
key_buffer_size设为0或1(最小有效值),避免内存浪费 - 混合引擎环境:必须确认哪些表真正在用 MyISAM(
SELECT ENGINE, COUNT(*) FROM information_schema.TABLES GROUP BY ENGINE;),再按实际 MyISAM 索引大小的 2–3 倍设key_buffer_size,别拍脑袋填 256MB - Buffer Pool 大小不要超过物理内存的 70%,否则可能触发系统 swap,反而拖垮性能
查询缓存已淘汰,别把它和 Buffer Pool 搞混
有人看到 query_cache_size 默认为 0,就以为“MySQL 没缓存了”,转头猛调 key_buffer_size 想补位——这是典型误解。query_cache 缓的是 SELECT 语句的完整结果集(SQL 文本 → 结果二进制),而 Buffer Pool 缓的是底层数据页(16KB 一页,跨语句复用),两者粒度、生命周期、失效机制全不同。InnoDB 的性能提升主要靠 Buffer Pool 命中率,不是靠复活 query cache。
容易被忽略的一点:Buffer Pool 中的脏页刷盘由 innodb_max_dirty_pages_pct 和 Checkpoint 控制,不是“写完立刻落盘”,这和 MyISAM 的写即落盘行为有本质区别——这也意味着,Buffer Pool 越大,崩溃恢复时重放 redo log 的压力也可能越大,不能只看命中率盲目堆内存。











