当前位置:Gxlcms > 数据库问题 > 原创mysql内核源代码深度解析 缓冲池 buffer pool 整体概述

原创mysql内核源代码深度解析 缓冲池 buffer pool 整体概述

时间:2021-07-01 10:21:17 帮助过:2人阅读

frame则是bufpool部门真正服务的核心所在,这是非压缩页(数据页,undo页,特殊页。。。。。。)的页帧地址。一旦某页记录读入通过read模块读入链表进行管理之后,那么它的所有modify操作等同于都是针对这个页帧里面做内存修改,至于写回磁盘是异步(同步)IO需要考虑的事情(详解文件存储子系统的时候会对IO机制作出完整说明)。

压缩页控制块(buf_page_struct),理论上讲,全部的非压缩页只是压缩页的子集(实际情况有待本人进一步验证),因为在进行核心操作的时候,都是在非压缩页中进行,因此压缩页控制块(buf_page_struct)并不包含互斥体,但是为了保证与(buf_block_struct)的一致,需要进行锁计数器的实现,另外,它还包含对应物理页的表空间id、表空间内页的偏移量、页状态、刷新类型(上文介绍过BUF_FLUSH_LRU和BUF_FLUSH_LIST)、压缩页对应引用、所在hash表、5大链表(unzip_LRU在非压缩页结构体对象(buf_block_struct)所以此处才是剩下的5个链表)的子节点(UT_LIST_NODE_T)、以及是否处于OLD_LRU端(LRU链表结构old部分)是否崩溃页初次访问时间等细节,这些也仅仅是列举出的最重要结构体对象而已,不是全部。

struct buf_page_struct{

       unsigned      space:32;     /*!<tablespace id; also protected

                                   bybuf_pool->mutex. */

       unsigned      offset:32;     /*!<page number; also protected

                                   bybuf_pool->mutex. */

。。。。。。

       unsigned      flush_type:2;      /*!< if this block is currently being

                                   flushedto disk, this tells the

                                   flush_type.

                                   @seeenum buf_flush */

       unsigned      io_fix:2;       /*!<type of pending I/O operation;

                                   alsoprotected by buf_pool->mutex

                                   @seeenum buf_io_fix */

       unsigned      buf_fix_count:19;/*!< count of howmanyfold this block

                                   iscurrently bufferfixed */

。。。。。。

       UT_LIST_NODE_T(buf_page_t)free;

       UT_LIST_NODE_T(buf_page_t)flush_list;

       UT_LIST_NODE_T(buf_page_t)zip_list;

。。。。。。

};

(3)六个重要链表

技术分享

再次,子系统组件与基础控制结构体运作的过程要实现各种复杂功能,必然无法脱离6个重要的链表,

空闲链表(buf_pool->free),bufpool最重要的三个链表之一,上文已经多次提到LRU和flush等链表,但未提到空闲链表,实际上它是在系统初始化阶段bufpool进行初始化后唯一显式调用链表初始化函数进行init操作的唯一bufpool链表。系统内的第一个LRU链表块,必然是从free链表中获取到的,当flush模块脏页刷新完成,LRU链表节点就会被清除或者移动到LRU链表结尾等待清除,清除LRU之后的节点仍旧是回归到free链表内。

LRU链表(buf_pool->LRU),bufpool最重要的三个链表之二,当有LRU链表为空时,必然从free链表获取空闲节点,并进行异步IO读将页读入bufpool,并加入LRU链表,LRU链表长度过大的情况下,会进行尾部刷新,刷新失败会进行更彻底的直接通过LRU进行脏页刷新(BUF_FLUSH_LRU方式),flush链表节点得到释放脏页完成刷新,并同时把LRU链表的脏块也完成移除。可以说LRU和free、flush三个链表、5个模块有之间有着千丝万缕的联系。

非压缩LRU链表(buf_pool->unzip_LRU),本链表实际是LRU链表的一个子集,在压缩页控制块(buf_page_struct)中的压缩页需要进行解压缩以进行各种记录级读写操作时,该链表将发挥作用,因此可以说,插入到了unzip_LRU链表就一定页在LRU链表中,反之则未必。

脏块链表(buf_pool->flush_list),bufpool最重要的三个链表之二,实际上也是LRU链表的子集,所以读入bufpool的页都通过压缩的或者非压缩的控制块进行管理,最初一定是在LRU链表中,当事务部分(和mini事务部分)完成commit操作时候,实际上就意味着内存写的成功,脏页必然要加入flush链表,并等待异步IO线程(系统主线程子系统组成之一)进行刷新操作(linux原生异步IO和作者Heikki Tuuri自己用条件变量实现的模拟异步IO,buf_pool_struct提到过,存储部分会做详细说明)动作。

未修改压缩块链表(buf_pool->zip_clean),本链表以目前的源代码来看仅用于调试功能。

伙伴系统空闲链表(buf_pool->zip_free[]),bufpool6大链表中最特殊的一个,链表的根节点可以看做“是一个指针数组”,伙伴系统的精髓就在于按照2的倍数进行紧邻内存块的合并和拆分,进而达到高效管理、代码复杂度低的效果。这个指针数组按照块大小实际包含4层,1024,2048,4096和8192,每一层基结点只管理同类大小的块。


关于bufpool部分的整体概述,暂时告一段落,后续还会陆续添加新的内容,并作进一步整理。老刘会坚持把这个分析一直做下去。如有兴趣的朋友也可以QQ加本人私聊:275787374,随时欢迎。

下一部分会将LRU进行详解。如发现文章中的任何错误欢迎朋友们指正。

原创mysql内核源代码深度解析 缓冲池 buffer pool 整体概述

标签:

人气教程排行