InnoDB Buffer Pool

定义

对于InnoDB存储引擎,不管用户数据还是系统数据都是以页的形式存储在表空间进行管理的,其实都是存储在磁盘上的。

当InnoDB处理客户端请求,需要读取某页的一条记录时,就会将这个页中的所有数据加载到内存中,再进行读写操作,当读写操作完成后,不是先将内存空间释放,而是将其缓存起来,当下次有同样的请求时,可以省去磁盘IO的开销。

而InnoDB缓存这些页的内存就叫做Buffer Pool,(5.7.5v之前这是一块连续的内存,可以在配置文件中以innodb_buffer_pool_size动态修改其大小,这之后,以chunk为单位想操作系统申请空间,Buffer Pool由若干个chunk组成,一个chunk就是一片连续的空间)如果Buffer Pool大小大于1G时,那么可以被拆分成若干个小的独立的实例(系统变量innodb_buffer_pool_instances设置个数),缓存页的映射是有特定算法的,所以不存在重复缓存页,且在多线程访问时,互不影响。

(TODO Buffer Pool配置注意事项+Buffer Pool的状态信息查看SHOW ENGINE INNODB STATUS

组成

Buffer Pool由n个控制块和n个缓存页还有一些碎片组成,控制块与缓存页一一对应。

  • 缓存页:和磁盘上的页一样都是16kb大小,存放在Buffer Pool后边

  • 控制块:存放了一些控制信息包含页所属的表空间编号/页号/缓存页在Buffer Pool中的位置/链表节点信息/锁信息/LSN信息等,存放在Buffer Pool前边,大小约为缓存页的5%

  • 碎片:Buffer Pool中不能再分配的空间

管理

Buffer Pool在MySQL服务器启动时,就会完成初始化工作:申请Buffer Pool内存空间,划分若干对控制块和缓存页;其中缓存页的的使用情况会用到一些数据格式来管理,如空闲缓存页,被修改过的脏页等用到双向链表。

空闲页

free链表记录Buffer Pool中哪些缓存页是可用的,将缓存页对应的控制块作为一个节点存放在链表中,在Buffer Pool初始化时,是将所有控制块都存放的。free链表定义了一个基节点,存储了链表的头尾节点;每当需要使用一个缓存页时,都会从free链表取出一个空闲的缓存页,将控制信息填上,并将对应的缓存页节点从free链表移除。

缓存页查找

申明一个hash表,以表空间号+页号为key,缓存页为value存储已经被加载到缓存中的缓存页,这样就可以很快定位哪些页已经被缓存了,就无需重复为这个页申请缓存页

脏页

脏页是修改了已经被加载到Buffer Pool中的缓存页数据,导致它和磁盘上的不一致。为了将这些脏页都同步到磁盘上,创建了一个flush链表,用于存储这些脏页的信息,隔一段时间就将这些数据同步到磁盘。flush链表和free链表构造一样

刷新脏页到磁盘,有两种方式(在flush链表的页肯定也在LRU链表)

  • 从LRU链表的冷数据中刷新一部分页面到磁盘BUF_FLUSH_LRU:后台线程定时从LRU链表尾部开始扫描,如果发现脏页就会刷新到磁盘
  • flush链表中刷新一部分页面到磁盘BUF_FLUSH_LIST:后台线程定时从flush链表中刷新一部分页面到磁盘
  • 刷新LRU链表尾部单页到磁盘BUF_FLUSH_SINGLE_PAGE:当用户线程准备加载的一个磁盘页到Buffer Pool,却没有空间,先查找尾部是否有可以直接释放却没有修改的缓存页,如果没有就会强制将LRU链表尾部的一个脏页同步到磁盘

缓存淘汰

Buffer Pool的大小是有限的,所以需要将一些旧的缓存页从Buffer Pool中移除,但是移除缓存页时也期望缓存集中率高

问题

为了考虑两种可能会导致缓存命中率降低情况,所以需要对这个链表做一定的设计

  1. InnoDB提供“预读”的功能,即在执行某个请求后,将它认为之后可能会读到的一些页面预先加载到Buffer Pool中,并存放到LRU链表的头部

预读read ahead

  • 线性预读(使用操作系统核心提供的AIO接口异步读取下一个区中全部的页面到Buffer Pool)
  • 随机预读(如果Buffer Pool中已经缓存了某个区的13个连续(即young区域的头1/4)的页面,不论这些页面是不是顺序读取的,都会触发一次异步读取本区中所有其的页面到Buffer Pool的请求)

这个预读到的页如果真的被访问到,是可以提高效率的,但如果没有被访问,就会浪费内存,且让存放在链表尾部的缓存被淘汰,降低了缓存命中率;

  1. 全表扫描时读取表中所有记录,这时会将该表的所有页都存放到Buffer Pool中,这样可能会让Buffer Pool被完全覆盖,一些命中率非常高的缓存页就被淘汰了,降低了缓存命中率;
实现

LRU链表以按照最近最少使用的原则去淘汰缓存页,将这个链表分为两截(young区和old区,以使用频率高低区分,系统变量innodb_old_blocks_pct确定old区所占比例)

当访问某个页不存在缓存页中时(初始读),将这个缓存页的控制块放到old区,并在对应的控制块中记录下访问时间,这样预读/全表扫描的不被后续访问的页面就会逐渐从old区移除,如果后续被访问时,比较当前访问时间和记录的时间是否在一个时间间隔内(系统变量innodb_old_blocks_time查看),如果不在就会把页放到young区域的头部,反之,不会移动;这样就会减少将young中使用频率较高的页给顶下去的机会。

但是频繁的移动也会产生比较大的开销,所以规定只要被访问的缓存页位于young区域的1/4的后面,才会被移动到LRU链表的头部,降低调整LRU链表的频率

InnoDB缓存---InnoDB Buffer Pool的更多相关文章

  1. Innodb之监控Buffer pool Load progress

    你可以使用PERFORMANCE SCHEMA中的相关信息监控BUFFER POOL状态加载进程. 1. 启用 stage/innodb/buffer pool load instrument: 2. ...

  2. InnoDB Status Output – Buffer Pool and Spin Rounds

    InnoDB has a good source of information about its status which can be requested every time you need ...

  3. 面试题:你有没有搞混查询缓存和Buffer Pool

    一. 关注送书!<Netty实战> 文章公号号首发!连载中!关注微信公号回复:"抽奖" 可参加抽活动 首发地址:点击跳转阅读原文,有更好的阅读体验 使用推荐阅读,有更好 ...

  4. MySQL InnoDB缓冲池(Buffer Pool)

    InnoDB缓冲池并不仅仅缓存索引,它还会缓存行的数据.自适应哈希索引.插入缓冲(Insert Buffer).锁,以及其他内部数据结构. InnoDB还使用缓冲池来帮助延迟写入,这样就能合并多个写入 ...

  5. 在线调整InnoDB Buffer Pool Size

    InnoDB Buffer Pool主要是用来缓存数据表和索引数据的内存区域,它的默认值为134217728字节(128MB).最大值取决于CPU架构;32位系统上的最大值为4294967295(23 ...

  6. 14.6.3.5 Configuring InnoDB Buffer Pool Flushing

    14.6.3.5 Configuring InnoDB Buffer Pool Flushing InnoDB 执行某些任务在后台, 包括脏叶的刷新(那些已经发生改变的pages 但是没有写入到数据文 ...

  7. 一文了解MySQL的Buffer Pool

    摘要:Innodb 存储引擎设计了一个缓冲池(Buffer Pool),来提高数据库的读写性能. 本文分享自华为云社区<MySQL 的 Buffer Pool,终于被我搞懂了>,作者:小林 ...

  8. 关于MySQL buffer pool的预读机制

    预读机制 两种预读算法 1.线性预读 2.随机预读 对预读的监控 一.预读机制 InnoDB在I/O的优化上有个比较重要的特性为预读,预读请求是一个i/o请求,它会异步地在缓冲池中预先回迁多个页面,预 ...

  9. InnoDB存储引擎--Innodb Buffer Pool(缓存池)

    InnoDB存储引擎--Innodb Buffer Pool(缓存池) Innodb Buffer Pool的概念 InnoDB的Buffer Pool主要用于缓存用户表和索引数据的数据页面.它是一块 ...

随机推荐

  1. 在realm中动态查询用户的权限&角色

    @Controller @Scope("prototype") @Namespace("/") @ParentPackage("struts-defa ...

  2. css样式背景图片设置缩放

    一.背景颜色图片平铺 background-color 背景颜色 background-image 背景图片地址 background-repeat 是否平铺 默认是平铺 background-pos ...

  3. 开源跨境ERP - 小老板 Docker/Docker Compose一键部署

    先上部署成功后的截图,各个菜单点击均无报错 DockerCompose 包含: 1. 三个mysql5.7数据库 2. redis php会话存储+ memcached 3. 小老板php主程序 do ...

  4. vue项目js实现图片放大镜功能

    效果图:   我写的是vue的组件形式,方便复用,图片的宽高,缩放的比例可以自己定义 magnifier.vue <template> <div class="magnif ...

  5. SAP分析云及协同计划

    大家好, 我是SAP成都研究院S/4HANA Sales 团队的软件工程师Derek.四年前我从SAP Consulting团队转到SAP Labs从事Sales Analytics相关应用的开发,在 ...

  6. 一个用JavaScript生成思维导图(mindmap)的github repo

    github 地址:https://github.com/dundalek/markmap 作者的readme写得很简单. 今天有同事问作者提供的例子到底怎么跑.这里我就写一个更详细的步骤出来. 首先 ...

  7. briup_JDBC_自建工具类

    1.操作的环境 STS,mysql,oracle orcle 所操作的数据库名为 ORCL 表为 m_stu 表结构如下 mysql  的表为:my_stu 表结构如下 工具类完整代码 package ...

  8. RobHess的SIFT代码解析之kd树

    平台:win10 x64 +VS 2015专业版 +opencv-2.4.11 + gtk_-bundle_2.24.10_win32 主要参考:1.代码:RobHess的SIFT源码:SIFT+KD ...

  9. 简单介绍 Java 构造器

    导读 构造器是编程的强大组件.使用它们来释放 Java 的全部潜力. 在开源.跨平台编程领域,Java 无疑(?)是无可争议的重量级语言.尽管有许多伟大的跨平台框架,但很少有像 Java 那样统一和直 ...

  10. Django:中间件与csrf

    一.中间件 什么是中间件 中间件有什么用 自定义中间件 中间件应用场景 二.csrf csrf token跨站请求伪造 一.中间件 什么是中间件 中间件顾名思义,是介于request与response ...