阅读change buffer相关文档

This commit is contained in:
asahi
2024-12-16 12:46:16 +08:00
parent 353e984695
commit ba967259bd

View File

@@ -12,6 +12,51 @@ innodb内存池由多个内存块构成内存快负责如下功能
在innodb存储引擎中后台线程主要负责刷新内存池中的数据保证内存缓存为最新状态。此时后台线程还负责将内存池中的修改刷新到磁盘中。 在innodb存储引擎中后台线程主要负责刷新内存池中的数据保证内存缓存为最新状态。此时后台线程还负责将内存池中的修改刷新到磁盘中。
## mysql存储结构
mysql存储结构如图所示
![mysql storage structure](https://www.mysqltutorial.org/wp-content/uploads/2024/01/mysq-innodb-architecture.png, "mysql存储结构")
mysql存储结构主要分为两部分
- 内存结构
- 磁盘存储结构
### 内存结构
mysql内存结构主要是为了管理和优化数据存储和数据检索mysql内存结构包含
- 缓冲区Buffer Pool
- Change Buffer
- 自适应哈希索引Adaptive hash index
- Log Buffer
#### Buffer Pool
buffer pool主要用于缓存经常访问的数据
#### change Buffer
change buffer主要用于缓存针对辅助索引页面的修改。当被修改的辅助索引页面不存在于内存中时将修改缓存在change buffer中当后续辅助索引页面被加载到内存中时会将对该页面的修改进行合并。
#### Adaptive hash index
自适应哈希索引是一个内存结构,用于优化部分读取操作的性能。其提供了一个快速内存检索机制,用于加速对索引页的频繁访问。
#### log Buffer
log buffer是一个内存区域用于存储将要被写入到transactiion log中的数据。
### 磁盘存储结构
innodb存储引擎将数据持久化存储到磁盘中。磁盘存储的结构如下所示
- system tablespace
- file-per-table tablespaces
- general tablespaces
- undo tablespaces
- temporary tablespaces
- double write buffer
- redo log
- undo log
#### system tablespace
system tablespace作为change buffer的存储区域。
innodb用一个或多个文件来存储system tablespace默认情况下mysql会创建名为`ibdata1`的文件。
`innodb_data_file_path`决定了system tablespace files的大小和数量。
## 后台线程 ## 后台线程
innodb采用多线程模型存在多个后台线程每种后台线程负责不同的后台任务。 innodb采用多线程模型存在多个后台线程每种后台线程负责不同的后台任务。
@@ -327,3 +372,72 @@ master thread中每秒一次的操作包括如下内容
- 将日志缓冲刷新到磁盘(总是) - 将日志缓冲刷新到磁盘(总是)
- 删除无用的undo log页总是 - 删除无用的undo log页总是
## change buffer
change buffer为一个特殊的数据结构当想要修改的辅助索引page不在缓冲区中时会将针对辅助索引page的修改缓冲到change buffer中。
对于辅助索引页面的修改可能是由`insert, update, delete`操作造成的当后续待修改的页面被读入到缓冲区中时会对change buffer中缓冲的修改操作进行合并。
### 聚簇索引和辅助索引插入顺序
和聚簇索引不同,辅助索引通常不是唯一的。`并且,当使用`auto_increment`的聚簇索引时新数据的插入通常都是顺序的插入的多个数据唯一同一page中。`
但是当插入新数据时新数据对应辅助索引记录的插入则相对是无序的多条辅助索引记录的插入可能都分布在不同的page。同样的针对辅助索引记录的修改和删除其影响的辅助索引记录页可能分布在不同的索引页中。
通过change buffer将针对辅助索引页面的修改缓冲在buffer中并且当需要修改的辅助索引页面读取到缓冲区中时再对change buffer中的修改操作进行合并这样能很大程度上避免多次随机读取辅助索引页到缓冲区中带来的开销。
> 定期执行的purge操作会将被更新的索引页写入到磁盘中。相比于马上将被修改的索引页写入到磁盘中purge操作更高效。
当存在很多被修改的行数据以及辅助索引数据时change buffer merging操作可能花费数个小时来执行。在change buffer merging期间磁盘IO将会增加可能会导致磁盘相关查询的性能下降。
在内存中change bufer占用的缓冲区的一部分而在磁盘中change buffer是system tablespace的一部分。当数据库实例未启动时针对辅助索引的修改存储在磁盘的change buffer文件中。
> 当辅助索引中包含`descending index column`或主键中包含`descending index column`时change buffer不适用。
降序索引示例如下:
```sql
CREATE TABLE t (
c1 INT, c2 INT,
INDEX idx1 (c1, c2 DESC),
INDEX idx2 (c1 DESC, c2),
INDEX idx3 (c1 DESC, c2 DESC)
);
```
### change buffer配置
当对于table执行insert、update、delete一些列操作时这些操作集合中辅助索引列的值通常是无序的分散在多个辅助索引页中如果大量更新多个索引页。`当待更新的辅助索引页不位于buffer pool中时针对辅助索引页的修改将会被缓存。当待更新的索引页面被加载到buffer pool中时被缓存的修改操作将会被合并被更新的页面后续会刷新到磁盘中`
> innodb在数据库实例空闲或slow shutdown时会进行change buffer的合并。
#### 优势
change buffer可以带来更少的磁盘读取和磁盘写入故而在工作负载收到io限制时change buffer能发挥重大作用。例如在存在大量插入操作时change buffer能够显著提升性能。
#### 弊端
由于change buffer会占用buffer pool的内存空间故而当change buffer较大时会减少数据缓存的可用空间。`但是如果work set的大小和buffer pool几乎相当时或是数据库表中几乎没有辅助索引时此时则可以禁用change buffer`
### `innodb_change_buffering`
`innodb_change_buffering`变量控制chnage buffer的行为通过`innodb_change_buffering`,可以对如下操作进行启用和禁用:
- insert operations
- delete operations:`当index record被标记为删除`
- purge operations: `当index被物理删除`
> update操作是insert操作和delete操作的组合
`innodb_change_buffering`取值如下:
| value | numeric value | description |
| :-: | :-: | :-: |
| none | 0 | `默认`,不针对任何操作进行缓存 |
| inserts | 1 | 针对insert操作进行缓存 |
| deletes | 2 | 针对delete marking操作进行缓存 |
| changes | 3 | 针对inserts和delete-marking操作进行缓存 |
| purges | 4 | 针对后台发生的物理删除操作进行缓存 |
| all | 5 | 针对inserts, deletes, purges操作进行缓存 |
### `innodb_change_buffer_max_size`
`innodb_change_buffer_max_size`允许按照百分比的方式来配置change buffer占用buffer pool的最大大小默认为`25`,最大可为`50`
当mysql server存在大量insert、update、delete操作时change buffer merging操作的速率无法跟上change buffer entries的新增速率此时可以考虑增加`innodb_change_buffer_max_size`
当change buffer占用了过多buffer pool中内存导致buffer pool中页面老化速度超出预期时此时可以尝试将`innodb_change_buffer_max_size`适当调小。