跳转到内容

MySQL Change Buffer


在 MySQL 的 InnoDB 引擎里,Change Buffer(变更缓冲区)是一个非常聪明的机制,用来提高磁盘 I/O 效率,尤其是对于二级索引(非聚簇索引)的更新操作。

想象一下,你家有一大堆账本,每次修改账本里的条目都得跑到柜子里翻找,写一条就写一条,非常慢。

  • 如果修改很多条目,每次都去柜子里写,效率极低。

Change Buffer 就像是 一个临时笔记本,当你要修改二级索引时,它先把修改记录记在笔记本上(缓冲区里),而不是立即去硬盘上改真正的索引页。

  • 这样可以 先在内存里累积多条修改,等到合适的时机(比如索引页被读取到内存,或者后台合并时)再一次性写入硬盘。

优势

  1. 减少磁盘随机写:大量小修改可以合并成一次连续写入,磁盘效率大大提升。

  2. 提升更新性能:尤其是对二级索引的 INSERTUPDATEDELETE,减少了每次操作都访问磁盘的开销。

注意点:

  • Change Buffer 只对 二级索引 起作用,对 聚簇索引(主键索引) 无效,因为主键索引必须立即更新。

  • 如果缓存过大或合并不及时,也可能增加后台 I/O 压力。

  • 可以通过参数 innodb_change_buffering 控制 Change Buffer 的使用策略(如仅插入、更新、删除都缓冲,或者只缓冲插入等)。

Change Buffer 就是 InnoDB 给[[二级索引]]做的“内存笔记本”,先记下来再慢慢写磁盘,减少随机 I/O,提高性能。

在 MySQL 的 InnoDB 存储引擎中,Buffer Pool(缓冲池)是一个核心的内存区域,用于缓存表的数据页、聚簇索引页、二级索引页以及部分 Undo 日志信息,它的主要作用是尽量减少对磁盘的访问,提高数据库的读写性能。

具体来说,当执行查询操作时,InnoDB 会首先在 Buffer Pool 中查找所需的数据页,如果数据页已经存在于内存中(命中),就可以直接返回查询结果,这比从磁盘读取要快上很多倍;如果数据页不在内存中(未命中),InnoDB 会从磁盘加载相应页到 Buffer Pool,再返回给查询请求,同时保存在内存中以便后续访问。

对于写操作,修改的数据同样会先在 Buffer Pool 的内存页中进行更新,这些内存中的数据页称为“脏页(Dirty Page)”,然后由后台刷新线程异步将脏页写回磁盘,保证数据持久性。

通过这种方式,Buffer Pool 可以显著降低磁盘随机 I/O 的次数,提高查询和更新的响应速度。此外,Buffer Pool 还可以与 Change Buffer 配合使用,对二级索引的插入、更新、删除操作进行缓冲,进一步减少对磁盘的频繁访问。通常,我们通过 innodb_buffer_pool_size 参数配置缓冲池的大小,以确保尽可能多的“热点”数据驻留在内存中,从而支撑高并发场景下的数据库性能。

InnoDB Buffer Pool 里,其实有一块内存是专门留给 Change Buffer 用的。那么,Change Buffer 究竟是什么呢?

假设表中有一个 二级索引 针对 name 字段。我们执行如下 SQL:

UPDATE table SET name = 'yes' WHERE id = 1;

这条语句需要修改 name 这个二级索引的索引页。此时,如果 Buffer Pool 中还没有对应的二级索引页,是否需要立即从磁盘加载索引页进行修改呢?

答案是否定的,Change Buffer 就在这里发挥作用。当二级索引页不在 Buffer Pool 中时,InnoDB 会将这次更新操作缓存在 Change Buffer 中,而不是立即访问磁盘。下次访问这条数据时,索引页加载到 Buffer Pool 中,同时会应用 Change Buffer 中缓存的变更,从而保证数据的一致性。上述 SQL 中,Change Buffer 会存储 name 字段的 旧索引值删除操作和新索引值插入操作

  1. 减少随机 I/O:当二级索引页不在 Buffer Pool 中时,Change Buffer 可以避免立即从磁盘读取对应索引页的昂贵随机 I/O。

  2. 批量应用修改:对二级索引的更改可以在索引页被加载到 Buffer Pool 时一次性应用,提高写入效率。

  3. 适用范围:Change Buffer 仅用于 二级索引,不适用于主键索引、空间索引、全文索引和唯一索引(因为唯一索引修改前必须检查数据一致性)。

如果更改先缓存在 Change Buffer 中,数据库突然挂了会丢吗?

不用担心,Change Buffer 也是会落盘的。它的数据存储在 系统表空间 中,并且 Redo Log 会记录 Change Buffer 的修改,以保证崩溃恢复时数据的一致性。

  • Change Buffer 的大小:通过系统变量 innodb_change_buffer_max_size 配置,默认是 Buffer Pool 的 25%,最大可设置为 50%

  • 是否开启:如果内存充足可以容纳所有索引页,或者二级索引较少,或者磁盘是 SSD 对随机访问影响不大,可以考虑关闭 Change Buffer,以减少系统复杂度。

  • 主要作用:避免二级索引修改产生大量随机 I/O,提高更新操作性能。

Change Buffer 就像二级索引的“笔记本内存”,先在内存里记下修改,等索引页被访问时再批量应用,从而降低随机磁盘 I/O、提高写入效率,同时保证数据安全。