阅读innodb made young相关文档
This commit is contained in:
@@ -137,11 +137,48 @@ midpoint将LRU列表分为了两部分:
|
||||
- 当innodb读取页到缓冲池中时,新读取的页将会被插入到midpoint位置。页可能因为如下原因被读取:
|
||||
- 由用户发起的操作,例如sql查询
|
||||
- 由innodb执行的read ahead操作
|
||||
- 当访问old部分的页时,会`made young`,即将页从old部分移动到young部分的头部。如果对old部分页的访问是由用户发起的操作,那么那么该页面会被移动到young部分的头部
|
||||
- 当访问old部分的页时,会`made young`,即将页从old部分移动到young部分的头部。
|
||||
- `如果old部分的页是因为用户发起的查询被读取到缓冲池,那么该页马上会被访问,并且该页会被made young`
|
||||
- `如果该页是被因为innodb的read ahead被读取到缓冲池中,那么该页可能不会马上被访问,甚至知道该页被淘汰也不会被访问`
|
||||
- 随着数据库的运行,LRU中的young部分和old部分页面都会向LRU列表尾部移动,这被称为`老化`。当其他页面触发`made young`操作时:
|
||||
- 如果发生`made young`操作,那么young部分和old部分的节点都会向后移动,发生老化
|
||||
- 如果由新页面被插入到midpoint,那么只有old部分的节点会发生老化
|
||||
|
||||
> #### table scan导致的问题
|
||||
> 默认情况下,因用户发起的查询操作而被读取的页面,挥别马上移动到LRU young部分。例如mysqldump操作或不带where条件的select,都会发起table scan,而table scan会读取大量数据到缓冲区中,此时,会对缓冲区中旧的页进行淘汰。(通常,table scan读取到缓冲区的新数据,后续可能并不会被用到)。
|
||||
>
|
||||
> table scan会快速的将原本处于young部分的页面向后推动到old部分,通常,这些页都是被频繁使用的。
|
||||
|
||||
如上所述,table scan会将大量页读取到缓冲池中,但是这些页只会在短期内被很快的访问过几次(访问会导致该页被made young,移动到young部分),只会就不会再用到,这样会导致大量原本被访问的页被淘汰。
|
||||
|
||||
为了解决该问题,innodb引入了`innodb_old_blocks_time`,在第一次访问了位于old区域的页后的`innodb_old_blocks_time`时间范围内,再次访问该页并不会导致该页被移动到LRU的young部分。`innodb_old_blocks_time`的默认值为1000,增加该值将会使old部分的页触发`made young`的条件变得更苛刻,old部分老化和淘汰的速度也会更快。
|
||||
|
||||
#### youngs/s & non-youngs/s
|
||||
- youngs/s: `youngs/s`该指标代表每秒平均的`因访问old页从而导致made young的访问次数`,如果相同的页发生多次访问,那么所有的访问将都会被计入
|
||||
- non-youngs/s: 该指标代表`访问old页且没有导致made young的访问次数`,如果相同页发生多次访问,那么所有的访问都会被计入
|
||||
|
||||
如果在没有大量扫描发生的情况下,youngs/s的指标值仍然很小,那么可以考虑适当降低`innodb_old_blocks_time`的值,让更多的页更快进入young部分。同样,可以适当增加old部分的百分比,从而可以令old页更慢移动到LRU尾端,更有可能被made young。
|
||||
|
||||
如果在发生大量扫描的情况下,non-youngs/s的指标值仍然不高,那么可以考虑增加`innodb_old_blocks_time`的值,延长old页不触发made young的时间窗口
|
||||
|
||||
#### buffer pool hit rate
|
||||
buffer pool hit rate代表缓冲池中页的命中率,如果命中率高则代表该缓冲池运行良好。如果命中率较低,则需要考虑是否应增加`innodb_old_blocks_time`的值,避免table scan导致缓冲池被污染。
|
||||
|
||||
#### FreeList
|
||||
当数据库实例刚启动时,LRU里列表中并没有任何页,此时页都存放在Free List中。当要从缓冲池中获取页时,首先查看Free List中是否有空闲的页,`如果有则从FreeList中获取,并将该页添加到LRU的midpoint位置`;`若Free List中没有空闲的页,那么将根据LRU算法淘汰LRU尾部的页,将淘汰页的内存空间分配给新的页。`
|
||||
|
||||
#### Flush List
|
||||
LRU中被修改的页称其为`脏页`,在缓冲池中的数据被修改之后,并不会马上就刷新到磁盘中,而是会通过checkpoint将脏页刷回到磁盘中。
|
||||
|
||||
FlushList即是脏页的列表,需要注意的是,脏页既存在于LRU中,又存在于FlushList中,LRU和FlushList都管理的是指向该内存页的指针,LRU管理缓冲,而FlushList管理脏页回刷,二者互不影响。
|
||||
|
||||
### redo log buffer
|
||||
innodb存储引擎的内存区域中,除了有缓冲池之外,还存在redo log buffer。innodb首先会将redo log放入到这个缓冲区,然后会按照一定频率将其刷新到redo log文件。
|
||||
|
||||
redo log缓冲区大小并不需要很大,通常每隔1s会将redo log buffer中的内容刷新到文件中。`innodb_log_buffer_size`负责控制该缓冲区域大小,该参数默认值为`8M`。(mysql 8中实际测试为`16M`)
|
||||
|
||||
redo log buffer在如下场景下会被刷新到文件中:
|
||||
- master thread每秒将缓冲刷新到磁盘文件中
|
||||
- 每个事务提交时都会将redo log buffer刷新到磁盘文件中
|
||||
- 当redo log buffer剩余空间小于一般时,redo log buffer刷新到磁盘文件中
|
||||
|
||||
|
||||
Reference in New Issue
Block a user