Change Buffer属于Innodb内存中的一块结构,它主要用来缓存对二级索引数据的修改(insert, update, delete)操作当二级索引不在Buffer pool中的时候,这些写操作会在稍后合并到二级索引当二级索引被其他读请求加载到buffer pool的时候。
不同于聚簇索引,二级索引通常不是唯一的,插入二级索引的顺序是相对随机的,删除和更新操作也可能会影响二级索引中不想临的页,在稍后当受影响的页被其他操作加载到buffer pool的时候会合并缓存在change buffer的更新,以此来避免大量的随机IO操作。
这些合并操作会在系统空闲的时候定期执行,或者在系统关闭的时候,将这些对索引页的更新写入磁盘。比起每次更新都写磁盘,这种purge 操作能够更有效的将一系列更新写入磁盘块。
当有许多被影响的行和大量的二级索引被更新,change buffer的合并操作可能会花费几个小时的时间。在这期间,磁盘IO会增加,这也会导致明显的磁盘查询缓慢。change buffer 合并可能在事务提交后继续执行,甚至MySQL server 重启之后。
在内存中,change buffer占用buffer pool的一部分,在磁盘上,change buffer是系统表空间(system tablespace)的一部分,当服务器停机的时候,change buffer会缓存在磁盘上。
change buffer 不支持包含逆序或者主键包含一个逆序字段的索引。
配置 Change Buffering
由于它能减少磁盘读写,Change buffer的特性对于IO高的应用最有用,比如有大量DML操作如批量插入的应用。
然而,change buffer占用了buffer pool的一部分,减少了用于缓存数据页的内存。如果工作集非常适合buffer pool(buffer pool中能缓存下所有的数据和索引),或者你的表有很少的二级索引,那么禁用change buffer也许是有用的。
使用 innodb_change_buffering 来配置change buffer中缓存的数据类型,默认值为 all ;
此值的取值有:
- all : 默认值,包含insert ,delete_marking, 和 purges.
- none: 禁用change buffer
- inserts : 缓存插入操作
- deletes : 缓存删除操作
- changes: 包含 insert delete-marking
- purge: 后台的物理删除操作
使用 innodb_change_buffer_max_size
监控 Change Buffer
- Innodb 标准监控输出包含了change buffer的信息,执行 SHOW ENGINE INNODB STATUS 语句
mysql> SHOW ENGINE INNODB STATUS\G
change buffer的统计信息在 INSERT BUFFER AND ADAPTIVE HASH INDEX 这行下面
1 -------------------------------------
2 INSERT BUFFER AND ADAPTIVE HASH INDEX
3 -------------------------------------
4 Ibuf: size 1, free list len 0, seg size 2, 0 merges
5 merged operations:
6 insert 0, delete mark 0, delete 0
7 discarded operations:
8 insert 0, delete mark 0, delete 0
9 Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
10 13577.57 hash searches/s, 202.47 non-hash searches/s