共计 2014 个字符,预计需要花费 6 分钟才能阅读完成。
三种 page、三种 list、LRU 控制调优
一、innodb buffer pool 中的三种页
1、free page:从未用过的页
2、clean page:干净的页,数据页的数据和磁盘一致
3、dirty page:脏页
SQL 执行需求:
1、找 free 页
2、刷新脏页
1、这个页不是热的数据页 (刷冷页)
2、这个页最早修改时间 (刷修改时间比较早的页,有可能是热页),方便日志文件的覆盖
3、覆盖冷的 clean 页
为了实现上述需求,innodb 用到链表技术 (每种链表一种作用,链的存在意义是为了遍历)。
二、innodb buffer pool 中的三种链
1、free list:将 free 数据页使用链表链起来
数据库刚启动的时候,lru 列表为空,此时需要用到的时候直接将 free 列表中的页删除,在 lru 列表中增加相应的页,维持页数守恒。
2、lru list:根据冷热将 clean、dirty 链起来
least recent used(最近最少使用)
1、“中点插入策略”
2、回写尽量回写冷的脏块
3、覆盖尽量覆盖冷的脏块
LRU 标准算法:
1)3/ 8 的 list 信息是作为 old list,这些信息是被驱逐的对象。
2)list 的中点就是我们所谓的 old list 头部和 new list 尾部的连接点,相当于一个界限。
3)新数据的读入首先会插入到 old list 的头部。
4)如果是 old list 的数据被访问到了,这个页信息就会变成 new list,变成 young page,就会将数据页信息移动到 new sublist 的头部。
5)在数据库的 buffer pool 里面,不管是 new sublist 还是 old sublist 的数据如果不会被访问到,最后都会被移动到 list 的尾部作为牺牲者。
3、flush list:将页按照最早脏时间链起来
flush list 中的也全都是脏页,刷盘即将 flush list 中的脏页刷新回磁盘中。
1、将非常旧的脏块回写到磁盘,按照新旧回写数据页;
2、因为是从最早脏的块开始刷,这样 logfile 里的对应的日志就可以被覆盖了。
Q:为什么需要这三种链?
A:
因为在 innodb 缓冲池中,内存管理如下:
1、需要经常找 free 空闲数据块:free list。
2、需要经常找冷的数据块:lru list(最近最少使用,根据冷热链起来)。
3、需要知道哪些数据块是比较早脏的,flush list:我们要覆盖旧的 logfile,就需要系统将这些 logfile 对应的脏块,即将 flush list 链上的脏页往磁盘上刷,(批量往磁盘写的时候,不如刷脏页)。
三、LRU 冷热区控制及调整
1、设置冷热分界线:innodb_old_blocks_pct
2、成为热块的所需时间:innodb_old_blocks_time
MySQL> show variables like ‘%old_blocks%’;
+————————+——-+
| Variable_name | Value |
+————————+——-+
| innodb_old_blocks_pct | 37 |
| innodb_old_blocks_time | 1000 |
+————————+——-+
2 rows in set (0.01 sec)
通过 innodb_old_blocks_pct 参数值得设定分为两部分:一是存放长时间未被访问的数据页,二是存放最近被访问的数据页。靠近 LRU 链表头部的数据页表示最近经常被访问,靠近尾部表示数据页长期未被访问,这两个部分的交汇处称为 midpoint,即 innodb_old_blocks_pct 这个点的设置。默认是 37%,最小是 5,最大是 95;如果内存比较大的话,可以将这个数值调低,通常会调成 20,也就是说 20% 的是冷数据块。目的是为了保护热区数据不被刷出内存。
通过 innodb_old_blocks_time 参数来控制成为热数据的所需时间,默认是 1000ms,也就是 1s,也就是数据在 1s 内没有被刷走,就调入热区。
3、LRU 冷热数据的监控
mysql> show engine innnodb status\G
……
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
1、数据页从冷到热,称为 young;not young 就是数据在没有成为热数据情况下就被刷走的量 (累计值)。
2、non-youngs/s,这个数值如果很高,一般情况下就是系统存在严重的全表扫描,自然意味着很高的物理读。
3、youngs/s,如果这个值相对较高,最好增加一个 innodb_old_blocks_time,降低 innodb_old_blocks_pct,保护热数据。
: