MySQL 存储引擎 InnoDB 内存结构之缓冲池
缓冲池是主存储器中的一个区域,在访问 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 内存结构之缓冲池的更多相关文章
- 常用Mysql存储引擎--InnoDB和MyISAM简单总结
常用Mysql存储引擎--InnoDB和MyISAM简单总结 2013-04-19 10:21:52| 分类: CCST|举报|字号 订阅 MySQL服务器采用了模块化风格,各部分之间保持相 ...
- MySQL存储引擎InnoDB,MyISAM
MySQL存储引擎InnoDB,MyISAM1.区别:(1)InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语 ...
- MySQL存储引擎InnoDB与Myisam
InnoDB与Myisam的六大区别 InnoDB与Myisam的六大区别 MyISAM InnoDB 构成上的区别: 每个MyISAM在磁盘上存储成三个文件.第一个 文件的名字以表的名字开始,扩展名 ...
- 浅谈MySQL存储引擎-InnoDB&MyISAM
存储引擎在MySQL的逻辑架构中位于第三层,负责MySQL中的数据的存储和提取.MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式是不同的.每一种存储引擎都有它的优势和劣势,本文只讨论最常见 ...
- mysql 存储引擎 InnoDB 与 MyISAM 的区别和选择
http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html 酷壳 - MySQL: InnoDB 还是 MyISA ...
- MySQL存储引擎InnoDB大量数据下的问题
MySQL如果只有MyISAM一个引擎的话,那你们黑真的也有道理,但问题是InnoDB现在已经是MySQL默认的引擎,而且这个引擎综合能力很强,能用好这个引擎其实就已经能解决大多数需要数据库的业务逻辑 ...
- MySQL存储引擎Innodb和MyISAM对比总结
Innodb引擎 InnoDB是一个事务型的存储引擎,设计目标是处理大数量数据时提供高性能的服务,它在运行时会在内存中建立缓冲池,用于缓冲数据和索引. Innodb引擎优点 1.支持事务处理.ACID ...
- mysql存储引擎InnoDB详解,从底层看清InnoDB数据结构
InnoDB一个支持事务安全的存储引擎,同时也是mysql的默认存储引擎.本文主要从数据结构的角度,详细介绍InnoDB行记录格式和数据页的实现原理,从底层看清InnoDB存储引擎. 本文主要内容是根 ...
- MySQL存储引擎 InnoDB/ MyISAM/ MERGE/ BDB 的区别
MyISAM:默认的MySQL插件式存储引擎,它是在Web.数据仓储和其他应用环境下最常使用的存储引擎之一.注意,通过更改 STORAGE_ENGINE 配置变量,能够方便地更改MySQL服务器的默认 ...
- MySQL存储引擎InnoDB与MyISAM的区别
一.比较 事务:InnoDB是事务型的,可以使用Commit和Rollback语句. 并发:MyISAM只支持表级锁,InnoDB还支持行级锁. 外键:InnoDB支持外键. 备份:InnoDB支持在 ...
随机推荐
- 自建kms2种方法,亲测有效
你还在用网上那种坑爹的Ghost盗版系统吗?内置各种辣鸡.流氓软件,新系统?纯净版Ghost系统?不存在的~ 在开始自建KMS服务器之前,我觉得很有必要给大家分享一个神站,没错就是MSDN! 地址:h ...
- SSM整合的所有配置(配置类)
导入依赖坐标pom.xml <dependencies> <dependency> <groupId>junit</groupId> <artif ...
- Java 异常处理:使用和思考
概念 异常处理的概念起源于早期的编程语言,如 LISP.PL/I 和 CLU.这些编程语言首次引入了异常处理机制,以便在程序执行过程中检测和处理错误情况.异常处理机制随后在 Ada.Modula-3. ...
- .NET中使用Redis总结——2.项目实战
接上篇.NET中使用Redis总结 -- 1.Redis搭建 看一些Redis相关资料,.NET 方面ServiceStack.Redis 用的比较多,就直接拿来用了. 在使用过程中经常过出现假死状态 ...
- Java设计模式 —— 观察者模式
16 观察者模式 16.1 观察者模式概述 Observer Pattern: 定义对象之间的依赖关系(一对多),当一个对象的状态发生改变时,其关联的依赖对象均收到通知并自动更新. 观察者模式又称:发 ...
- 华为云 OpenTiny 跨端、跨框架企业级开源组件库项目落地实践直播即将开启!
大家好,我是 Kagol,公众号:前端开源星球. "你们这个产品怎么只能在电脑上适配呀?我想在手机上看都不行,太麻烦了!!" "你们这个产品看起来太简单了,我想要@@功能 ...
- 第2章. reco主题介绍
1. 这是一个vuepress主题,旨在添加博客所需的分类.TAB墙.分页.评论等能: 2. 主题追求极简,根据 vuepress 的默认主题修改而成,官方的主题配置仍然适用: 3. 你可以打开 [午 ...
- 浏览器发送POST请求、DELETE请求
1.浏览器发送POST请求 方法一: var xml = new XMLHttpRequest(); var url = "http://127.0.0.1:8800/admin/user& ...
- C# 反射 判断类型是否是列表
1 /// <summary> 2 /// 判断类型是否为可操作的列表类型 3 /// </summary> 4 /// <param name="type&q ...
- [Opencv-C++] 1.1Opencv环境准备
Opencv环境准备 一.Opencv各版本下载 二.安装: 1.先下载OpenCV的源码: 2.解压到服务器任意目录: 3.进入源码目录 4.事先安装下列软件 5.进入到cmake 6.cmake编 ...