一 为什么需要Buffer Pool

如果我们每一次查询或者更新都需要到磁盘找到对应数据页,每次的都需要从磁盘加载,那么性能必定是很差的。所以将一些从磁盘加载的数据页,放入到内存缓存起来,而不用每次都从磁盘加载,提升性能。

二 Buffer Pool数据结构

#1 数据库在启动的时候,根据Buffer Pool大小在申请一块内存区域,叫做Buffer Pool,默认大小128MB,可以通过innoddb_buffer_pool_size控制。

#2 每一个Buffer Pool是由多个Chunk构成,默认一个Chunk是128MB, 可以通过参数innodb_buffer_pool_chunk_size控制。

#3 申请完毕后,会按照缓存页16KB大小在Buffer Pool划分出一个个的空的缓存页以及按照元数据大小,划分出元数据块。

缓存块:用于存放从磁盘加载的数据页,每一个数据页大小16KB,而缓存块也刚好根据数据页大小设置为16KB

元数据块:1个元数据块对应一个缓存块,保存的是缓存块的地址、数据页所属的表空间、数据页的编号。

#4 为了确地哪些缓存页是空的,引入了free链表;为了确地哪些是缓存页是可以刷盘的或者脏页,则引入flush链表,并且flush链表刷盘的时候采用LRU策略

三 Buffer Pool free链表作用

数据库从磁盘加载数据页到内存,需要获取一个空闲的缓存页来存储磁盘上加载多大数据页数据,那么如何确定哪一个缓存页是空闲的呢? 所以引入free空闲链表,是一个双向数据结构,前驱free_pre,后继free_next, 在数据库启动的时候,创建的都是空闲的缓存页和对应的元数页,则将所有元数据块以双向链表的形式连接起来,只要这个链表不为空,则表示可以获取缓存页

四 Buffer Pool flush链表作用

当free空闲链表没有元数据块,即表示没有缓存页了,这时候需要获取一个脏的数据页,然后将其刷到磁盘,清空之后作为free缓存页存放新的数据页。但是我们如何知道哪一个缓存页是修改过的呢?

所以MySQL引入了flush链表,前驱flush_pre,后继flush_next构造的双向链表,发生过修改的缓存页,从free链表移出,加入到flush链表。这时候只需要从flush链表中获取一个元数据块,然后将其对应的缓存页flush到磁盘。

五 如何淘汰flush链表中的缓存页

我们知道数据库没有空闲缓存页,从flush链表上找一个flush到磁盘就可以使用了,但是获取哪一个呢? 不能随便获取吧,有些经常被访问,有些很少被访问或者几乎不访问,那么你把经常被访问的淘汰了不合适吧。所以flush链表基于LRU原则构建,最新访问的flush链表上缓存页被移到flush链表前面,那么自然链表末尾就是最近很少使用的,所以把flush链表上最后的节点淘汰。

六 基础LRU flush链表带来的问题

但是上面简单的LRU机制是有缺陷的,当触发MySQL的预读机制,会把临近的数据页一起加载出来,这就要求占用更多空闲缓存页,如果没有则从flush链表淘汰,但是其他的数据页又暂时不会被访问,可能会把一些经常被访问的缓存页给淘汰,而新的数据页很多都不会被访问。

什么是预读机制呢? 什么场景会触发预读机制呢?

预读机制:允许把相邻的数据页一起加载到内存

#1 当MySQL顺序读取一个区内56个数据页,则触发预读机制,可以通过参数innodb_read_ahead_threshold控制次数

#2 全表扫描,可能会涉及到多个数据页,从而触发预读机制

七 基于冷热数据分离方式解决基础LRU flush链表问题

那如何避免预读机制带来的问题呢? MySQL引入了冷热数据分离机制,流程如下:

#1 flush链表分为两部分,一部分是热数据,缓存的是经常被访问的缓存页,一部分是冷数据,缓存的是刚从磁盘读取和经常不被访问的缓存页

#2 flush 冷热数据分离,冷数据占比37%,热数据占比63%,通过innodb_old_blocks_pct参数控制,默认37,分隔的点叫做中间点midpoint

#3 刚才磁盘读取的数据页,会被放在冷数据头部,即midpoint处。但不是立马访问就会被加载到热数据区域,而是默认需要在1秒后被访问才可以放到热数据区域,free空闲缓存页链表没有缓存页了,则从冷数据区获取最后一个缓存页刷盘

#4 如果热数据经常被访问,会导致不断的前后移动,但是又不是都需要淘汰,所以不需要移动这么频繁,对这个LRU的flush链表优化,热数据区域前1/4被访问不会移动,只有后面的3/4缓存页被访问才移动到链表头部

#5 热数据区域的缓存页永不淘汰吗?肯定不是的,当后台线程每隔一段时间就会把所有的flush链表上的缓存页都刷到磁盘

整个Buffer Pool用一张图片来总结:

MySQL深度剖析之Buffer Pool专题(2021)相关推荐

  1. MySQL · 性能优化· InnoDB buffer pool flush策略漫谈

    MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...

  2. MySQL深度剖析之undo log redo log binlog专题(2021)

    因为每次对磁盘随机读写影响性能,尤其是高并发的时候,所以引入了Buffer Pool, 即只要更新Buffer Pool中的记录,则算更新成功,那如果更新完了还没有flush到磁盘则宕机了,此时内存的 ...

  3. MySQL深度剖析之SQL语句更新流程(2021)

    #1 线程开始执行SQL更新请求之前,会创建事务,并且为当前线程分配一块内存空间叫做binlog cache 注意:binlog cache 是每一个线程分配一个:binlog cache大小受bin ...

  4. [MySQL 源码] 从buffer pool中获取空闲block流程

    当我们将一个page读入内存时,需要先为其分配一个block,从buffer pool中获取.入口函数为buf_LRU_get_free_block 之前在http://mysqllover.com/ ...

  5. MySQL 引擎特性 · InnoDB Buffer Pool

    前言 用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因为引入 ...

  6. mysql fsync_MySQL - InnoDB特性 - Buffer Pool漫谈

    缓存管理是DBMS的核心系统,用于管理数据页的访问.刷脏和驱逐:虽然操作系统本身有page cache,但那不是专门为数据库设计的,所以大多数数据库系统都是自己来管理缓存.由于几乎所有的数据页访问都涉 ...

  7. MySQL深度剖析之索引专题(2021)

    9.1 为什么需要使用索引 第一:减少了MySQL需要扫描的数据量,尤其是全表扫描 第二:随机IO变成顺序IO,提升查询速度 可以快速匹配where子句.排序和分组也可以使用索引,匹配原则最左匹配.特 ...

  8. MySQL深度剖析之事务隔离级别和锁机制(2021)

    一 事务隔离级别和锁机制 1.1 多个事务并发修改同一条数据或者对同一条数据并发读写存在哪些事务并发问题 1.1.1 脏读(未提交读) A事务读取了别的事务还未提交的更新,而B事务是有可能回滚的. 1 ...

  9. MySQL深度剖析之数据在磁盘上存储(2021)

    一 数据在磁盘上存储格式(row format) 表中的数据在磁盘上存储是有格式的,可以在创建表的时候通过row_format指定,比如MySQL5.0之前的reduntant,MySQL5.0 之后 ...

最新文章

  1. 【转】Hive学习路线图
  2. objective-c 编写规范_Objective-c成员变量的定义方式?如何写才规范?
  3. C# 制作不规则窗体的两种解决方案
  4. 图的定义与术语 - 数据结构和算法54
  5. java返回特定下标元素_java基础--输出数组中指定元素的下标
  6. oracle的buffercache
  7. 若微型计算机在工作时突然断电,16秋《计算机基础》作业1
  8. 【ZOJ】3380 Patchouli's Spell Cards
  9. macOS Big Sur无法安装 Big Sur为什么安装不了?
  10. python中bool怎么用_python函数之bool([x])用法详解
  11. Arduino PS2手柄小车代码
  12. 计算机无法装补丁,老司机教你win7 sp1补丁安装失败怎么办
  13. 晚清十大武林高手(电视里常引用的真实人物)
  14. linux永久修改dns
  15. has a default child route. When navigating to this named route 。。。。。报错
  16. git常用命令梳理及常见开发场景总结
  17. 夜刃CTF小组招募志同道合的CTFer
  18. Arduino驱动oled
  19. 记一次与第三方ROM上的360软件全家桶的斗智斗勇难忘的经历
  20. T4模版引擎之基础入门

热门文章

  1. php include不可用,无法设置PHP include_path
  2. python和java哪个有用_python和java哪个好
  3. IDEA启动hadoop报Could not locate executable null\bin\winutils.exe in the Hadoop binaries.错误的解决办法
  4. PostgreSQL12系统视图pg_stats
  5. Linux下qwt源码编译,QWT的编译与配置
  6. java shark_JAVA项目开发笔记(3)Shark部分: Shark API | 学步园
  7. CentOS 7 上搭建 ZooKeeper 集群
  8. dos 退出for循环_循环?一次帮你搞定!
  9. Java 算法 邮票
  10. Java 算法 友好数