问题

  1. change buffer 有什么作用?
  2. 什么情况下会用到change buffer

准备工作

  1. select * from information_schema.innodb_metrics where name like '%ibuf%';

可以查看到change buffer 的相关信息。
image.png

创建张表

  1. CREATE TABLE `author_1` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `name` varchar(255) DEFAULT NULL,
  4. `age` int(11) DEFAULT NULL,
  5. PRIMARY KEY (`id`),
  6. KEY `index_name` (`name`) USING BTREE
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

author_1 有主键索引,和一个index_name 的二级索引。

假设该表存在以下数据

聚簇索引的结构类似于:

页6
1 2 3
abc jack zrr
234 24 23

我们知道二级索引 的value 存的是主键,例如此例子中二级索引的结构类似于:

页65
abc jack zrr
1 2 3

如果没有Change Buffer ,一条更新语句是如何执行的?

  1. update author_1 set name = 'xxx' where id = 1

这个语句需要修改 2 个页面的数据。

  1. 第一处 是 聚簇索引 中的 id =1 条中的数据。
  2. 第二处 是 修改二级索引的 name 的数据。

更新流程是:
首先在 Buffer Pool 中查找对应的 页,(也就是页6, 和页65)
这里产生了2种情况:

  1. 页6 和 页 65 在Buffer Pool 中, 那么只要更新内存中的记录, 并写 redo log 。
  2. 页6 和 页 65 不在 Buffer Pool 中, 那么需要从磁盘中进行读取,放入内存后, 再修改, 并写redo log.

我们知道磁盘IO 比较耗时,所以Mysql 为了优化这一步骤,引入了Change Buffer 。

Change Buffer 作用场景

首先强调:

  • Change Buffer 是针对 非唯一的二级索引 的优化!
  • Change Buffer 是针对 非唯一的二级索引 的优化!
  • Change Buffer 是针对 非唯一的二级索引 的优化!

那么也就是 主键,以及唯一索引 是用不了这个优化的。
对应到例子中, 即使引入了Change Buffer ,如果页6不在Buffer Pool 中,无论如何都需要从磁盘中读取,然后修改。
而页65,则不同了:
这个时候页65,不需要从磁盘中进行读取了,InnoDB 会直接写一条信息到Change Buffer 中,然后写redo log 。这样无需进行磁盘IO就可以完成更新。

总结下 Change Buffer 只有 对非唯一的二级索引 的数据页 ,并且该数据页不存在Buffer Pool 中,才会被使用到。

另外说明一点:change buffer 和 redo log 的数据为了持久化是会被刷入磁盘的。 也许会有疑问?这还不是进行磁盘操作了吗? 是进行磁盘操作了,但是change buffer 和 redo log 都是进行顺序写效率较高 (磁盘顺序写 和 随机写 性能差异很大)

修改后立即读取会如何?

  1. select * from school where name = 'xxx'

由于会用到 index_name 索引, 所以需要将页65 读取到Buffer Pool ,但我们知道此时页面65页中 只有记录 ‘abc’ ,那么读取页面65 之后,InnoDB 首先把 Change Buffer 中的数据 与读取的数据merge ,然后存储在Buffer Pool中,这个时候页65 中的数据就是正确的数据了。

为什么唯一索引无法使用Change Buffer ?

道理很简答, 唯一索引 在插入修改时都要进行唯一判断。如果不读取数据无法进行判断,既然数据无论如何都必须读取到Buffer Pool 中 自然就不会用到Change Buffer 了。

总结

change buffer 提升了对非唯一二级索引 的写性能。 如果业务上对字段没有唯一性要求,那么应该尽量使用普通索引,避免唯一索引。对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时 change buffer 的使用效果最好。这种业务模型常见的就是账单类、日志类的系统。