TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

mysql change buffer

参考

innodb buffer poll

2020082601.jpg

inser buffer

innodb的索引是B+树,主键索引也叫聚簇索引,是自增的一个非空的键值。所以顺序插入的效率是很高的。但是对于非聚簇索引(第二索引),则往往是离散插入的,效率很低。经常会碰到字符串,或者非递增的数据作为第二索引。

为了减少离散插入造成的效率损失,innodb引入了insert buffer缓冲区,对于第二索引的插入,先放到缓冲区中,然后merge,如果merge的时候,一次可以处理多个,就提升了性能。

insert buffer使用要满足:

  • 索引是辅助索引(第二索引)
  • 索引不是唯一的

因为唯一索引要判断唯一性,就不能直接放到缓冲区不管。

1
2
3
4
5
6
7
8
9
10
11
show engine innodb status;


-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0

segsize表示insert buffer大小:2*16kb

free list代表空闲列表长度

size表示已经合并数据页的长度

change buffer

innodb从1.0.x版本引入change buffer,是insert buffer的加强版,不仅支持insert,还支持其他dml操作(insert buffer, delete buffer, purge buffer)。所以,insert buffer也是个老古董了。

delete操作可能的过程:

  • 将记录标记为已删除
  • 真正删除记录

第一步就是delete buffer,第二步是purge buffer.

innodb_change_buffering

1
2
3
4
5
6
7
MySQL [mysql]> show variables like 'innodb_change_buffering';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| innodb_change_buffering | all |
+-------------------------+-------+
1 row in set (0.00 sec)

innodb_change_buffering可选的值:

  • inserts
  • deletes
  • purges
  • changes
  • all
  • none

changes = inserts + deletes

all = 所有

none表示不启用

innodb_change_buffer_max_size

1
2
3
4
5
6
7
MySQL [mysql]> show variables like 'innodb_change_buffer_max_size';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| innodb_change_buffer_max_size | 25 |
+-------------------------------+-------+
1 row in set (0.00 sec)

innodb_change_buffer_max_size表示change buffer的最大大小,25表示最多使用1/4的缓冲池空间。

change buffer内部也是B+树,具体不研究了。

question

如果binlog=row,需要旧的数据,会影响change buffer吗?

这个mysql实战45讲下面的问题,之前自己也没搞懂,这篇文章写完似乎明白了。

聚簇索引和第二索引都是B+树,不管是新增数据还是删除数据,聚簇索引和第二索引都是要同步的。所以change buffer必要性在这里。同步聚簇索引效率高,同步第二索引效率低,所以先缓存,并不真的落盘同步。等下次查询的时候,在从磁盘读取第二索引的值,将之前的buffer数据读入merge.或者后台线程merge.

然后查老得数据是从聚簇索引查的,不影响。我理解聚簇索引是肯定要持久化到磁盘的,第二索引应该也会持久化到磁盘。所以对于查老得数据,如果内存不存在,直接将磁盘的聚簇索引的记录查出来就是完整的行记录,不用查磁盘的第二索引的值,所以change buffer还是起效果的。

ending

----------- ending -----------