当前位置: 首页 > news >正文

【MySQL高阶】18.缓冲池页管理

文章目录

  • 5. InnoDB 内存结构
    • 5.3 缓冲池 - Buffer Pool
      • 5.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 Pool

5.3.3 缓冲池中的页是如何进行管理的?

  • 当缓冲池初始化完成后,缓冲池中的数据页只是被分配了内存空间,并没有真实的数据(空闲页)

    当用户进行数据查询时真实的数据从磁盘加载到内存中并分配一个内存中的数据页,这时内存中数据页的状态从空间变成了有实际的数据;(已使用页,干净页)

    当用户修改数据时,并不是直接修改磁盘中的数据页,而是修改内存中数据页中的数据页,这时内存中数据页的状态从有实际数据变成了被修改。(已修改页,需要落盘,脏页)

  • 在缓冲池中采用三个链表维护内存页,这三个链表也对应着内存中页的三种状态,分别是:

    • Free未使用的页,也可以称做空闲页;
    • Clean已使用但未修改的页,也可以称做干净页;
    • Dirty已修改的页,也可以称做脏页。
  • 对应的三个链表分别是Free List 、 LRU ListFlush 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 ID=2658071, Main thread ID=139983131321920 , state=sleeping 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) mysql>

InnoDB缓冲池指标如下,以供参考:

小结

  1. 缓冲池是用来缓存各种数据,最主要的就是缓存从磁盘中加载的数据页,从而提升效率
  2. 缓冲池为了方便数据组织定义了不同的数据结构,包括Instances实例,Chunk块,其中Buffer Pool中包含至少一个InstancesInstances包含至少一个Chunk块,Chunk管理若干个从磁盘加载到内存的Page数据页
  3. 缓冲池能过三个链表管理内存中的数据页,分别是Free List 、 LRU ListFlush List
  4. 缓冲池淘汰策略采用变形的最近最少使用(LRU)算法
http://www.jsqmd.com/news/938959/

相关文章:

  • 零基础也能搭建:三步拥有你的专属AI股票分析平台
  • 【Redis从入门到精通】第35篇:Redis为什么这么快——单线程也能称王的秘密
  • 浏览器音乐解锁工具:3分钟解决你的加密音乐播放难题
  • 2026年GEO源码服务商选型深度评测与避坑指南 - 品牌报告
  • 焦作母婴除甲醛CMA甲醛检测治理公司2026深度测评:森氧家环保稳居榜首 - 五金回收
  • 【Claude博弈论实战指南】:20年AI架构师亲授3大经典场景建模方法与避坑清单
  • 2026年想找有社区交流功能的手机阅读器?这些选择别错过!
  • 2026年薪酬设计五步法:从零搭建公平激励体系
  • 【Redis从入门到精通】第36篇:Redis客户端属性大揭秘——一个连接背后有多少状态
  • 葫芦岛母婴除甲醛CMA甲醛检测治理公司深度测评:清醛卫士稳居榜首 - 五金回收
  • Windows Defender完全移除终极指南:专业级系统性能优化与安全组件深度清理
  • 3个简单步骤彻底解决魔兽争霸III现代化难题:WarcraftHelper完全指南
  • 【顶刊】基于ESO+MFPCC+ADRC,二阶三阶ESO扩展状态观测器的PMSM驱动器无模型预测电流电机控制算法
  • 深度实战:构建79万条中文医疗对话数据集的完整指南
  • 【Redis从入门到精通】第37篇:Redis服务器启动全流程——从redis-server到ready to accept
  • 深度解析:2026年现阶段山东不错的电线杆制造厂选哪家 - 2026年企业资讯
  • 标注软件WPF-LabelImg的使用教程
  • 基于树莓派与电子墨水屏的慢速电影播放器DIY全攻略
  • WarcraftHelper完整使用教程:魔兽争霸3性能优化终极指南
  • 打破音乐枷锁:3分钟掌握开源音频解密核心技术
  • 给物理模拟新手的Geant4保姆级入门:从第一个例子到看懂运行日志
  • Linux 组调度的 cfs_bandwidth 结构体:带宽控制的核心配置
  • 【Redis从入门到精通】第38篇:serverCron——Redis的“心跳“定时任务干了哪些活
  • 湘潭CMA甲醛检测治理公司深度测评:绿居净环保稳居榜首 - 五金回收
  • AI | ollama - [入门]
  • 旧项目安装QtFusion找不到IMcore:补wheel依赖还是迁移VibeFlux
  • 告别模板化论文困局:okbiye 分层式毕设创作体系,从资料上传到终稿排版全链路落地
  • 基于LM324运放的土壤湿度监测电路设计与实践
  • BetterGI AI自动化游戏辅助工具完整教程:从新手到专家的原神自动化指南
  • STM32F103硬件SPI直驱GC9A01芯片1.28寸240×240 TFT屏,含GUI与测试例程