爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

      首页 知识中心 数据库 文章详情页

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

      2023-06-14 09:13:23 阅读次数:445

      CPU,MySQL,磁盘

      1.MySQL是如何读取记录的——缓存的重要性

        对于使用InnoDB作为存储引擎的表来说,不管是用于存储用户数据的索引(包括聚集索引和非聚集索引),还是各种系统数据,都是以页的形式存放在磁盘上的。而CPU与内存的交互远远快于与磁盘的交互,所以InnoDB存储引擎在处理客户端的请求时,如果需要访问某个页的数据,就会把完整的页中的数据全部加载到内存中。也就是说,即使我们只需要访问一个页的一条记录,也需要先把整个页的数据加载到内存中。

        将整个页加载到内存中后就可以进行读写访问了,在进行完读写访问之后并不着急把该页对应的内存空间释放掉,而是将其缓存起来,这样下次有请求再次访问该页面时,就可以省去磁盘I/O的开销了。


      2. InnoDB的Buffer Pool

      2.1 什么是Buffer Pool

        为了缓存磁盘中的页,在MySQL服务器启动的时候就向操作系统申请了一片连续的内存,并给这片内存起了个名——Buffer Pool(缓冲池)。默认情况下Buffer Pool只有128M大小。

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        innodb_buffer_pool_size的单位是字节,134217728 Byte=128MB

        如果你想修改大小,可以在启动服务器的时候配置innodb_buffer_pool_size参数的值,它表示Buffer Pool的大小,就像这样:

      [server]
      innodb_buffer_pool_size = 268435456

        上面指定Buffer Pool大小是256M,注意,Buffer Pool不能太小,最小值是5MB,即使innodb_buffer_pool_size的值小于5MB,也会被自动设置成5MB

      2.2 Buffer Pool的内部结构

        Buffer Pool对应的一片连续的内存被划分为若干个页,页大小默认是16KB。我们前文又说过,页是磁盘与内存之间交互的基本单位,为了将磁盘中的页和Buffer Pool中的页区分开,我们这里把Buffer Pool中的页称为缓存页。

        为了更好的管理这些在Buffer Pool中的缓存页,InnoDB在每一个缓存页都创建了一些控制信息,这些控制信息包括该页所属的表空间编号、页号、缓存页在Buffer Pool中的地址、链表节点信息等等。

        每个缓存页对应的控制信息占用的内存大小是相同的,我们就把每个页对应的控制信息占用的一块内存称为一个控制块,控制块和缓存页是一一对应的,它们都被存放到 Buffer Pool 中,其中控制块被存放到 Buffer Pool 的前边,缓存页被存放到 Buffer Pool 后边,所以整个Buffer Pool对应的内存空间看起来就是这样的:

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        细心的小伙伴会发现,上图的控制块和缓存页之间还有个碎片。因为每一个控制块都对应一个缓存页,那在分配足够多的控制块和缓存页后,剩余的那点儿空间可能不够一对控制块和缓存页的大小,自然就用不到了,这个用不到的内存空间就被称为碎片。当然,如果你把Buffer Pool的大小设置的刚刚好的话,也可能不会产生碎片。

        注意:在DEBUG模式下,每个控制块大约占用缓存页大小的5%(非DEBUG模式下会更小一点),在MySQL 5.7.22这个版本的DEBUG模式下,每个控制块占用的大小是808字节。而我们设置的innodb_buffer_pool_size并不包含这部分控制块占用的内存空间大小,也就是说InnoDB在为Buffer Pool向操作系统申请连续的内存空间时,这片连续的内存空间一般会比innodb_buffer_pool_size的值大5%左右。

      2.3 free链表

        当我们最初启动MySQL服务器的时候,需要完成对Buffer Pool的初始化过程,就是先向操作系统申请Buffer Pool的内存空间,然后把它划分成若干对控制块和缓存页的位置(用来缓存后续从磁盘读取的页)。但是此时并没有真实的磁盘页被缓存到Buffer Pool中(因为还没有用到),下次查询某条记录时,如果Buffer Pool中没有这个磁盘页,那么包含这条记录的磁盘页就会被缓存到Buffer Pool中。

        问题来了,从磁盘上读取一个页到Buffer Pool中的时,该放到哪个缓存页的位置呢?怎么知道Buffer Pool中哪些缓存页是空闲的,哪些已经被使用了呢?所以需要记录一下Buffer Pool中哪些缓存页是可用的,这个时候控制块就派上大用场了——我们可以把所有空闲的缓存页对应的控制块作为一个节点放到一个链表中,这个链表也可以被称作free链表(或者说空闲链表)。刚刚完成初始化的Buffer Pool中所有的缓存页都是空闲的,所以每一个缓存页对应的控制块都会被加入到free链表中,假设该Buffer Pool中可容纳的缓存页数量为n,那增加了free链表的效果图就是这样的:

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        为了管理好这个free链表,特意为这个链表定义了一个基节点,里边儿包含着链表的头节点地址、尾节点地址以及当前链表中节点的数量等信息。这里需要注意的是,链表的基节点占用的内存空间并不包含在为Buffer Pool申请的一大片连续内存空间之内,而是单独申请的一块内存空间。

        链表基节点占用的内存空间并不大,在MySQL 5.7.22中,每个基节点只占用40字节,后面会介绍的flush链表、LRU链表的基节点也是一样,它们的基节点在内存分配方式上与free链表的基节点一样,都是一块单独申请的40字节的内存空间,并不包含在为Buffer Pool申请的一大片连续内存空间之内。

        每当需要从磁盘中加载一个页到Buffer Pool中时,就从free链表中取一个空闲的缓存页,并且把该缓存页对应的控制块的信息填上(就是该页所在的表空间、页号之类的信息),然后把该缓存页对应的free链表节点从链表中移除,表示该缓存页已经被使用了。

        综上所述,free链表是干什么的?

        free链表是用来记录Buffer Pool中哪些缓存页是空闲的,空闲的缓存页对应的控制块就是free链表中的节点。有了空闲的缓存页,才能将读取的磁盘页缓存起来。

      2.4 如何知道磁盘页在Buffer Pool是否已存在——缓存页的hash

        当我们需要访问某个页中的数据时,就会把该页从磁盘加载到Buffer Pool中,如果该页已经在Buffer Pool中的话就不用从磁盘读取了,这样可以加快速度。

        怎么知道该页在不在Buffer Pool中呢?总不能依次遍历Buffer Pool中各个缓存页吧?其实是根据表空间号 + 页号来定位一个页的,也就相当于表空间号 + 页号是一个key,缓存页就是对应的value,要通过一个key来找一个value,哈希表就能解决 。

        你查找这个表,表空间号一定知道,关于页号查找过程,下面马上会讲。

      补充知识:

      • 表空间中的每一个页都对应着一个页号,也就是FIL_PAGE_OFFSET,我们可以通过这个页号在表空间中快速定位到指定的页面,这个页号由4个字节组成,也就是32个比特位,所以一个表空间最多可以拥有2³²个页,如果按照页的默认大小16KB来算,一个表空间最多支持64TB的数据。表空间的第一个页的页号为0,之后的页号分别是1,2,3...依此类推

        写到这里,我自己也在思考一个问题,当sql需要查询某条记录时,首先会去判断这条记录所属的页是在磁盘上还是已经被加载到内存中的Buffer Pool,具体过程是怎么样的?

      • 1.sql当从磁盘中读取一页到内存的时候,页号和表空间号就已经知道了(页结构的File Header部分存储页的各种状态信息,其中有2个状态变量这里要关注。FIL_PAGE_OFFSET就是记录的页号,FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID就是表示页属于哪个表空间)
      • 2.再利用表空间号+页号就可以hash定位是否该页在Buffer Pool中,如果在Buffer Pool中,直接从Buffer Pool中返回记录,如果不在,那么从磁盘读取该页,然后缓存到Buffer Pool,再返回记录。

        如果你不知道怎么从B+树查找记录对应的页,建议阅读我的前面的基础博文图文并茂说MySQL索引——入门进阶必备   简单描述一下怎么从B+树查找记录对应的页,直接从磁盘B+树的根节点往下找,利用二分缩小查找范围,最后到对应范围的页去进行槽点二分查找,确定这个页有没有这条记录,如果有,就直接返回这个页。

      总结一下:
        我们可以用表空间号 + 页号作为key,缓存页作为value创建一个哈希表,在需要访问某个页的数据时,先从哈希表中根据表空间号 + 页号看看有没有对应的缓存页,如果有,直接使用该缓存页就好,如果没有,那就从free链表中选一个控制块,找到对应的空闲缓存页,然后把磁盘中对应的页加载到该缓存页的位置。

      2.5 flush链表

        如果我们修改了Buffer Pool中某个缓存页的数据,它就和磁盘上的页不一致了,这样的缓存页也被称为脏页(dirty page)。当然,我们可以每当修改完某个缓存页时,就立即将其刷新到磁盘中对应的页上,但是频繁的往磁盘中写数据会严重的影响程序的性能。所以每次修改缓存页后,并不是立即把修改刷新到磁盘上,而是在未来的某个时间点进行刷新。

        但是,如果不立即将修改刷新到磁盘,那之后再刷新的时候我们怎么知道Buffer Pool中哪些页是脏页,哪些页从来没被修改过呢?总不能把所有的缓存页都刷新到磁盘上吧,假如Buffer Pool被设置的很大,那一次性刷新这么多数据岂不是要慢死!所以,我们不得不再创建一个存储脏页的链表,凡是被修改过的缓存页对应的控制块都会作为一个节点加入到这个链表中。因为这个链表节点对应的缓存页都是需要被刷新到磁盘上的,所以也叫flush链表。链表的构造和free链表差不多,那么对应的flush链表就长这样:

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

      综上所述,flush链表是用来干啥的?
        flush链表是一个存储脏页对应控制块的链表,被修改过的缓存页对应的控制块都会作为一个节点加入到这个链表中。如果一个缓存页是空闲的,那它肯定不可能是脏页。如果一个缓存页是脏页,那它肯定就不是空闲的。所以,某个缓存页对应的控制块不可能既是free链表的节点,又是flush链表的节点,只能二者居其一。

      2.6 LRU链表

      2.6.1 Buffer Pool不够怎么办

        Buffer Pool对应的内存大小毕竟是有限的,如果需要缓存的页占用的内存大小超过了Buffer Pool大小,这样该怎么办?当然是把某些旧的缓存页从Buffer Pool中移除,然后再把新的页放进来。应该移除哪些旧的缓存页吗?

        设计Buffer Pool的初衷就是想减少和磁盘的I/O,最好每次在访问某个页的时候它都已经被缓存到Buffer Pool中了。假设我们一共访问了n次页,页已在缓存中的次数除以n就是所谓的缓存命中率,缓存命中率当然是越高越好。 比如我们的微信最近聊天列表,排在前边的都是最近很频繁使用的,每聊天一次就将这个聊天会话项排在了最前面,假如最近聊天列表能容纳下的会话数有限,你是会把最近聊天很频繁的留下还是最近很少聊天的留下呢? 当然那些聊天少的就给移除了,Buffer Pool管理缓存页也是如此。

      2.6.2 简单的LRU链表

        当Buffer Pool中不再有空闲的缓存页时,就需要淘汰掉部分最近很少使用的部分缓存页。不过,我们怎么知道哪些缓存页最近频繁使用,哪些最近很少使用呢?

        我们可以再创建一个链表,和上面free链表和flush链表结构图类似,这个链表是为了按照最近最少使用的原则去淘汰缓存页的,所以这个链表可以被称为 LRU链表(Least Recently Used)。当需要访问某个页时,可以按照下面的方式处理LRU链表:

      • 如果该页不在Buffer Pool中,在把该页从磁盘加载到Buffer Pool中的缓存页时,就把该缓存页对应的控制块作为节点塞到LRU链表的头部。
      • 如果该页已经被加载到Buffer Pool中,则直接把该页对应的控制块移动到LRU链表的头部。

        也就是说,只要我们使用到某个缓存页,就把该缓存页对应的控制块调整到LRU链表的头部,这样LRU链表尾部就是最近最少使用的缓存页了。 所以当Buffer Pool中的空闲缓存页使用完时,到LRU链表的尾部找些缓存页对应的控制块,将这些控制块和对应缓存页淘汰就OK了。

      2.6.3 划分区域的LRU链表(内容难度提升 ↑)

        上面只是简单的LRU链表,用了没多长时间就会发现问题,因为存在这两种比较尴尬的情况:

      • 情况一:我们上面说过,只有当我们用到某个页时,才会将其从磁盘加载到Buffer Pool中,用不到则不加载。而InnoDB提供了预读(read ahead)的功能,所谓预读,就是InnoDB认为执行当前的请求时,可能会在后面读取某些页面,于是就预先把这些页面加载到Buffer Pool中。根据触发方式的不同,预读又可以细分为下边两种:
      • 线性预读:InnoDB提供了一个系统变量innodb_read_ahead_threshold,如果顺序访问了某个区(extent)的页面超过这个系统变量的值,就会触发一次异步读取下一个区中全部的页面到Buffer Pool的请求,注意异步读取意味着从磁盘中加载这些被预读的页面时,并不会影响到当前工作线程的正常执行。这个innodb_read_ahead_threshold系统变量的值默认是56,我们可以在服务器启动时通过启动选项来调整该值,或者在服务器运行过程中直接调整该系统变量的值,由于它是一个全局变量,因此要使用SET GLOBAL命令来修改。
      • 随机预读:如果Buffer Pool中已经缓存了某个区的13个连续的页面,不论这些页面是不是顺序读取的,都会触发一次异步读取本区中所有其的页面到Buffer Pool的请求。InnoDB同时提供了innodb_random_read_ahead系统变量,它的默认值为OFF,也就意味着InnoDB并不会默认开启随机预读的功能,如果想开启该功能,可以通过修改启动选项或者直接使用SET GLOBAL命令把该变量的值设置为ON。

      扩展了解:
        InnoDB是怎么实现异步读取的呢?在Windows或者Linux平台上,可能是直接调用操作系统内核提供的AIO接口,在其它类Unix操作系统中,使用了一种模拟AIO接口的方式来实现异步读取,其实就是让别的线程去读取需要预读的页面。

        InnoDB提供预读本来是想提高效率的,如果预读到Buffer Pool中的页用不到呢?原本这些预读的页的控制块先会放到LRU链表的头部,但是如果此时Buffer Pool的容量不大,而且很多预读的页面都没有用到的话,随着数据的不断读取,这就会导致LRU链表头部预读的缓存页控制块很快会到尾部,这意味着这些控制块和对应的缓存页很快会被淘汰掉,从而大大降低Buffer Pool命中率。

      • 情况二:如果写了一些需要全表扫描的查询语句(比如没有建立合适的索引或者没有WHERE子句的查询)。

        全表扫描意味着将访问该表的聚集索引的所有叶子结点对应的页(由于需要找到第一个叶子结点,首选从B+树的根一步步定位到第一个叶子结点的第一条记录,这个过程不得不访问少量的非叶子节点,这个细节问题大家可以注意一下。)!如果访问的页面特别多,而Buffer Pool又不能全部容纳它们的话,这就意味着需要将其他语句在执行过程中用到的页面移出Buffer Pool,之后在其他语句重新执行时,又需要将需要用到的页重新从磁盘加载到Buffer Pool中(这就像我在饭店吃饭吃了一半,忽然来了一群人把我的饭菜收走,然后把我从饭店赶了出去,等他们吃完后我又得进去重新点菜吃)

        我们在业务中一般对很大的表不会进行全表扫描,因为对很大的表进行全表扫描可能要把Buffer Pool中的缓存页换一次,这严重的影响到其他查询对 Buffer Pool的使用,从而大大降低了Buffer Pool命中率。

      综上所述,可能降低Buffer Pool命中率的两种情况如下:

      • 加载到Buffer Pool中的页不一定被用到;
      • 如果有非常多的使用频率偏低的页被同时加载到Buffer Pool时,则可能会把那些使用频率非常高的页从Buffer Pool中淘汰掉。

      因为有这两种情况的存在,InnoDB把这个LRU链表按照一定比例分成两截:

      • 一部分存储使用频率非常高的缓存页,所以这一部分链表也称为热数据,或者称为 young区域。
      • 另一部分存储使用频率不是很高的缓存页,这一部分链表也称为冷数据,或者称为 old区域。

      把示意图做了简化如下:

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        需要特别注意的是:我们是按照某个比例将LRU链表分成两半的,而不是某些节点固定位于young区域的,某些节点固定位于old区域的,随着程序的运行,某个节点所属的区域也可能发生变化。这个划分成两截的比例怎么确定呢?对于InnoDB存储引擎来说,我们可以通过查看系统变量innodb_old_blocks_pct的值来确定old区域在LRU链表中所占的比例,比方说这样:

      show variables like 'innodb_old_blocks_pct'

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        从结果可以看出来,默认情况下old区域在LRU链表中所占的比例是37%,也就是说old区域大约占LRU链表的3/8。这个比例我们是可以设置的,我们可以在启动服务器时修改innodb_old_blocks_pct启动选项来控制old区域在LRU链表中所占的比例,比方在配置文件中输入如下:

      [server]
      innodb_old_blocks_pct = 40

        这样我们在启动服务器后,old区域占LRU链表的比例就是40%。当然,在服务器运行期间也可以修改这个系统变量的值,不过需要注意的是,这个系统变量属于全局变量,所以我们要使用SET GLOBAL命令来修改:

      SET GLOBAL innodb_old_blocks_pct = 40;

        有了这个被划分成young和old区域的LRU链表之后,InnoDB就可以针对我们上边提到的两种可能降低Buffer Pool命中率的情况进行优化了。

      (下面的2条优化项有点难以理解,需要大家多读2遍)

      • 针对预读的页面的处理

        InnoDB规定,当磁盘上的某个页面在初次加载到Buffer Pool中的某个缓存页时,该缓存页对应的控制块会被放到old区域的头部。这样针对预读到Buffer Pool但不进行后续访问的页面就会被逐渐从old区域逐出,而不会影响young区域中被使用比较频繁的缓存页。

      • 全表扫描时,对短时间内访问大量使用频率非常低的页面进行优化

        InnoDB规定,每次去页面中读取一条记录时,都算是访问一次页面。

        在进行全表扫描时,首次被加载到Buffer Pool的页被放到了old区域的头部,而一个页面中可能会包含很多条记录,读取完某个页面的记录就相当于访问了这个页面好多次,并且这些记录顺序访问时间间隔非常短,也就是InnoDB会认为old区域短时间内某一页被多次访问了。

        这种情况是短时间内频繁访问同一页面,而后续不再访问。如果此时把这种页放到young区域的头部,会把那些真正使用频率比较高的页面给顶下去,这样会降低Buffer Pool命中率。(就像一个新玩具,前几天每天都玩,后续这个玩具放在一旁不再使用,那么不能认定你喜欢玩这个玩具)

        所以我们规定,计算上次访问old区域的时间戳和本次访问的时间戳如果小于某一时间间隔,该页面就不会被从old区域移动到young区域的头部,否则将它移动到young区域的头部。每次访问old区域后就刷新时间戳,方便下次计算时间间隔。

        上述的这个间隔时间是由系统变量innodb_old_blocks_time控制的,默认是1000 ms。

      show variables like 'innodb_old_blocks_time'

       

      细说MySQL中磁盘与CPU的交互——神秘的Buffer Pool

        对于从磁盘上被加载到LRU链表的old区域的某个页来说,如果第一次和最后一次访问该页面的时间间隔小于1s,那么该页是不会被加入到young区域的。很明显在一次全表扫描的过程中,多次访问一个页面(也就是读取同一页面中的多条记录)的时间不会超过1s,

        如果我们把innodb_old_blocks_time的值设置为0,那么每次我们访问一个页面时就会把该页面放到young区域的头部。

      综上所述
        正是因为将LRU链表划分为young和old区域这两个部分,又添加了innodb_old_blocks_time这个系统变量,预读机制和全表扫描造成的Buffer Pool命中率降低的问题才得到了遏制,因为用不到的预读页面以及全表扫描的页面都只会被放到old区域,而不影响young区域中的缓存页。

      2.6.4 进一步优化LRU链表

        对于young区域的缓存页来说,我们每次访问一个缓存页就要把它移动到LRU链表的头部,开销还是有点大,毕竟在young区域的缓存页都是高热度的页,也就是可能被经常访问的,这样频繁的对LRU链表进行节点移动操作不太好。

        为了解决这个问题其实我们还可以提出一些优化策略,比如某个缓存页对应的节点在young区域的前1/4时,再次访问该缓存页时也不会将其移动到LRU链表头部,这样就可以降低调整LRU链表的频率,从而提升性能。(你可以认为young区域的前1/4是超高热度的页,后3/4是普通热度的页,超高热度的页之间不必来回切换。)

      注意: 上面2.6.3介绍随机预读的时候提到,如果Buffer Pool中有某个区的13个连续页面就会触发随机预读,这其实是不严谨的,其实还要求这13个页面是超高热度的页面,也就是指的是这些页面在整个young区域的头1/4处。

        只要从磁盘中加载一个页面到Buffer Pool的一个缓存页中,该缓存页对应的控制块就会作为一个节点加入到LRU链表中,这样一来,该缓存页对应的控制块就不在free链表中了,flush链表中的节点(控制块)肯定也是LRU链表中的节点。


      文章参考自书籍《MySQL是怎样运行的》,后续本文将持续更新。

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/u_14973569/6422596,作者:砖业洋__,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Oracle系列之三:Oracle字符集

      下一篇:MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC

      相关文章

      2025-05-19 09:05:01

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      2025-05-19 09:05:01
      MySQL , Navicat , 解决 , 连接
      2025-05-19 09:04:38

      mysql只有在任务处于完成状态才能运行

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38
      MySQL , 任务 , 数据库 , 查询 , 状态
      2025-05-16 09:15:24

      MySQL 表的内外连接

      MySQL 表的内外连接

      2025-05-16 09:15:24
      MySQL , 显示 , 连接
      2025-05-14 10:03:13

      一步一步在linux上部署Oracle 11g R2 RAC 【1】

      一步一步在linux上部署Oracle 11g R2 RAC 【1】

      2025-05-14 10:03:13
      app , oracle , 主机名 , 磁盘
      2025-05-14 10:03:13

      MySQL 索引优化以及慢查询优化

      MySQL 是一种广泛使用的关系型数据库管理系统,因其性能优异和使用便捷而备受欢迎。然而,随着数据量的增长和查询复杂度的增加,性能瓶颈也变得越来越明显。

      2025-05-14 10:03:13
      MySQL , 优化 , 使用 , 性能 , 数据库 , 查询 , 索引
      2025-05-14 10:02:58

      Linux top 命令使用教程

      Linux top 是一个在Linux和其他类Unix 系统上常用的实时系统监控工具。它提供了一个动态的、交互式的实时视图,显示系统的整体性能信息以及正在运行的进程的相关信息。

      2025-05-14 10:02:58
      CPU , 信息 , 内存 , 占用 , 备注 , 进程
      2025-05-14 10:02:48

      SQL Server 事务日志体系结构1--基本术语

      事务包括对数据库的一次更改或一系列更改。它有一个明确开始和明确结束。开始时使用BEGIN TRANSACTION语句,或者SQL Server会自动为您开始一个事务。

      2025-05-14 10:02:48
      Server , SQL , 事务 , 数据库 , 日志 , 磁盘
      2025-05-14 09:51:21

      mysql数据库中decimal数据类型比较大小

      在MySQL中,DECIMAL数据类型用于存储精确的数值,它非常适合用于需要高精度计算的场景,如金融应用。当我们需要在MySQL数据库中比较DECIMAL类型数据的大小时,可以使用标准的比较运算符,如>, <, >=, <=, = 和 <>(或!=)。

      2025-05-14 09:51:21
      MySQL , SQL , 数据类型 , 查询 , 比较 , 示例
      2025-05-14 09:51:15

      mysql 语句如何优化

      MySQL语句的优化是一个复杂但重要的过程,因为它可以显著提高数据库的性能。

      2025-05-14 09:51:15
      JOIN , MySQL , 优化 , 使用 , 排序 , 查询 , 索引
      2025-05-13 09:53:23

      java检测当前CPU负载状态

      在Java中,直接检测CPU负载状态并不像在操作系统命令行中那样简单,因为Java标准库并没有直接提供这样的功能。

      2025-05-13 09:53:23
      CPU , 使用 , 命令 , 示例 , 获取 , 负载
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5249931

      查看更多

      最新文章

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      2025-05-19 09:05:01

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38

      MySQL 表的内外连接

      2025-05-16 09:15:24

      MySQL 索引优化以及慢查询优化

      2025-05-14 10:03:13

      mysql数据库中decimal数据类型比较大小

      2025-05-14 09:51:21

      mysql 语句如何优化

      2025-05-14 09:51:15

      查看更多

      热门文章

      Confluence 6 MySQL 输入你的数据库细节

      2023-04-27 08:03:27

      MySQL timestamp(3)问题

      2023-04-27 08:00:12

      MySQL安全小技巧

      2023-05-06 10:22:49

      MySQL数据库的安装(安装以及简单数据库操作)

      2023-05-06 10:22:26

      MySQL的数据库database(二)

      2023-04-23 09:35:19

      MySQL的子查询(二十)

      2022-12-27 10:00:39

      查看更多

      热门标签

      数据库 mysql 字符串 数据结构 MySQL 算法 redis oracle java sql python 数据 索引 SQL 查询
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      【MySQL】—— 数据库 增删查改 练习(基础)

      MySQL的MVCC机制

      MySQL执行安装“rpm -ivh mysql-community-server-5.7.34-1.el6.i686.rpm“报错“error:Failed dependencies“

      项目性能优化(MySQL读写分离、MySQL主从同步、Django实现MySQL读写分离)

      Windows 安装mysql数据库

      MySQL使用show profile调优

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号