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. C#之Action和Func

    以前我都是通过定义一个delegate来写委托的,但是最近看一些外国人写的源码都是用action和func方式来写,当时感觉对这很陌生所以看起源码也觉得陌生,所以我就花费时间来学习下这两种方式,然后发 ...

  2. js重点——作用域——内部原理(二)

    本篇是深入分析和理解作用域的第一篇——内部原理和工作模型. 我们知道作用域是变量,对象,函数可访问的一个范围.这说明了我们需要一套良好的规则来存储变量,之后方便查找.所以我们首先要理解的是在哪里而且怎 ...

  3. c# 将datatable中的数据保存到excel文件中

    using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Lin ...

  4. vs 调试时 QuickWatch 不能计算变量值

    尝试下这个方法:DEBUG- -> Options and Settings--> Symbols中查看缓存路径是否设置为当前程序的bin文件然后将Debug-->Options a ...

  5. # 机器学习算法总结-第六天(Adaboost算法)

    SKlearn中的Adaboost使用 主要调的参数:第一部分是对我们的Adaboost的框架进行调参, 第二部分是对我们选择的弱分类器进行调参. 使用 Adaboost 进行手写数字识别 导入库,载 ...

  6. K2 BPM_如何将RPA的价值最大化?_全球领先的工作流引擎

     自动化技术让企业能够更有效的利用资源,减少由于人为失误而造成的风险损失.随着科技的进步,实现自动化的途径变得更加多样化. 据Forrester预测,自动化技术将在2019年成为引领数字化转型的前沿技 ...

  7. ESP8266 UDP通信

    #include "driver/uart.h" #include "espconn.h" void ICACHE_FLASH_ATTR user_rf_pre ...

  8. LCD1602 液晶

    它是一种专门用来显示字母.数字.符号的点阵型液晶模块 它是由若干个5x7或者5x10的点阵字符位组成 引脚 时序 操作步骤 初始化 写命令(RS=L)设置显示坐标 写数据(RS=H) 指令 清屏: 指 ...

  9. bootsctrap4 datepicker时间选择插件

    现在网上基本都是v3的时间选择插件,花了点时间改了找了个v4能用的 bootstrap-datepicker <!DOCTYPE html> <html> <head&g ...

  10. sql 随机数系列

    一.把数据库把某个字段更新为随机数 DECLARE @Hour INT DECLARE @Counts INT SET @Hour =DATENAME(HOUR, GETDATE()) ) BEGIN ...