mysql的LRU队列详解

       MySQL的缓冲池(innodb_buffer_pool_instances,innodb_buffer_pool_size)是通过LRU算法来进行管理的。即最频繁使用的页在LRU列表的最前端,而最少使用的页在LRU列表的尾端。当缓冲池不能存放新读取到的页时,将首先释放LRU列表尾端的页。

      在INNODB引擎中,缓冲池页的大小默认为16KB。

      在INNODB引擎中,有一个midpoint位置。新读取到的页,虽然是最新访问的页,但并不直接放到LRU队列的首部,而是放到LRU列表的midpoint位置。

     midpoint位置是通过参数innodb_old_blocks_pct来控制的。表示新读取的页插入到LRU列表尾端的37%的位置。在INNODB中,把midpoint之后的列表称为old列表,之前的列表称为new列表。可以简单的理解为new列表中的页都是活跃的热点数据。

       为什么不把读入的页直接放入LRU队列的首部呢?是因为如此做可能会把大量频繁使用的数据页换出LRU队列,带来再次磁盘读取的IO压力。

      数据页在midpoint位置,什么情况下会进入NEW列表呢?是通过参数innodb_old_blocks_time来控制的。该参数表示,页读取到midpoint位置后需要等多久才会被加入到LRU队列的热端。

重新调整两个参数的值:

mysql> set  global  innodb_old_blocks_pct=20;

mysql> set global innodb_old_blocks_time=500;

数据页在LRU队列上的移动规则:

       当数据库刚启动的时候,LRU列表是空的,所有的页都放在FREE列表中。当需要重缓冲池中分页时,首先从FREE列表中查找是否有可用的空闲页,如果有则将该页从FREE列表中删除,放入LRU列表中;如果没有,则根据LRU算法,淘汰LRU列表尾部的页,将该内存空间分配给新的页。

      当页从LRU列表的OLD部分加入到NEW部分时,称此时发生的操作为page made young;如果因为innodb_old_blocks_time的设置导致页没有从old部分移动到new部分的操作,称为page not made young。

通过命令 show engine innodb status\G;可以查看LRU队列的使用情况:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 140621
Buffer pool size   8192
Free buffers       7912
Database pages     280
Old database pages 0
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 245, created 35, written 40
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 988 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 280, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

Buffer pool size:表示当前缓冲池中内存页的数量,内存池的大小=Buffer pool size*16KB

Free buffers:表示当前FREE列表中页的数量;

Database pages:LRU列表中页的数量;

Modified db pages:显示了脏页的数量;

Pages made young 0, not young 0  :表示是否发生了页在LRU队列上的移动;

0.00 youngs/s, 0.00 non-youngs/s:表示每秒两类操作发生的次数;

Buffer pool hit rate:表示缓冲池的命中率,正常情况下命中率如果低于95%,则需要观察是否因为全表扫描引起了LRU队列被污染的问题

Per second averages calculated from the last 18 seconds:表示show engine innodb status\G;打印的是过去18秒内的数据库状态。

观察缓冲池的运行状态:

select pool_id,hit_rate,pages_made_young,pages_not_made_young from information_schema.innodb_buffer_pool_stats\G;

 查看LRU列表中每个页的具体信息:

select table_name,space,page_number,page_type from information_schema.innodb_buffer_page_lru where space=1;

脏页的刷新:

         脏页既存在于LRU列表中,也存在于Flush列表中。LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘,二者互不影响。

猜你喜欢

转载自blog.csdn.net/David_ifx/article/details/120926064
LRU