设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 重新 试卷 文件
当前位置: 首页 > 服务器 > 安全 > 正文

2017数据库大会实录-MySQL核心参数含义的源码解析(2)

发布时间:2021-01-17 06:15 所属栏目:53 来源:网络整理
导读:在实现上面两个功能的同时,需要考虑客观条件的限制,因为机器的内存大小是有限的,所以mysql的innodb buffer ?pool的大小同样是有限的.在通常的情况下,当数据库的数据量比较大的时候,缓存池并不能缓存所有的数据页,所

在实现上面两个功能的同时,需要考虑客观条件的限制,因为机器的内存大小是有限的,所以mysql的innodb buffer ?pool的大小同样是有限的.在通常的情况下,当数据库的数据量比较大的时候,缓存池并不能缓存所有的数据页,所以也就可能会出现,当需要访问的某个页面时,该页面却不在缓存池中的情况,这个时候就需要从磁盘中将这个页面读出来,加载到缓存池中,然后再去访问.这样就涉及到随机的物理io,也就延长了访问页面所消耗的时间.

这样的情况是一个bad case,是我们期望尽量避免的——因此需要想办法来提高缓存的命中率.?innodb buffer pool采用经典的LRU列表算法来进行页面淘汰,以提高缓存命中率.将缓存的页面按照最近使用的次数跟时间进行排序,队列最末尾的页面将会最先被淘汰.这个机制在后面会结合源码详细讲解.同时,在LRU列表的中间位置打了一个old标识,可以简单的理解为将LRU列表分为两个部分,这个标记到LRU列表头部的页面称之为yong的页面,这个标志到LRU列表尾部的页面称之为old页面.再进行抽象的话,我们简单地理解为缓存池被分成两个池子,一个叫young池子,一个叫old池子.当一个页面从磁盘上加载缓存池中的时候,会将它排放在这个old标识之后的第一个位置,也就是说放在了old池子中.这个机制的作用就是,在做大表的一次性全表扫描的时候,大量新进来的页面,是存放在old池子中的,当old池子的大小不够缓存新进来的页面的时候,也只是在old池子中内部进行循环冲洗,这样就不会冲洗young池子中的热点页面,从而保护了热点页面.这就是LRU列表的机制.

另外,前面我们讲到页面更新是在缓存池中先进行的,所以需要考虑这些被修改的页面什么时候刷新到磁盘?以什么样的顺序刷新到磁盘?在innodb buffer pool中,采用的方式是将页面在缓存中的按照第一次修改时间,也就是变成脏页的时间进行排序,flush列表进行排序,由后台刷新线程依次刷新到磁盘,实现修改落地到磁盘.

我们简单介绍了buffer pool的工作机制,我们现在来看buffer pool 里面最重要的三个列表,前面已经讲了两个列表,LRU列表以及flush列表,也就是脏页刷新列表.现在再补充一个列表——空闲列表.空闲列表中的内存块,是没有存放任何数据页的内存块.当没有在缓存池中的页面需要被访问时,它需要先被加载到缓存池中,从而需要从空闲列表中取出一个空闲内存块来缓存这个页面.

在这里提一下,一个bufferpool 可能会分成好几个buffer pool instance,在mysql5.7中,如果不显示设置innodb_buffer_pool_instances这个参数,当innodb buffer size 大于1G的时候,就会默认会分成8个instances,如果小于1G,就只有1个instance.

下面我们来看一下一个数据页的访问流程.

1.? 当访问的页面在缓存池中命中,则直接从缓冲池中访问该页面.

2.? 如果没有命中,则需要将这个页面从磁盘上加载到缓存池中,因此需要在缓存池中的空闲列表中找一个空闲的内存块来缓存这个从磁盘读入的页面.

3.? 但存在空闲内存块被使用完的情况,不保证一定有空闲的内存块.假如空闲列表为空,没有空闲的内存块,则需要想办法去产生空闲的内存块.

4.? 首先去LRU列表中找可以替换的内存页面,查找方向是从列表的尾部开始找,如果找到可以替换的页面,将其从LRU列表中摘除,加入空闲列表,然后再去空闲列表中找空闲的内存块.这就是LRU列表中的页面淘汰机制.

5.? 如果在LRU列表中没有找到可以替换的页,则在列表最末尾选择一个页面进行刷新,刷新后加入空闲列表,然后再去空闲列表中取空闲内存块.

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

画图跟表述可能没有完全清楚地表达,下面我们来看一下查找空闲内存块的源代码:

这个函数的名称是buf_LRU_get_free_block,单纯从函数的命名来看,我们就能大概猜出这个函数的作用——-获取空闲的内存块.我们来解析这个函数:

1.? 首先看函数的开头部分——我们直接看代码注释,ifthere is a block in the free list,take it .从空闲列表中去获取block,如果获取到,就返回. 这个return,是该函数的唯一返回出口,也就是一定要找到空闲的block才返回,否则一直循环找下去.

2.? 如果没有找到,则从LRU列表的尾部开始找可以替换的BLOCK,第一次查找最多只扫描100个页面,循环进行到第二次时,会查找深度就是整个LRU列表.如果找到可以替换的页,则将其加入到空闲列表,然后再去空闲列表中找.

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

中间还有一些细节,包括设置刷新事件,以请求后台刷新线程进行脏页刷新,以及当进行第三次循环时,线程自己先sleep 10 毫秒,然后再去做页面刷新.这些将不再祥描.

通过了解了空闲页面的查找流程之后,我们知道,如果需要刷新脏页来产生空闲页面或者需要扫描整个LRU列表来产生空闲页面的时候,查找空闲内存块的时间就会延长,这个是一个base case,是我们希望尽量避免的.因此,innodb buffer pool 中存在大量可以替换的页面,或者free 列表中一直存在着空闲内存块,对快速获取到空闲内存块起决定性的作用.?在innodbbuffer pool的机制中,是采用何种方式来产生的空闲内存块,以及可以替换的内存页的呢?这就是我们下面要讲的内容——通过后台刷新机制来产生空闲的内存块以及可以替换的页面.

在讲innodb buffer pool的刷新机制之前,我们再来简单看一下有关buffer pool 的参数,这些参数将在后面的源码解析中使用到.

这就是我们接下来要讲的内容:这些函数是跟缓存池后台页面刷新相关的函数.后台刷新的动作由后台刷新协调线程触发,该线程的所有工作内容均由

buf_flush_page_cleaner_coordinator函数完成,我们后面简称它为协调函数.

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读