学习于极客时间--MySQL实战
Change Buffer
InnoDB 从 1.0.x 版本开始引入了 Change Buffer,算是对 Insert Buffer 的升级。从这个版本开始,InnoDB 存储引擎可以对 insert、delete、update 都进行缓存。
影响参数有两个:
- innodb_change_buffering:确定哪些场景使用 Change Buffer,它的值包含:none、inserts、deletes、changes、purges、all。默认为 all,表示启用所有。
- innodb_change_buffer_max_size:控制 Change Buffer 最大使用内存占总 buffer pool 的百分比。默认25,表示最多可以使用 buffer pool 的 25%,最大值50。
使用 change buffer 对更新过程的加速作用,但change buffer 只限于用在普通索引的场景下,而不适用于唯一索引。那么,普通索引的所有场景,使用 change buffer 都可以起到加速作用吗?
因为 change buffer merge 的时候是真正进行数据更新的时刻,而 change buffer 的主要目的就是将记录的变更动作缓存下来,所以在一个数据页做 merge 之前,change buffer 记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大。
因此,对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时 change buffer 的使用效果最好。这种业务模型常见的就是账单类、日志类的系统。
反过来,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新先记录在 change buffer,但之后由于马上要访问这个数据页,会立即触发 merge 过程。这样随机访问 IO 的次数不会减少,反而增加了 change buffer 的维护代价。所以,对于这种业务模式来说,change buffer 反而起到了副作用。
change buffer 和 redo log
redo log 与 change buffer(含磁盘持久化) 这2个机制,不同之处在于优化了整个变更流程的不同阶段。 先不考虑redo log、change buffer机制,简化抽象一个变更(insert、update、delete)流程:
1、从磁盘读取待变更的行所在的数据页,读取至内存页中。
2、对内存页中的行,执行变更操作
3、将变更后的数据页,写入至磁盘中。
步骤1,涉及 随机 读 磁盘IO; 步骤3,涉及随机 写 磁盘IO;
hange buffer机制,优化了步骤1,节省了随机读磁盘的 IO 消耗。
redo log机制, 优化了步骤3,节省的是随机写磁盘的 IO 消耗(将随机写磁盘,优化为了顺序写磁盘(写redo log,确保crash-safe) ;
在mysql innodb中, change buffer机制不是一直会被应用到,仅当待操作的数据页当前不在内存中,需要先读磁盘加载数据页时,change buffer才有用武之地。 redo log机制,为了保证crash-safe,一直都会用到。
有无用到change buffer机制,对于redo log这步的区别在于—— 用到了change buffer机制时,在redo log中记录的本次变更,是记录new change buffer item相关的信息,而不是直接的记录物理页的变更。