MySQL数据库InnoDB存储引擎 Buffer Pool页面分配详解 - 图文
更新时间:2023-10-17 21:57:01 阅读量: 综合文库 文档下载
MySQL数据库InnoDB存储引擎 Buffer Pool页面分(innodb_buffer_pool_size)
当用户需要读取一个在外存中的页面,或者是分配一个新的页面进行插入,就需要调用
buf0flu.cc::buf_LRU_get_free_block函数进行页面的分配。一个完整的MySQL数据库InnoDB存储引擎页面分配流程需要包含以下几个步骤:
1.尝试从Buffer Pool的free list中分配新页面,大部分情况下,Buffer Pool的free list都是包含空闲页面的,因此直接分配即可。分配出的页面,需要从free list中删除。
2.若Buffer Pool的free list中不存在空闲页面,同时当前系统正在进行BUF_FLUSH_LRU类型的flush (buf_pool->init_flush[BUF_FLUSH_LRU] == TRUE),则等待flush完成,然后跳转到1重新分配。 3.遍历LRU链表,寻找其中的非脏页面,将这些页面从LRU链表中摘除,并插入free list
(buf_LRU_scan_and_free_block ->buf_LRU_free_from_common_LRU_list)。从LRU链表的尾部开始向前遍历,第一次遍历srv_LRU_scan_depth = 1024个page,之后每次遍历整个LRU链表。
buf_LRU_free_from_common_LRU_list函数从LRU链表的尾部遍历,对于遇到的每一个page,调用函数buf_LRU_free_block尝试释放当前page。buf_LRU_free_block是一个极为复杂的函数,其简要流程如下:
a) 判断page是否被pin在内存中(buf_page_can_relocate()),若page被pin住,则说明不能释放此page,直接返回。
b) 判断page是否是脏页(bpage->oldest_modification),若page为脏页,则说明不能释放此page,直接返回。
c) 不满足以上条件,page可以释放。首先将page从LRU list与buf pool的page hash中删除(buf_LRU_block_remove_hashed_page)。
d) 判断当前page的类型,若为zip page,需要做特殊处理,此处暂时略过不表。 e) page中的记录,若存储在btr_search_sys->hash_index中,则从此hash表中删除(btr_search_drop_page_hash_index())。在调用此函数时,需要释放buf pool的
mutex(buf_pool_mutex_exit()),考虑到同时有多个线程可以同时调用此函数,并且将此page标识为可替换page。因此,在释放buf pool mutex之前,将page标识为pin在内存中,不可被替换(buf_page_set_sticky())。 备注:
此处的hash表是MySQL数据库InnoDB存储引擎提供的adaptive hash index,记录级别的hash index (存储记录项到索引页面的映射)。通过参数innodb_adaptive_hash_index,可以控制是否使用此hash index。若参数设置为true,那么在做scan查询时(btr_cur_search_to_nth_level),就会调用
btr_search_guess_on_hash函数就行hash index的查询,若存在则可以直接定位到对应的叶页面,减少了search path的代价。
关于InnoDB adaptvie hash index,后续将会做更为详尽的分析,此处简单说明其功能,页面被替换出去时,需要将页面中的记录从hash index中删除。除此之外,adaptive hash index系统中只有一个,使用全局的btr_search_latch来保护,因此存在着并发性能问题。
f) 在page中的所有记录,均从btr_search_sys hash表中删除之后,重新获取buf pool mutex。并将page上的pin标识删除。然后将page添加到buf pool的free链表中(buf_LRU_block_free_hashed_page -> buf_LRU_block_free_non_file_page)。 g) 至此,一个clean page的释放过程完成。
h) 同时,InnoDB存储引擎还做了一个统计,当page是clean,可以被选择为替换page,同时判断page是否被访问过(buf_page_is_accessed)。若page未被访问过,那么增加统计计数
buf_pool->stat.n_ra_pages_evicted。表示当前page是一个read ahead page,但是却是无效的read ahead。
4.若步骤3,遍历LRU链表,成功释放一个clean page,那么再次扫描buf pool的free list,就会找到空闲page,加以利用。成功返回即可。
5.若步骤3未成功释放一个clean page,则继续进行下一个动作:从LRU链表中flush一个dirty page,然后释放此page (buf_flush_single_page_from_LRU())。注意,此时由于处于用户线程之中,因此只flush一个page即可,保证用户的响应时间。
a) 从LRU链表的尾部遍历,找寻第一个可以立即被flush的page (buf_flush_ready_for_flush)。可以立即被flush的page需要满足以下要求:脏页,在FLUSH链表中;未被pin在内存中;
b) 若找到一个可以立即flush的page,则调用函数buf_flush_page将当前page写到磁盘中,同时设置flush type为BUF_FLUSH_SINGLE_PAGE。buf_flush_page函数中,主要需要将page pin在内存中(buf_page_set_io_fix(BUF_IO_WRITE));设置buf pool对应flush类型的数量;最后调用buf_flush_write_block_low函数写出page。
c) 一个被写出的dirty page,在写出之前,需要做一些额外处理,包括:将此page的最新修改的lsn (newest_lsn)写到页头/页尾;重新计算页面的页头checksum (buf_calc_page_new_checksum)与页尾checksum (buf_calc_page_old_checksum)。
d) 注意 页头checksum的计算,需要读取整个页面中的所有数据(一次读取1 byte);页尾checksum的计算,只需要读取页面的前26 bytes即可。而且,需要先计算页头checksum,写入page,然后再计算页尾checksum。在MySQL 5.6.3之后,InnoDB提供了新的checksum计算方法(crc32),同时新增了系统参数innodb_checksum_algorithm来设置不同的checksum算法。
e) 前面的buf_flush_page函数负责将page写出到disk,但是并不保证page一定被写到磁盘之上。仍旧需要调用函数buf_flush_sync_datafiles将写fsync到磁盘之上。
f) 当写出完全flush到磁盘之后,需要重新在buf pool的LRU链表中定位page,因为在写page时,会释放buf pool mutex以及页面mutex,因此当写完成之后,不能再继续使用原有的page内存结构,可能已经被其他的线程释放。
g) 重新定位到page之后,再次调用buf_LRU_free_block函数,判断当前page是否可以被从LRU链表中摘除。
6.buf_flush_single_page_from_LRU函数返回,无论是否成功flush一个dirty page,均再次尝试一个新的分配free page的循环。当完成20次循环之后,若仍旧不能找到一个可用的page,打出warnning,要求管理员增加buf pool的大小。
7. 疑问:在buf_flush_single_page_from_LRU中,flush一个page时,何时将page从LRU链表与flush链表中摘除?
a) MySQL数据库InnoDB存储引擎中,无论是日志文件/数据文件的读写操作,当完成之后,会调用buf_page_io_complete函数(异步读/写操作,由后台的io_handler_thread线程组处理;同步读/写操作,由发起读/写操作的线程本身处理)。针对于dirty page的写操作,此函数进而调用buf_flush_write_complete函数,将page从flush链表中摘除(buf_flush_remove);设置in_flush_list为false;同时将页面的oldest_modification设置为0,标识当前页面为clean page,位于LRU链表中的clean page,可以被上面提到的流程重用。
b) 如果当前dirty page是有FLUSH LRU完成写出的,那么同时将flush后的clean page移到LRU链表的最后(LRU_old尾部),如此一来,保证下次页面分配可以快速重用此page。
c) 最后,无论是那种写操作,写成功之后,增加buf pool的统计信息:buf_pool->stat.n_pages_written++ 8.当有free page可以使用之后,就可以读取外存页面到内存buf pool之中。前面提到buf_page_io_complete处理写操作的流程,那么该函数又是如何处理读操作的呢? a) 若读到的是一个压缩页面,则将页面解压(buf_zip_decompress)
b) 调用buf_page_is_corrupted函数,判断页面是否已损坏。该函数主要的流程,就是重新计算页面的new checksum与old checksum,然后对比计算出来的checksum与页面中保存的checksum是否一致。若两
个checksum均一致,则页面未损坏,否则返回页面已损坏。
c) 调用ibuf_merge_or_delete_for_page方法,若页面存在insert buffer记录,则合并。 d) 最后,释放页面上的latch与mutex,并返回。
d) 最后,释放页面上的latch与mutex,并返回。
正在阅读:
MySQL数据库InnoDB存储引擎 Buffer Pool页面分配详解 - 图文10-17
管理会计 第四章个人作业答案11-17
对中学语文作业设计依据和原则的几点思考-2019年作文03-11
员工手册致辞02-06
企业融资如何做好风险防控措施03-26
三道岩151景点01-04
房地产金融风险管理及对策文献综述09-13
山东省文综卷文档版(含答案)-2010年普通高等学校招生统一考试05-31
2、电院13级2015年上学期课程表08-10
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 详解
- 分配
- 存储
- 页面
- 图文
- 数据库
- 引擎
- InnoDB
- Buffer
- MySQL
- Pool
- 2012最新题库大全2007-2011生物高考试题分项详解专题汇编 02 细胞的结构和功能
- 优秀班干部发言稿
- 工商总局关于印发《自费出国留学 中介服务合同示范文本》
- 江苏省射阳县盘湾中学高中数学 第1章《三角函数》弧度制教学案 苏教版必修4
- 丘成桐访谈录
- 最新医疗机构病历管理规定()
- “为何从警如何做警为谁用警”大讨论活动心得体会
- 二次竞价报价一览表
- 昌吉州农村环境保护专项资金项目管理暂行办法
- 医学英语词汇B-C
- 奥鹏北语14秋《企业经营战略概论》作业2满分答案
- 端承桩
- 方正春元会计软件备份数据怎么导入AO系统
- 《Visual FoxPro程序设计》期末复习提纲
- 连续退火炉的数模优化设计开题报告
- 2015年春中国石油大学(北京)数控技术 第三阶段在线作业
- 研究生公共英语
- 八年级物态变化2导学案OK2
- 北师大版数学五年级下册第四单元测试题 含答案
- 抗氧化活性 - 图文