缓冲池是主存储器中的一个区域,在访问 table 和索引数据时InnoDB会对其进行缓存。缓冲池允许直接从内存中访问频繁使用的数据,从而加快处理速度。在专用服务器上,通常将高达 80% 的物理内存分配给缓冲池。

为了高效处理大量读取操作,缓冲池被划分为可以容纳多行数据的页面。为了有效管理缓存,缓冲池被实现为页面的链接列表;通过 LRU(least recently used)算法的变体将很少使用的数据从缓存中淘汰出去。

了解如何利用缓冲池将频繁访问的数据保留在内存中是MySQL调优的重要方面之一。

缓冲池 LRU 算法

缓冲池使用一种最近最少使用(LRU)算法的变体作为列表进行管理。当需要空间以将新页面添加到缓冲池时,最近最少使用的页面会被移除,并将新页面添加到列表的中间。这种中点插入策略将列表视为两个子列表:

  • 在前面是最近访问过的新("young")页面的子列表;
  • 在尾部是最近较少被访问的旧("old")页面子列表。

缓冲池列表如下图所示:

该算法将频繁使用的页面保留在新页面子列表中。旧页面子列表则包含较少被使用的页面,这些页面是可能被淘汰(eviction)的候选页面。

默认情况下,算法运行如下:

  • 缓冲池的 3/8 专门用于旧页面子列表。
  • 列表的中点是新页面子列表的尾部与旧页面子列表的头部相遇的边界位置。
  • 当InnoDB将一个页面读入缓冲池时,它最初会插入到中点位置(旧页面子列表的头部)。一个页面可以被读取,因为它是用户发起的操作(例如 SQL 查询)所必需的,或者是InnoDB自动执行的预读(read-ahead)操作的一部分。
  • 访问旧页面子列表中的一个页面会使其变为"young",并将其移动到新页面子列表的开头。如果页面由于用户发起的操作而被读取,则将立即进行首次访问,并且页面会被标记为"young"。如果页面是由于预读操作而被读取,则第一次访问不会立即发生,并且在该页面被淘汰之前可能根本不会发生。
  • 随着数据库的运行,缓冲池中未被访问的页面会通过向列表的尾部移动而"老化"。新页面子列表和旧页面子列表中的页面都会随着其他页面的更新而老化。旧页面子列表中的页面也会随着在中点插入页面而老化。最终,一个长时间未被使用的页面会到达旧页面子列表的尾部并被淘汰。

默认情况下,通过查询读取的页面会立即移动到新页面子列表中,这意味着它们在缓冲池中停留的时间更长。例如,对于执行mysqldump操作或不带WHERE子句的SELECT语句进行的表扫描,可能会将大量数据带入缓冲池,并淘汰相同数量的较旧数据,即使新数据永远不会再次使用。同样地,由预读取后台线程加载且仅访问一次的页面会移动到新页面子列表的开头。这些情况会将频繁使用的页面推入旧页面子列表,使其面临淘汰的风险。关于优化这种行为的信息,请参阅"使缓冲池具有扫描抵抗力"和"配置 InnoDB 缓冲池预取(预读)"。

InnoDB标准监视器(Standard Monitor)的输出在BUFFER POOL AND MEMORY部分中包含了几个与缓冲池 LRU 算法操作有关的字段。有关详细信息,请参阅使用 InnoDB 标准监视器监控缓冲池。

缓冲区配置

您可以配置缓冲池的各个方面以提高性能。

  • 理想情况下,您应该将缓冲池的大小设置为尽可能大的值,同时确保为服务器上的其他进程留有足够的内存,以避免过多的页面交换(paging)。缓冲池越大,InnoDB就更像是一个内存数据库,从磁盘读取一次数据,然后在后续读取从内存中访问数据。有关详细信息,请参阅"配置 InnoDB 缓冲池大小"。
  • 在具有足够内存的64位系统上,可以将缓冲池分成多个部分,以最大程度地减少并发操作之间对内存结构的争用。有关详细信息,请参阅"配置多个缓冲池实例"。
  • 您可以将频繁访问的数据保留在内存中,而不受会将大量不经常访问的数据带入缓冲池的操作突然活动的影响。有关详细信息,请参阅"使缓冲池具有扫描抵抗力"。
  • 您可以控制何时以及如何执行预读请求,以异步方式将页面预取到缓冲池中,从而期望这些页面很快会被使用。有关详细信息,请参阅"配置 InnoDB 缓冲池预取(预读)"。
  • 您可以控制何时进行后台刷新,以及是否根据工作负载动态调整刷新速率。有关详细信息,请参阅"配置缓冲池刷新"。
  • 您可以配置InnoDB保存当前的缓冲池状态的方式,以避免服务器重新启动后的漫长预热时间。有关详细信息,请参阅"保存和恢复缓冲池状态"。

使用 InnoDB 标准监视器监控缓冲池

可以使用SHOW ENGINE INNODB STATUS访问InnoDB标准监视器输出提供的有关缓冲池操作的指标。缓冲池指标位于InnoDB标准监视器输出的BUFFER POOL AND MEMORY部分:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872
Dictionary memory allocated 776332
Buffer pool size 131072
Free buffers 124908
Database pages 5720
Old database pages 2071
Modified db pages 910
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 4, not young 0
0.10 youngs/s, 0.00 non-youngs/s
Pages read 197, created 5523, written 5060
0.00 reads/s, 190.89 creates/s, 244.94 writes/s
Buffer pool hit rate 1000 / 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: 5720, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

下表描述了InnoDB标准监视器报告的缓冲池指标。

注:InnoDB标准监视器输出中提供的每秒平均值是基于自上次打印InnoDB标准监视器输出以来经过的时间计算的。

InnoDB 缓冲池指标如下表所示:

Name Description
Total memory allocated 为缓冲池分配的总内存(以字节为单位)。
Dictionary memory allocated 为InnoDB数据字典分配的总内存(以字节为单位)。
Buffer pool size 分配给缓冲池的页面总大小。
Free buffers 缓冲池空闲列表的页面总大小。
Database pages 缓冲池 LRU 列表的页面总大小。
Old Database pages 缓冲池旧 LRU 子列表的页面总大小。
Modified db pages 当前在缓冲池中修改的页面数。
Pending reads 等待读入缓冲池的缓冲池页面数。
Pending writes LRU 从 LRU 列表底部等待写入缓冲池中旧脏页的数量。
Pending writes flush list 检查点期间要刷新的缓冲池页面数。
Pending writes single page 缓冲池中暂挂的独立页面写入数。
Pages made young 缓冲池 LRU 列表中变年轻的页面总数(移至“新”页面的子列表的开头)。
Pages made not young 缓冲池 LRU 列表中没有变年轻的页面总数(保留在“旧”页面子列表中没有年轻的页面)。
youngs/s 在缓冲池 LRU 列表中,平均每秒访问旧页面并使其变为年轻页面的次数。有关更多信息,请参阅此表格后面的注释。
non-youngs/s 在缓冲池 LRU 列表中,平均每秒访问旧页面并未导致页面变为年轻页面的次数。有关更多信息,请参阅此表格后面的注释。
Pages read 从缓冲池读取的页面总数。
Pages created 在缓冲池中创建的页面总数。
Pages written 从缓冲池写入的页面总数。
reads/s 平均每秒读取的缓冲池页面数。
creates/s 平均每秒创建的缓冲池页面数。
writes/s 平均每秒缓冲池页面写入数。
Buffer pool hit rate 从缓冲池读取的页面与从磁盘存储读取的页面之间的缓冲池页面命中率。
young-making rate 页面访问导致页面变为年轻页面的平均命中率。有关更多信息,请参阅此表格后面的注释。
not (young-making rate) 页面访问未使页面变年轻的平均命中率。有关更多信息,请参见此表格后面的注释。
Pages read ahead 平均每秒的预读操作次数。
Pages evicted without access 平均每秒从缓冲池中淘汰而被访问的页面数量。
Random read ahead 平均每秒随机预读操作次数。
LRU len 缓冲池 LRU 列表的页面总大小。
unzip_LRU len 缓冲池 unzip_LRU 列表的长度(以页面为单位)。
I/O sum 访问的缓冲池 LRU 列表页面总数。
I/O cur 当前间隔内访问的缓冲池 LRU 列表页面总数。
I/O unzip sum 已访问的缓冲池 unzip_LRU 列表页面的总数。
I/O unzip cur 当前时间间隔内已访问的缓冲池 unzip_LRU 列表页面的总数。

Notes:

  • 年轻页面生成速率youngs/s指标仅适用于旧页面。它基于页面的访问次数而不是页面数计算。对于给定页面,可能会有多次访问,所有访问都会被计算在内。如果在没有进行大规模扫描的情况下youngs/s非常低,则可能需要减少延迟时间或增加用于旧子列表的缓冲池百分比。增加百分比会使旧子列表变大,因此需要更长的时间才能将该子列表中的页面移动到尾部,从而增加这些页面再次被访问并成为年轻页面的可能性。请参阅“使缓冲池抗扫描”。

  • 非年轻页面生成速率non-youngs/s指标仅适用于旧页面,它基于页面的访问次数而不是页面数计算。对于给定页面,可能会有多次访问,所有访问都会被计算在内。如果在执行大型表扫描(以及较高的youngs/s)时没有看到更高的非年轻页面生成速率值non-youngs/s,请增加延迟值。请参阅“使缓冲池抗扫描”。

  • 年轻页面生成率young-making考虑了所有缓冲池页面的访问,而不仅仅是旧子列表中页面的访问。年轻页面生成率young-making和非年轻页面生成率non-youngs/s通常不会累加到整体缓冲池命中率上。在旧子列表中的页面命中会导致页面移动到新子列表,但是新子列表中的页面命中只有当它们距离列表头部一定距离时才会移动到列表头部。

  • 非(年轻页面生成率)not (young-making rate)是指由于未达到由innodb_old_blocks_time定义的延迟时间,或由于新子列表中的页面命中未导致页面移动到头部,而导致页面访问未使页面变为年轻页面的平均命中率。此率考虑了所有缓冲池页面的访问,而不仅仅是旧子列表中页面的访问。

缓冲池服务器状态变量和INNODB_BUFFER_POOL_STATS表提供了许多与InnoDB Standard Monitor 输出中相同的缓冲池指标。有关更多信息,请参阅示例“查询INNODB_BUFFER_POOL_STATS table”。

注:原文来自 MySQL 5.7 官方文档,阅读 MySQL 中文文档时有些语句理解不顺畅,便结合中文文档使用 ChatGPT 进行了翻译,如有不正请指出。

MySQL 存储引擎 InnoDB 内存结构之缓冲池的更多相关文章

  1. 常用Mysql存储引擎--InnoDB和MyISAM简单总结

    常用Mysql存储引擎--InnoDB和MyISAM简单总结 2013-04-19 10:21:52|  分类: CCST|举报|字号 订阅     MySQL服务器采用了模块化风格,各部分之间保持相 ...

  2. MySQL存储引擎InnoDB,MyISAM

    MySQL存储引擎InnoDB,MyISAM1.区别:(1)InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语 ...

  3. MySQL存储引擎InnoDB与Myisam

    InnoDB与Myisam的六大区别 InnoDB与Myisam的六大区别 MyISAM InnoDB 构成上的区别: 每个MyISAM在磁盘上存储成三个文件.第一个 文件的名字以表的名字开始,扩展名 ...

  4. 浅谈MySQL存储引擎-InnoDB&MyISAM

    存储引擎在MySQL的逻辑架构中位于第三层,负责MySQL中的数据的存储和提取.MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式是不同的.每一种存储引擎都有它的优势和劣势,本文只讨论最常见 ...

  5. mysql 存储引擎 InnoDB 与 MyISAM 的区别和选择

    http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html     酷壳 - MySQL: InnoDB 还是 MyISA ...

  6. MySQL存储引擎InnoDB大量数据下的问题

    MySQL如果只有MyISAM一个引擎的话,那你们黑真的也有道理,但问题是InnoDB现在已经是MySQL默认的引擎,而且这个引擎综合能力很强,能用好这个引擎其实就已经能解决大多数需要数据库的业务逻辑 ...

  7. MySQL存储引擎Innodb和MyISAM对比总结

    Innodb引擎 InnoDB是一个事务型的存储引擎,设计目标是处理大数量数据时提供高性能的服务,它在运行时会在内存中建立缓冲池,用于缓冲数据和索引. Innodb引擎优点 1.支持事务处理.ACID ...

  8. mysql存储引擎InnoDB详解,从底层看清InnoDB数据结构

    InnoDB一个支持事务安全的存储引擎,同时也是mysql的默认存储引擎.本文主要从数据结构的角度,详细介绍InnoDB行记录格式和数据页的实现原理,从底层看清InnoDB存储引擎. 本文主要内容是根 ...

  9. MySQL存储引擎 InnoDB/ MyISAM/ MERGE/ BDB 的区别

    MyISAM:默认的MySQL插件式存储引擎,它是在Web.数据仓储和其他应用环境下最常使用的存储引擎之一.注意,通过更改 STORAGE_ENGINE 配置变量,能够方便地更改MySQL服务器的默认 ...

  10. MySQL存储引擎InnoDB与MyISAM的区别

    一.比较 事务:InnoDB是事务型的,可以使用Commit和Rollback语句. 并发:MyISAM只支持表级锁,InnoDB还支持行级锁. 外键:InnoDB支持外键. 备份:InnoDB支持在 ...

随机推荐

  1. 从APNIC获取中国IP地址列表

    关于APNIC 全球IP地址块被IANA(Internet Assigned Numbers Authority)分配给全球三大地区性IP地址分配机构,它们分别是: ARIN (American Re ...

  2. 【Vue原理模拟】模拟Vue实现响应式数据

    1. 预期效果 当数据变动时,触发自定义的回调函数. 2. 思路 对对象 object 的 setter 进行设置,使 setter 在赋值之后执行回调函数 callback(). 3.细节 3.1 ...

  3. 四月九号java知识

    1.do{}while();和while(){}结构最主要区别就是前者后面要一个分号 2.System.out.print();与System.out.println();的区别后者输出换行, 前者不 ...

  4. Go 语言切片是如何扩容的?

    原文链接: Go 语言切片是如何扩容的? 在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice). 切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装.它非常灵活,支 ...

  5. Redis源码之SDS简单动态字符串

    Redis 是内存数据库,高效使用内存对 Redis 的实现来说非常重要. 看一下,Redis 中针对字符串结构针对内存使用效率做的设计优化. 一.SDS的结构 c语言没有string类型,本质是ch ...

  6. Java:如何加密或解密PDF文档?

    在工作中,我们会将重要的文档进行加密,并且设置用户的访问权限,其他外部人员均无法打开,只有获取该权限的用户才有资格打开文档.此外,限制用户的使用权限,极大程度上阻止了那些有意要篡改.拷贝其中内容的人, ...

  7. LangChain vs Semantic Kernel

    每当向他人介绍 Semantic Kernel, 会得到的第一个问题就是 Semantic Kernel 类似于LangChain吗,或者是c# 版本的LangChain吗? 为了全面而不想重复的回答 ...

  8. 项目中统计SQL执行缓慢的方案-数据预处理

    使用场景: 由于表数据量巨大,导致一些统计相关的sql执行非常慢,使用户有非常不好的体验,并且sql和数据库已经没有优化空间了.(并且该统计信息数据实时性要求不高的前提下) 解决方案: 整体思路:创建 ...

  9. Spring源码:bean的生命周期(一)

    前言 本节将正式介绍Spring源码细节,将讲解Bean生命周期.请注意,虽然我们不希望过于繁琐地理解Spring源码,但也不要认为Spring源码很简单.在本节中,我们将主要讲解Spring 5.3 ...

  10. dataX源码学习

    文章目录 前言 开始准备 运行配置 开始运行 JobContainer 1.进入init prepare schedule post阶段 this.invokeHooks(); 总结 前言 在用dat ...