MySQL 的 Change Buffer
1. 什么是 Change Buffer?
Change Buffer 是 MySQL InnoDB 存储引擎中的一个优化机制,用于减少磁盘 I/O 操作。它是一个专门用来缓存 非唯一二级索引变更操作 的内存区域,位于 InnoDB 的 Buffer Pool 中。
当对非唯一二级索引执行插入、更新或删除操作时,MySQL 并不会立即将这些变更写入磁盘,而是将变更记录存入 Change Buffer,稍后再合并到物理页面中。
2. Change Buffer 的作用
(1)减少磁盘 I/O
将索引页的变更操作缓存起来,避免频繁的随机磁盘读写操作,从而提升性能。
(2)提升写入性能
对于非唯一二级索引的修改操作:
- 如果目标索引页已在内存中,直接更新内存中的页。
- 如果目标索引页不在内存中,将变更写入 Change Buffer,延迟加载目标页,从而减少磁盘读取。
(3)批量合并
当后台线程或需要访问相关索引页时,MySQL 将 Change Buffer 的内容与实际的物理页面进行合并(称为 merge 操作)。这种批量合并可以提高效率。
3. Change Buffer 的适用场景
Change Buffer 仅适用于 非唯一二级索引 的修改操作:
- 非唯一二级索引的插入(Insert Buffering)
- 非唯一二级索引的更新(Delete-Mark Buffering 和 Insert Buffering)
- 非唯一二级索引的删除(Delete Buffering)
主键索引和唯一索引 无法使用 Change Buffer,因为它们需要立即验证唯一性。
4. Change Buffer 的管理
(1)参数配置
innodb_change_buffer_max_size
用于控制 Change Buffer 占用 Buffer Pool 的比例(百分比),默认值为 25。
SET GLOBAL innodb_change_buffer_max_size = 50;
该参数的取值范围为 0 到 50,设置为 0 时禁用 Change Buffer。
(2)合并时机
Change Buffer 的合并操作发生在以下时机:
- 查询需要访问相关索引页时。
- 后台线程(如主线程)空闲时执行异步合并。
- 数据页从磁盘加载到内存时。
(3)持久化
Change Buffer 的内容保存在系统表空间中,保证在 MySQL 重启后仍然有效。
5. Change Buffer 的优势
- 性能提升
- 避免频繁的随机磁盘 I/O,提升插入和更新性能。
- 高效资源利用
- 利用内存缓存变更,提高磁盘访问效率。
- 适用于批量写入场景
- 批量插入、更新非唯一二级索引时,Change Buffer 的效果尤为显著。
6. Change Buffer 的限制
- 适用范围有限
- 仅支持非唯一二级索引的修改,主键索引和唯一索引无法使用。
- 占用内存资源
- Change Buffer 位于 Buffer Pool 中,占用一定内存资源,可能影响其他缓存的效率。
- 可能增加磁盘负载
- 当 Change Buffer 内容较多时,后台合并操作会增加磁盘 I/O。
7. Change Buffer 的使用示例
创建非唯一二级索引
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
age INT,
INDEX (age)
) ENGINE=InnoDB;
对于 age
列上的非唯一二级索引插入操作:
- 如果目标页不在内存中,变更会写入 Change Buffer,而不是立即加载索引页。
- 后续访问或后台线程会将 Change Buffer 中的内容合并到磁盘页中。
8. 总结
- Change Buffer 是 InnoDB 用于优化非唯一二级索引写入性能的重要机制。
- 它通过将变更缓存在内存中,减少磁盘 I/O,提升写入性能。
- 适用于大量插入、更新非唯一二级索引的场景,但需要注意内存和磁盘资源的平衡。