1. BufferPool

What is BufferPool?

MySQL InnoDB Buffer Pool,MySQL InnoDB 缓冲池。里面缓存着大量数据(数据页),使 CPU 读取或写入数据时,不直接和低速的磁盘打交道,直接和缓冲区进行交互,从而解决了因为磁盘性能慢导致的数据库性能差的问题。

Why need BufferPool?

buffer pool 最主要的功能便是加速读和加速写。

加速读就是当需要访问一个数据页的时候,如果这个页已经在缓存池中,那么就不再需要访问磁盘,直接从缓冲池中就能获取这个页面的内容。

加速写就是当需要修改一个数据页的时候,先将这个页在缓冲池中进行修改,记下相关的 redo log,这个页的修改就算已经完成了。至于这个被修改的页什么时候真正刷新到磁盘,这个是 buffer pool 后台刷新线程来完成的。

How implemented?

所有从磁盘加载进内存的数据页,都会通过这个buffer pool管理起来。对应在代码的中的结构体为buf_pool_t。在MySQL中通常会有多个buffer pool instance,这是为了减少多线程并发访问时,buffer pool锁等待的开销。

BufferPool由buf_pool, buf_chunk, buf_block和buf_page组成,结构如下:

Code?

struct buf_pool_t {

buf_chunk_t *chunks; /*!< buffer pool chunks */

hash_table_t *page_hash; /*!< hash table of buf_page_t or

buf_block_t file pages,

buf_page_in_file() == TRUE,

indexed by (space_id, offset).

page_hash is protected by an

array of mutexes. */

UT_LIST_BASE_NODE_T(buf_page_t) flush_list;

/*!< base node of the modified block

list */

UT_LIST_BASE_NODE_T(buf_page_t) free;

/*!< base node of the free

block list */

UT_LIST_BASE_NODE_T(buf_page_t) LRU;

/*!< base node of the LRU list */

/* ... */

}

struct buf_chunk_t {

ulint size; /*!< size of frames[] and blocks[] */

unsigned char *mem; /*!< pointer to the memory area which

was allocated for the frames */

buf_block_t *blocks; /*!< array of buffer control blocks */

/* ... */

}

struct buf_block_t {

buf_page_t page; /*!< page information; this must

be the first field, so that

buf_pool->page_hash can point

to buf_page_t or buf_block_t */

byte *frame; /*!< pointer to buffer frame which

is of size UNIV_PAGE_SIZE, and

aligned to an address divisible by

UNIV_PAGE_SIZE */

/* ... */

}

class buf_page_t {

public:

/** @name General fields

None of these bit-fields must be modified without holding

buf_page_get_mutex() [buf_block_t::mutex or

buf_pool->zip_mutex], since they can be stored in the same

machine word. */

/* @{ */

/** Page id. */

page_id_t id;

/** Page size. */

page_size_t size;

/** Count of how manyfold this block is currently bufferfixed. */

uint32_t buf_fix_count;

/** type of pending I/O operation. */

buf_io_fix io_fix;

/** Block state. @see buf_page_in_file */

buf_page_state state;

/* ... */

}

2. 页面管理机制

InnoDB 基于 LRU 算法管理 buffer pool 中的数据页。一般情况下 list 头部存放的是热数据,就是所谓的 young page(最近经常访问的数据),list 尾部存放的就是 old page(最近不被访问的数据)。

LRU List:缓存了所有读入内存的数据页。包含三类:

未修改的页面,可以从该链表中摘除,然后移到 Free List 中;

已修改还未刷新到磁盘的页面;

已修改且已经刷新到磁盘的页面,可并为第一类。

Free List:空闲内存页列表,需要装载(缓存)磁盘上数据页的时候,从此列表取内存块。

Flush List:在内存中被修改但还没有刷新到磁盘的数据页(脏页)链表,内存中的数据跟对应磁盘上的数据不一致,属于该链表的页同样存在于 LRU List 中,但反之未必。

How read a page?

当访问的页面在缓存池中命中,则直接从缓冲池中访问该页面。如果没有命中,则需要将这个 page 从磁盘上加载到缓存池,因此需要在缓存池中的 Free List 中找一个空闲的内存页来缓存这个从磁盘读入的 page。

但存在空闲内存页被使用完的情况,不保证一定有空闲的内存页。假如 Free List 为空,则需要想办法产生空闲的内存页。 首先是在 LRU List 中找可以替换的内存页,查找方向是从列表的尾部开始找,如果找到可以替换的 page,将其从 LRU List 中摘除,加入 Free List,然后再去 Free List 中找空闲的内存页。第一次查找最多只扫描 100 个 page,循环进行到第二次时,查找深度就是整个 LRU List。这就是 LRU List 的页面淘汰机制。

如果在 LRU List 中没有找到可以替换的页,则进行单页刷新,将脏页刷新到磁盘后,再将释放的内存页加入到 Free List,最后再去 Free List 取。为什么只做单页刷新呢?因为它的目的是获取空闲内存页,进行脏页刷新是不得已而为之,所以只会进行一个页的刷新,目的是为了尽快的获取空闲内存页。

因为 Free List 是一个公共的链表,所有的用户线程都可以使用,存在争用的情况。因此,自己产生的空闲内存页有可能会刚好被其它线程所使用,因此用户线程可能会重复执行上面的查找流程,直到找到空闲的内存页为止。

通过数据页访问机制,可以知道当无空闲页时产生空闲页就成为了一个必须要做的事情。

如果需要通过刷新脏页来产生空闲页或者需要扫描整个 LRU List 来产生空闲页,查找空闲页的时间就会延长,这是一个 bad case。

因此,innodb buffer pool 中存在大量可以替换的页,或者 Free List 中一直存在着空闲内存页,对快速获取空闲内存页就起到了决定性的作用。

而在 innodb buffer pool 的机制中,是采用何种方式来产生空闲内存页以及可以替换的内存页呢?这就是下面要讲的内容——脏页刷新策略。

How to flush a dirty page?

MySQL线程后台会有flush线程,定期地将flush list的脏页flush到磁盘上,这样可以减轻check point的开销,和页面替换时,那些被替换页面的flush开销,而使得读取页面时间增长。flush list的页面根据修改的时间从新到老进行排序,也即是最新的修改,在flush list的头部,最老的修改在flush list的尾部。当flush时,从尾部取page flush到磁盘上。这样的逻辑是跟checkpoint保持一致,checkpoint的流程也是从老到新一步步持久化page,所以可以加快checkpoint。

When to flush dirty page?

后台线程定期刷;

redo log 写满了(强制刷);

内存不足(强制刷)。

参考:

mysql内存机制_MySQL内存管理机制相关推荐

  1. mysql内存工作机制_MySQL内存使用机制

    对于任何一个数据库管理系统来说,内存的分配使用绝对可以算的上是其核心之一了,所以很多希望更为深入了解某数据库管理系统的人,都会希望一窥究竟,我也不例外. 从内存的使用方式MySQL 数据库的内存使用主 ...

  2. mysql select 缓存_mysql select缓存机制使用详解

    mysql Query Cache 默认为打开.从某种程度可以提高查询的效果,但是未必是最优的解决方案,如果有的大量的修改和查询时,由于修改造成的cache失效,会给服务器造成很大的开销,可以通过qu ...

  3. mysql 线程内存 回收_MySQL内存使用-线程独享

    对于任何一个数据库管理系统来说,内存的分配使用绝对可以算的上是其核心之一了,所以很多希望更为深入了解某数据库管理系统的人,都会希望一窥究竟,我也不例外. 从内存的使用方式MySQL 数据库的内存使用主 ...

  4. mysql 内存调整_mySQL内存及虚拟内存优化设置

    为了装mysql环境測试,装上后发现启动后mysql占用了非常大的虚拟内存,达8百多兆. 网上搜索了一下,得到高人指点my.ini. 再也没见再具体的了..仅仅好打开my.ini逐行的啃,虽然英文差了 ...

  5. JVM内存区域划分及其管理机制

    java 虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,如图.各个区域有各自的用途,以及创建时间和销毁时间,有的区域随着虚拟机进程启动而存在,有些区域则依赖用户线程的启 ...

  6. mysql的proxy机制_MySQL Proxy工作机制浅析

    MySQL Proxy处于客户端应用程序和MySQL服务器之间,通过截断.改变并转发客户端和后端数据库之间的通信来实现其功能,这和WinGate之类的网络代理服务器的基本思想是一样的.代理服务器是和T ...

  7. mysql内存数据库性能_Mysql内存表配置及性能测试

    centos7 mysql数据库安装和配可以参考一下文章,基本照做就可以了(我选的方法二): http://www.cnblogs.com/starof/p/4680083.html 说到内存表,首先 ...

  8. mysql内存释放_MySQL内存不释放

    欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入 连接了一下,并进行了一次查询操作 (root:NJ-245:Thu Apr 24 16:38:38 2014)[infor ...

  9. mysql内存持续上涨_MySql内存增长过快导至崩溃的问题

    本帖最后由 annatrov 于 2012-9-24 10:32 编辑 我服务器配置是:Linux 5.5 CPU:16核,内存:64GB    MySql 5.5.18 问题是: MySQL稳定运行 ...

最新文章

  1. Python 虚拟环境 virtualenv
  2. perl脚本的默认参数
  3. acdream 1023 xor按位思考
  4. 在 Apex 代码中生成 csv 文件
  5. MATLAB说文本命令超过,MATLAB基础
  6. 管壁式换热器cad图纸_一文详解换热器技术问答,真的都是珍藏版!
  7. Qt显示wav波形图
  8. 新元宇宙奇科幻小说原创作品每周连载地球人奇游天球记第六回冬奥登月
  9. 计算机机房消房安全管理制度,计算机机房消防安全管理制度
  10. 模拟器连接本地服务器
  11. PowerPoint PPT 模板插入可修改的文本框
  12. html5 audio左侧,HTML5之Audio(四)—— 左右声道
  13. 单工通信、半双工通信和全双工通信的区别
  14. 机器人竟会写诗,诗人们大呼不敢相信!
  15. 情绪是人生最大的敌人
  16. NVIDIA GeForce RTX 2070显卡参数
  17. GDOI2016 退役记
  18. Xshell的快捷键(非常实用)
  19. STM2F407ZGT6和NBIOT模块链接华为云
  20. Silvaco学习笔记——Save,log

热门文章

  1. 动画原理——用户交互:移动物体
  2. OSMeteorTranslationAPI(百度,有道)对比
  3. 集成UG和ANSYS之二----upupdate之x_t
  4. Every Woman is beautiful
  5. 什么是贝叶斯定理?朴素贝叶斯有多“朴素”?终于有人讲明白了
  6. 相关和因果是一回事吗?R值低就是不相关?终于有人讲明白了
  7. 指引趋势和方向!2019开发者技能报告出炉!!
  8. 阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法
  9. 日志Loki基妹出,便胜却ELK无数
  10. 微信小程序wepy框架资源汇总