change buffer 是什么:写多读少场景的免费午餐

举报
yd_275379215 发表于 2026/10/26 08:15:05 2026/10/26
【摘要】 接手了一套埋点日志库,写入量每天2亿条,表上有十几个二级索引,磁盘IO长期高位。查了一圈资料,把目光落在changebuffer上——一个很多人听过名字但说不清原理的机制。调大它之后写入吞吐提升了25%,没改一行业务代码。原理拆开讲不复杂。InnoDB写入时要维护所有索引,如果目标二级索引页恰好在bufferpool里,直接改内存完事;但如果页不在内存(大表随机写时很常见),默认做法是从磁盘...

接手了一套埋点日志库,写入量每天 2 亿条,表上有十几个二级索引,磁盘 IO 长期高位。查了一圈资料,把目光落在 change buffer 上——一个很多人听过名字但说不清原理的机制。调大它之后写入吞吐提升了 25%,没改一行业务代码。

原理拆开讲不复杂。InnoDB 写入时要维护所有索引,如果目标二级索引页恰好在 buffer pool 里,直接改内存完事;但如果页不在内存(大表随机写时很常见),默认做法是从磁盘把页读进来再改,一次随机读就这样产生了。change buffer 的思路是:先把这笔修改记在 change buffer 里就返回,等将来这个页因为查询被读进内存、或者后台线程合并时,再把攒下的修改一次性应用。写的时候跳过了磁盘读,等于把随机读 IO 延后并合并了。

它有几个明确的边界。第一,只对非唯一的二级索引生效,唯一索引插入前必须读页判重,绕不开那次读。第二,收益取决于"写了但不马上读"的比例,埋点、日志这类 append 多、查询少的场景收益最大;如果写完马上要读,change buffer 里攒的修改立刻要合并,反而多一跳。第三,它占用 buffer pool 的空间,上限由 innodb_change_buffer_max_size 控制,默认 25%,我们调到了 50%。

判断生效程度看两个地方:SHOW ENGINE INNODB STATUS 里 INSERT BUFFER AND ADAPTIVE HASH INDEX 一节,有 merges、merged operations 的累计值,IOPS 高压时段 merged operations 持续增长说明在干活;也可以观察 information_schema.innodb_buffer_page 里 IBUF 类型的页占比。

最后给个判断口诀:SHOW ENGINE INNODB STATUS 里 merged operations 的增长速度,除以同期的二级索引写次数,就是 change buffer 的实际吸收率。我们那套日志库吸收率 62%,意思是近三分之二的二级索引写没触发磁盘读。低于 20% 就别调了,说明你的负载是读密集型,change buffer 帮不上忙。

这次调优后我重新审视了索引设计:那十几个二级索引里有三个是唯一索引,吃不到 change buffer 红利还贡献了最多的读放大,跟业务确认唯一性约束其实可以由上游保证,删掉之后写入延迟进一步下降。change buffer 不是万能药,但它提醒我们:写多读少的库,索引数量和唯一性设计本身就是性能参数。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。