缓冲池的用处

对于使用 InnoDB 作为存储引擎的表来说,不管是用于存储用户数据的索引,还是各种系统数据,都是以页的形式存放在表空间中的,而所谓的表空间只是 InnoDB 对文件系统上一个或几个实际文件的抽象,也就实际数据说到底还是存储在磁盘上的。

磁盘的速度很慢,怎么能配得上“快如闪电”的CPU 呢?

InnoDB 存储引擎在处理客户端的请求时,当需要访问某个页的数据时,就会把完整的页的数据全部加载到内存中。

也就是说即使我们只需要访问一个页的一条记录,那也需要先把整个页的数据加载到内存中。

缓冲池内部组成

缓冲池中默认的缓存页大小和在磁盘上默认的页大小是一样的,一般是16KB。

为了更好的管理这些在缓冲池中的缓存页,InnoDB为每一个缓存页都创建了一些所谓的控制信息。

这些控制信息包括该页所属的表空间编号、页号、缓存页在缓冲池中的地址、链表节点信息、一些锁信息。

缓冲池的一些参数: SHOW VARIABLES LIKE 'innodb_buffer_pool%'; free 链表 当最初启动MySQL服务器的时候,此时并没有真实的磁盘页被缓存到缓冲池中,之后随着程序的运行,会不断的有磁盘上的页被缓存到缓冲池中。

从磁盘上读取一个页到缓冲池中的时候该放到哪个缓存页的位置呢?

思路:区分缓冲池中哪些缓存页是空闲的,哪些已经被使用了。

把所有空闲的缓存页对应的控制块作为节点放到一个链表中,这个链表叫作 free 链表。

flush 链表

如果我们修改了缓冲池中某个缓存页的数据,那它就和磁盘上的页不一致了,这样的缓存页也被称为脏页(dirty page)。

最简单的做法就是每发生一次修改就立即同步到磁盘上对应的页上,但是频繁的往磁盘中写数据会严重的影响程序的性能。

所以,Innodb 创建了一个存储脏页的链表,凡是修改过的缓存页对应的控制块都会作为一个节点加入到一个链表中,在未来的某个时间点进行同步。这个链表叫做 flush 链表。

缓存不够的窘境

缓冲池对应的内存大小毕竟是有限的,如果需要缓存的页占用的内存大小超过了缓冲池大小,也就是已经没有多余的空闲缓存页的时候怎么办?

把某些旧的缓存页从缓冲池中移除,然后再把新的页放进来。

移除哪些缓存页?这就需要引入缓存淘汰机制了。

缓存淘汰机制

缓存淘汰有以下两个目的:

  • 实现淘汰
  • 使缓存命中率高

缓存淘汰机制比较常用的是用 LRU (Least recently used)算法。

传统LRU

LRU 的两种情况:

(1)页已经在缓冲池里,那就只做“移至”LRU头部的动作,而没有页被淘汰;

(2)页不在缓冲池里,除了做“放入”LRU头部的动作,还要做“淘汰”LRU尾部页的动作;

在 InnoDB 中,传统的 LRU 会遇到两个问题:

(1)预读失效;

(2)缓冲池污染;

什么是预读失效?

由于预读 (Read-Ahead),提前把页放入了缓冲池,但最终 MySQL 并没有从页中读取数据,称为预读失效。

如何对预读失效进行优化?

要优化预读失效,思路是:

(1)让预读失败的页,停留在缓冲池 LRU 里的时间尽可能短;

(2)让真正被读取的页,才挪到缓冲池 LRU 的头部;以保证,真正被读取的热数据留在缓冲池里的时间尽可能长。

具体方法是:

(1)将LRU分为两个部分

  • new 区(new sublist)
  • old 区(old sublist)

(2)两个区首尾相连,即:new 区的尾(tail)连接着 old 区的头(head);

(3)新页(例如被预读的页)加入缓冲池时,只加入到 old 区头部: 如果数据真正被读取(预读成功),才会加入到 new 区的头部 如果数据没有被读取,则会比 new 区里的“热数据页”更早被淘汰出缓冲池

改进版缓冲池LRU能够很好的解决“预读失败”的问题。

查看系统变量 innodb_old_blocks_pct 的值来确定old区域在LRU链表中所占的比例 SHOW VARIABLES LIKE 'innodb_old_blocks_pct';

什么是 MySQL 缓冲池污染? 当某一个SQL语句,要批量扫描大量数据时,可能导致把缓冲池的所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降,这种情况叫缓冲池污染。

例如,有一个数据量较大的用户表,当执行 select * from user where name like "%test%";

要优化缓冲池污染,思路是:

(1)不让批量扫描的大量数据进入到 new 区;

(2)让真正被读取的页,才挪到缓冲池 LRU 的头部;

具体实现: 加入了一个“old 区停留时间”的机制: 在 old 区域的缓存页进行第一次访问时就在它对应的控制块中记录下来这个访问时间,如果后续再次访问的时间与第一次访问的时间在某个时间间隔内(即该缓存页在 old 区的存在时间在某个时间间隔内),那么该页面就不会被从old 区移动到 new 区的头部。

上述的全表扫描执行:

(1)扫描过程中,需要新插入的数据页,都被放到old区

(2)一个数据页会有多条记录,因此一个数据页会被访问多次

(3)由于是顺序扫描,数据页的第一次被访问和最后一次被访问的时间间隔不会超过1S,因此还是会留在old区

(4) 继续扫描,之前的数据页再也不会被访问到,因此也不会被移到 new 区,最终很快被淘汰这个间隔时间是由系统变量 innodb_old_blocks_time 控制的。SHOW VARIABLES LIKE 'innodb_old_blocks_time';配置缓冲池时的注意事项 innodb_buffer_pool_size
innodb_buffer_pool_chunk_size ×
innodb_buffer_pool_instances 的倍数(这主要是想保证每一个 缓冲池 实例中包含的 chunk 数量相同)。

查看Buffer Pool的状态信息

SHOW ENGINE INNODB STATUSG

一些参数如下:

  • Total memory allocated :代表 Buffer Pool 向操作系统申请的连续内存空间大小,包括全部控制块、缓存页、以及碎片的大小。
  • Buffer pool size:代表该 Buffer Pool 可以容纳多少缓存页,单位是页
  • Free buffers:代表当前 Buffer Pool 还有多少空闲缓存页,也就是 free 链表中还有多少个节点。
  • Database pages:代表 LRU 链表中的页的数量,包含 new 和 old 两个区域的节点数量。
  • Old database pages:代表 LRU 链表 old 区域的节点数量。
  • Modified db pages:代表脏页数量,也就是 flush 链表中节点的数量。

总结

1、磁盘太慢,用内存作为缓存很有必要。
2、缓冲池本质上是InnoDB向操作系统申请的一段连续的内存空间,可以通过innodb_buffer_pool_size 来调整它的大小。
3、InnoDB 使用了许多链表来管理缓冲池。
4、缓冲池的常见管理算法是 LRU
5、InnoDB 对普通 LRU 进行了优化:分为 new 区和 old 区,加入“停留时间”机制。

作者:JeffreyC链接:https://juejin.im/post/5eccf7c3f265da76f525d333

缓冲多少数据_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理相关推荐

  1. 分页缓冲池占用很高怎么解决_聊点深的:解析MySQL,看看InnoDB 缓冲池(buffer pool) 工作原理...

    缓冲池的用处 对于使用 InnoDB 作为存储引擎的表来说,不管是用于存储用户数据的索引,还是各种系统数据,都是以页的形式存放在表空间中的,而所谓的表空间只是 InnoDB 对文件系统上一个或几个实际 ...

  2. mysql分页缓冲池占用很高怎么解决_缓冲池(buffer pool),这次彻底懂了!!!

    https://blog.csdn.net/weixin_40009393/article/details/111103350 应用系统分层架构,为了加速数据访问,会把最常访问的数据,放在缓存(cac ...

  3. linux mysql定时删除数据_让linux每天定时备份MySQL数据库并删除五天前的备份文件...

    MYSQL定期备份是一项重要的工作,但人工操作太繁琐,也难避免有所疏漏,使用下面的方法即可让系统定期备份数据.利用系统crontab来定时执行备份文件,按日期对备份结果进行保存,达到备份的目的. 1. ...

  4. tm1650中文资料_[STM8入门资料]第53讲 TM1650 LED数码管驱动芯片工作原理

    刘洋[剑齿虎]STM8开发板学习笔记 第53讲TM1650 LED数码管驱动芯片工作原理 目 录 53.1 特性描述 TM1650是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路.内部 ...

  5. mysql是怎样工作的_六星教育揭秘一个真实的MySQL,述说它能给工作带来怎样的便利?...

    原标题:六星教育揭秘一个真实的MySQL,述说它能给工作带来怎样的便利? 提起web开发,六星教育就不得不想到PHP编程语言.提到PHP,首先就不能忽略掉它的MySQL数据库.很多初学者们并不是清楚M ...

  6. python调用通达信数据_[python]沪深龙虎榜数据导入通达信的自选板块并标注于k线图上...

    [python] 沪深龙虎榜数据导入通达信的自选板块, 并标注于 K 线图上 1 #coding=utf-8 2 3 # 读取 '[paint]' 开头的 csv 文件 4 #copyright @ ...

  7. python 通达信数据_[python]沪深龙虎榜数据导入通达信的自选板块,并标注于K线图上...

    1 #coding=utf-8 2 3 #读取'[paint]'开头的csv文件 4 #copyright @ WangXinsheng 5 #http://www.cnblogs.com/wangx ...

  8. c 获取mysql列数据_转 用C API 操作MySQL数据库

    用C API 操作MySQL数据库 参考MYSQL的帮助文档整理 这里归纳了C API可使用的函数,并在下一节详细介绍了它们.请参见25.2.3节,"C API函数描述". 函数 ...

  9. php mysql 插入多条数据_雷林鹏分享:PHP MySQL 插入多条数据

    使用 MySQLi 和 PDO 向 MySQL 插入多条数据 mysqli_multi_query() 函数可用来执行多条SQL语句. 以下实例向 "MyGuests" 表添加了三 ...

最新文章

  1. [转]div里table居中的问题 Div与body顶部间隙
  2. fastjson 1.1.71.android 版本发布,优化部分场景性能
  3. 第一章 代码无错就是优吗?(简单工厂模式)
  4. [蓝桥杯][2018年第九届真题]全球变暖(DFS)
  5. 协同遗漏的效果–使用简单的NIO客户端/服务器测量回送延迟
  6. mysql 根据当前时间戳_mysql timestamp类型 根据当前时间戳更新
  7. float php 运算_写给 PHP 程序员的 Python 学习指南
  8. matlab 连接数组,matlab数组操作知识点总结
  9. 基于图神经网络的节点表征学习
  10. Java使用Jacob转换Word为HTML
  11. 基础01类与对象、封装、构造方法
  12. js 父子标签同时设置onclick,子标签触发父标签onclick解决办法
  13. 贵州省中职学校计算机教材电子版,中职计算机基础课件_贵州省中职学校计算机应用基础教学工作计划.doc...
  14. 小型机 PC服务器 性能,pc服务器小型机
  15. Android 解决程序启动时的黑屏问题
  16. 还在用Navicat破解版吗?资深DBA推荐的八款SQL工具,免费又简单!
  17. ipad2019编写html,2019 iPad性能排行榜,选对型号很重要
  18. 获取data-*属性值
  19. Java最新面试题100道,包含答案示例(1-10题)
  20. ctfshow web80-88

热门文章

  1. mysql Decimal(M,D)解释
  2. 【热烈祝贺】俺们的S5PV210 工控板终于启动到wince桌面了!
  3. Windows Phone 7 Tips (1)
  4. 活动目录.NET编程Tips
  5. 树莓派(Raspberry Pi 3) - 系统烧录及系统使用
  6. MySQL事务效率测试
  7. Vmware7.1.4安装+破解+汉化
  8. FTP登录时指定用户名密码的方法
  9. uwsgi的log日志中出现错误uWSGI listen queue of socket 4 full。
  10. zzuli1895: 985的0-1串难题