直接回答:Change Buffer 是 InnoDB 对非唯一二级索引写操作的延迟物化机制:当要修改的二级索引页不在 Buffer Pool 时,不立即从磁盘读入该页,而是把变更记录到 Change Buffer(常驻 Buffer Pool,持久化在系统表空间),之后该页因查询被读入内存时再 merge。它把随机 I/O 变成内存操作,还能合并对同一页的多次修改,显著降低写放大,是 InnoDB 写性能的关键优化之一。
展开解析:为什么只限非唯一索引——唯一索引插入必须读页做冲突检查,缓存变更没有意义。因此 Change Buffer 适合写多读少、二级索引多、写后短期不读的业务(日志、流水、埋点表);如果写完马上读,页面立即被加载触发 merge,收益消失反而多写一次,这种表应考虑关闭。相关参数:innodb_change_buffering(all/inserts/deletes/none,控制缓存哪些操作)、innodb_change_buffer_max_size(默认占 Buffer Pool 的 25%,上限 50%)。merge 时机有三个:页面被读入 Buffer Pool、后台 master thread 定期合并、实例正常 shutdown 前。可靠性由 redo log 保证——Change Buffer 本身的变更也写 redo,崩溃不丢,恢复时会重放。
实践要点:观察 INFORMATION_SCHEMA.INNODB_METRICS 或 SHOW ENGINE INNODB STATUS 中的 merge 频率评估收益;它与 LSM 树“先写内存结构、后合并”的思想一脉相承。
追问方向:为什么唯一索引不能用 Change Buffer?崩溃恢复时 Change Buffer 里的数据如何处理?Change Buffer 和 LSM-Tree 有什么相通之处? (约 351 字)