文章目录5. InnoDB 内存结构5.3 缓冲池 - Buffer Pool5.3.3 缓冲池中的页是如何进行管理的5.3.3.1 内存中有这么多数据页如何快速找到目标页5.3.3.2 缓冲池中的数据放不下了怎么办5.3.4 缓冲池采用哪种淘汰策略是如何实现的5.3.4.1 为什么要把页插入到中间而不是直接插入到新子列表的头部5.3.5 怎么查看当前缓冲池的信息5. InnoDB 内存结构5.3 缓冲池 - Buffer Pool5.3.3 缓冲池中的页是如何进行管理的当缓冲池初始化完成后缓冲池中的数据页只是被分配了内存空间并没有真实的数据空闲页当用户进行数据查询时真实的数据从磁盘加载到内存中并分配一个内存中的数据页这时内存中数据页的状态从空间变成了有实际的数据已使用页干净页当用户修改数据时并不是直接修改磁盘中的数据页而是修改内存中数据页中的数据页这时内存中数据页的状态从有实际数据变成了被修改。已修改页需要落盘脏页在缓冲池中采用三个链表维护内存页这三个链表也对应着内存中页的三种状态分别是Free未使用的页也可以称做空闲页Clean已使用但未修改的页也可以称做干净页Dirty已修改的页也可以称做脏页。对应的三个链表分别是Free List 、 LRU List和Flush List:Free List只管理Free页LRU List管理Clean页和Dirty页Flush List只管理Dirty页如下图所示Free List管理着空闲的也就是没有被使用的内存页当执行查询操作时如果对应的页已经在buffer pool中则直接返回数据如果没有且Free List不为空则从磁盘中查询对应的数据并存到Free List的某一页中然后把这个页从Free List中移除并放入LRU List中。LRU List管理所有从磁盘中读取的数据页包括未被修改的和已被修改的数据页并根据LRU算法对链表中的页节点进行维护与淘汰。当数据库刚启动时LRU List是空的这时从内存中申请到的页都存放在Free List中当数据从磁盘读取到缓冲池时首先从Free List中查找是否有可用的空闲页如果有则把该页从Free List中删除并加入到LRU List如果没有则根据LRU算法淘汰LRU List末尾的页并将该内存空间分配给新数据页Flush List当LRU List中的页被修改后会被标识为脏页(Dirty page)并把脏页加入到Flush List中在这种情况下数据库会通过刷盘机制把Flush List中的脏页刷回磁盘从内存写到外存Flush List是一个专门用来管理脏页的列表。脏页既存在于LRU List中也存在于Flush List中LRU List用来管理缓冲池中页的可用性Flush List用来管理要被刷回磁盘的页二者互不影响。Flush List中的脏页在执行了刷盘操作后会将空间还给Free List。总结每个缓冲池都采用三个链表维护内存页这三个链表也对应着内存中页的三种状态分别是Free未使用的页也可以称做空闲页Clean已使用但未修改的页也可以称做干净页Dirty已修改的页也可以称做脏页。5.3.3.1 内存中有这么多数据页如何快速找到目标页首先第一种办法是通过遍历这种做法显示不能满足性能要求InnoDB采用的是Page Hash的方式也就是每当把磁盘中数据页加载到内存时用数据页的表空间Id和页号做为Key当前页在内存中的地址做为Value保存起来每次查询时就可以通过Key快速定位到目标页如果内存中没有目标页则从磁盘中获取。5.3.3.2 缓冲池中的数据放不下了怎么办InnoDB根据根据自身的实际场景使用淘汰策略来淘汰相应的数据页从而释放出内存空间以便新的数据页加载到内存中。5.3.4 缓冲池采用哪种淘汰策略是如何实现的缓冲池淘汰策略采用变形的最近最少使用(LRU)算法(在原来LRU算法的基础做了修改)以下出现的LRU算法指的是LRU变形算法。缓冲池使用LRU算法管理链表当有新页面添加到缓冲池时最近最少使用的页将被淘汰并将新页添加到列表的中间这种中点插入策略将列表视为两个子列表链表头部是存放最近访问的新页(年轻页)子列表链表尾部是存放最近较少访问的旧页子列表。如下图所示经常使用的页保存在新子列表中较少使用的页保存在旧子列表中随着时间的推移旧子列表中的页将会逐渐被淘汰。默认情况下算法的执行过程如下缓冲池总容量的5/8用于新子列表3/8用于旧子列表列表的中间插入点是新子列表的尾部与旧子列表头部的交界当一个页被读入缓冲池时首先插入到中点做为旧子列表的头节点当访问的页在旧子列表中时把被访问的页移动到新子列表的头部使其成为 “新” 页数据库运行的过程中缓冲池中被访问页面的位置不断更新未访问的页面向列表的尾部移动从而逐渐变老 最终超出缓冲池容量的页从旧子列表的尾部被淘汰。总结缓冲池淘汰策略采用变形的最近最少使用(LRU)算法5.3.4.1 为什么要把页插入到中间而不是直接插入到新子列表的头部因为InnoDB在读取页时可能会发生预读预读的意思是InnoDB根据当前访问的记录自动推断后面可能会访问哪个页并把他们提前加载到内存中从而提高以后查询的效率预读的页以并不一定会被真正的读取从中间点插入可以使其尽快被淘汰。因为有的预读的部分可能用不到如果放到前面那么那些读不到的就会占用之前读到的应占据的位置。放到中间可以保证之前读到的应占据的位置还在那里哪些用不到的部分往后直到回收。也就是说中间插入的新数据被使用部分前移到新子列表不使用部分默认就在旧子列表。5.3.5 怎么查看当前缓冲池的信息通过使用SHOW ENGINE InnoDB STATUS访问InnoDB标准监视器输出中BUFFER POOL AND MEMORY部分查看有关缓冲池的指标。缓冲池指标位于InnoDB标准监视器输出的缓冲池和内存部分:mysql SHOW ENGINE INNODB STATUS\G *************************** 1. row *************************** Type: InnoDB Name: Status: .......省略 ---------------------- BUFFER POOL AND MEMORY # 缓冲池和内存 ---------------------- Total large memory allocated 0 # 为缓冲池分配的总内存以字节为单位 Dictionary memory allocated 634151 # 为InnoDB数据字典分配的总内存以字节为单位 Buffer pool size 8192 # 分配给缓冲池的总页大小 Free buffers 6917 # 缓冲池空闲列表的总页大小 Database pages 1270 # 缓冲池LRU列表的总分页大小 Old database pages 487 # 缓冲池旧子列表的总页大小 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 1094, created 176, written 736 0.00 reads/s, 0.00 creates/s, 0.00 writes/s No buffer pool page gets since the last printout Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s LRU len: 1270, unzip_LRU len: 0 I/O sum[0]:cur[0], unzip sum[0]:cur[0] -------------- ROW OPERATIONS -------------- 0 queries inside InnoDB, 0 queries in queue 0 read views open inside InnoDB Process ID2658071, Main thread ID139983131321920 , statesleeping Number of rows inserted 75, updated 0, deleted 0, read 51 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s Number of system rows inserted 166, updated 409, deleted 8, read 6079 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s ---------------------------- END OF INNODB MONITOR OUTPUT 1 row in set (0.00 sec) mysqlInnoDB缓冲池指标如下以供参考小结缓冲池是用来缓存各种数据最主要的就是缓存从磁盘中加载的数据页从而提升效率缓冲池为了方便数据组织定义了不同的数据结构包括Instances实例Chunk块其中Buffer Pool中包含至少一个InstancesInstances包含至少一个Chunk块Chunk管理若干个从磁盘加载到内存的Page数据页缓冲池能过三个链表管理内存中的数据页分别是Free List 、 LRU List和Flush List缓冲池淘汰策略采用变形的最近最少使用(LRU)算法
【MySQL高阶】18.缓冲池页管理
文章目录5. InnoDB 内存结构5.3 缓冲池 - Buffer Pool5.3.3 缓冲池中的页是如何进行管理的5.3.3.1 内存中有这么多数据页如何快速找到目标页5.3.3.2 缓冲池中的数据放不下了怎么办5.3.4 缓冲池采用哪种淘汰策略是如何实现的5.3.4.1 为什么要把页插入到中间而不是直接插入到新子列表的头部5.3.5 怎么查看当前缓冲池的信息5. InnoDB 内存结构5.3 缓冲池 - Buffer Pool5.3.3 缓冲池中的页是如何进行管理的当缓冲池初始化完成后缓冲池中的数据页只是被分配了内存空间并没有真实的数据空闲页当用户进行数据查询时真实的数据从磁盘加载到内存中并分配一个内存中的数据页这时内存中数据页的状态从空间变成了有实际的数据已使用页干净页当用户修改数据时并不是直接修改磁盘中的数据页而是修改内存中数据页中的数据页这时内存中数据页的状态从有实际数据变成了被修改。已修改页需要落盘脏页在缓冲池中采用三个链表维护内存页这三个链表也对应着内存中页的三种状态分别是Free未使用的页也可以称做空闲页Clean已使用但未修改的页也可以称做干净页Dirty已修改的页也可以称做脏页。对应的三个链表分别是Free List 、 LRU List和Flush List:Free List只管理Free页LRU List管理Clean页和Dirty页Flush List只管理Dirty页如下图所示Free List管理着空闲的也就是没有被使用的内存页当执行查询操作时如果对应的页已经在buffer pool中则直接返回数据如果没有且Free List不为空则从磁盘中查询对应的数据并存到Free List的某一页中然后把这个页从Free List中移除并放入LRU List中。LRU List管理所有从磁盘中读取的数据页包括未被修改的和已被修改的数据页并根据LRU算法对链表中的页节点进行维护与淘汰。当数据库刚启动时LRU List是空的这时从内存中申请到的页都存放在Free List中当数据从磁盘读取到缓冲池时首先从Free List中查找是否有可用的空闲页如果有则把该页从Free List中删除并加入到LRU List如果没有则根据LRU算法淘汰LRU List末尾的页并将该内存空间分配给新数据页Flush List当LRU List中的页被修改后会被标识为脏页(Dirty page)并把脏页加入到Flush List中在这种情况下数据库会通过刷盘机制把Flush List中的脏页刷回磁盘从内存写到外存Flush List是一个专门用来管理脏页的列表。脏页既存在于LRU List中也存在于Flush List中LRU List用来管理缓冲池中页的可用性Flush List用来管理要被刷回磁盘的页二者互不影响。Flush List中的脏页在执行了刷盘操作后会将空间还给Free List。总结每个缓冲池都采用三个链表维护内存页这三个链表也对应着内存中页的三种状态分别是Free未使用的页也可以称做空闲页Clean已使用但未修改的页也可以称做干净页Dirty已修改的页也可以称做脏页。5.3.3.1 内存中有这么多数据页如何快速找到目标页首先第一种办法是通过遍历这种做法显示不能满足性能要求InnoDB采用的是Page Hash的方式也就是每当把磁盘中数据页加载到内存时用数据页的表空间Id和页号做为Key当前页在内存中的地址做为Value保存起来每次查询时就可以通过Key快速定位到目标页如果内存中没有目标页则从磁盘中获取。5.3.3.2 缓冲池中的数据放不下了怎么办InnoDB根据根据自身的实际场景使用淘汰策略来淘汰相应的数据页从而释放出内存空间以便新的数据页加载到内存中。5.3.4 缓冲池采用哪种淘汰策略是如何实现的缓冲池淘汰策略采用变形的最近最少使用(LRU)算法(在原来LRU算法的基础做了修改)以下出现的LRU算法指的是LRU变形算法。缓冲池使用LRU算法管理链表当有新页面添加到缓冲池时最近最少使用的页将被淘汰并将新页添加到列表的中间这种中点插入策略将列表视为两个子列表链表头部是存放最近访问的新页(年轻页)子列表链表尾部是存放最近较少访问的旧页子列表。如下图所示经常使用的页保存在新子列表中较少使用的页保存在旧子列表中随着时间的推移旧子列表中的页将会逐渐被淘汰。默认情况下算法的执行过程如下缓冲池总容量的5/8用于新子列表3/8用于旧子列表列表的中间插入点是新子列表的尾部与旧子列表头部的交界当一个页被读入缓冲池时首先插入到中点做为旧子列表的头节点当访问的页在旧子列表中时把被访问的页移动到新子列表的头部使其成为 “新” 页数据库运行的过程中缓冲池中被访问页面的位置不断更新未访问的页面向列表的尾部移动从而逐渐变老 最终超出缓冲池容量的页从旧子列表的尾部被淘汰。总结缓冲池淘汰策略采用变形的最近最少使用(LRU)算法5.3.4.1 为什么要把页插入到中间而不是直接插入到新子列表的头部因为InnoDB在读取页时可能会发生预读预读的意思是InnoDB根据当前访问的记录自动推断后面可能会访问哪个页并把他们提前加载到内存中从而提高以后查询的效率预读的页以并不一定会被真正的读取从中间点插入可以使其尽快被淘汰。因为有的预读的部分可能用不到如果放到前面那么那些读不到的就会占用之前读到的应占据的位置。放到中间可以保证之前读到的应占据的位置还在那里哪些用不到的部分往后直到回收。也就是说中间插入的新数据被使用部分前移到新子列表不使用部分默认就在旧子列表。5.3.5 怎么查看当前缓冲池的信息通过使用SHOW ENGINE InnoDB STATUS访问InnoDB标准监视器输出中BUFFER POOL AND MEMORY部分查看有关缓冲池的指标。缓冲池指标位于InnoDB标准监视器输出的缓冲池和内存部分:mysql SHOW ENGINE INNODB STATUS\G *************************** 1. row *************************** Type: InnoDB Name: Status: .......省略 ---------------------- BUFFER POOL AND MEMORY # 缓冲池和内存 ---------------------- Total large memory allocated 0 # 为缓冲池分配的总内存以字节为单位 Dictionary memory allocated 634151 # 为InnoDB数据字典分配的总内存以字节为单位 Buffer pool size 8192 # 分配给缓冲池的总页大小 Free buffers 6917 # 缓冲池空闲列表的总页大小 Database pages 1270 # 缓冲池LRU列表的总分页大小 Old database pages 487 # 缓冲池旧子列表的总页大小 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 1094, created 176, written 736 0.00 reads/s, 0.00 creates/s, 0.00 writes/s No buffer pool page gets since the last printout Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s LRU len: 1270, unzip_LRU len: 0 I/O sum[0]:cur[0], unzip sum[0]:cur[0] -------------- ROW OPERATIONS -------------- 0 queries inside InnoDB, 0 queries in queue 0 read views open inside InnoDB Process ID2658071, Main thread ID139983131321920 , statesleeping Number of rows inserted 75, updated 0, deleted 0, read 51 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s Number of system rows inserted 166, updated 409, deleted 8, read 6079 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s ---------------------------- END OF INNODB MONITOR OUTPUT 1 row in set (0.00 sec) mysqlInnoDB缓冲池指标如下以供参考小结缓冲池是用来缓存各种数据最主要的就是缓存从磁盘中加载的数据页从而提升效率缓冲池为了方便数据组织定义了不同的数据结构包括Instances实例Chunk块其中Buffer Pool中包含至少一个InstancesInstances包含至少一个Chunk块Chunk管理若干个从磁盘加载到内存的Page数据页缓冲池能过三个链表管理内存中的数据页分别是Free List 、 LRU List和Flush List缓冲池淘汰策略采用变形的最近最少使用(LRU)算法