zoukankan      html  css  js  c++  java
  • innodb buffer pool

    add page to flush list

    buffer pool中的page,有三种状态:

    l  free:      当前page未被使用

    l  clean:    当前page被使用,对应于数据文件中的一个页面,但是页面未被修改

    l  dirty:     当前page被使用,对应于数据文件中的一个页面,同时页面被修改

    free类型的page,一定位于buf pool的free链表中。

    clean,dirty两种类型的page,一定位于buf pool的LRU链表中。(LRU:近期最少使用)

    与此同时,dirty page还位于buf pool的flush链表中。flush list中的dirty page,按照page的oldest_modificattion时间排序,oldest_modification越大,说明page修改的时间越晚,就排在flush 链表的头部;oldest_modification越小,说明page修改的时间越早,就排在flush链表的尾部。当InnoDB进行flush list的flush操作时,从flush list链表的尾部开始,写出足够数量的dirty pages,推进Checkpoint点,保证系统的恢复时间。

    dirty page越新的,排在头部;越老的,排在尾部。

    将比较老的数据,写出去。

    那么,dirty page是在什么时候进入flush list的呢?看过我以前文档的同学,一定知道InnoDB存储引擎有一个所谓的mini-transaction,页面访问/修改都被封装为一个mini-transaction,当mini-transactin提交的时候,也就是该mini-transaction修改的页面进入flsuh list的时候。

    remove page from flush list

    有两种操作,可以将dirty page从flush list中移除。一是LRU list flush;二是Flush list flush。

    Buffer Pool LRU/Flush List flush对比

    总结来说,Flush lish flush与LRU list flush有以下几个不同之处:

    LRU list flush,由用户线程触发(MySQL 5.6.2之前);而Flush list flush由MySQL数据库InnoDB存储引擎后台srv_master线程处理。(在MySQL 5.6.2之后,都被迁移到page cleaner线程中)

    LRU list flush,其目的是为了写出LRU 链表尾部的dirty page,释放足够的free pages,当buf pool满的时候,用户可以立即获得空闲页面,而不需要长时间等待;Flush list flush,其目的是推进Checkpoint LSN,使得InnoDB系统崩溃之后能够快速的恢复。

    LRU list flush,其写出的dirty page,需要移动到LRU链表的尾部(MySQL 5.6.2之前版本);或者是直接从LRU链表中删除,移动到free list(MySQL 5.6.2之后版本)。Flush list flush,不需要移动page在LRU链表中的位置。

    LRU list flush,由于可能是用户线程发起,已经持有其他的page latch,因此在LRU list flush中,不允许等待持有新的page latch,导致latch死锁;而Flush list flush由后台线程发起,未持有任何其他page latch,因此可以在flush时等待page latch。

    LRU list flush,每次flush的dirty pages数量较少,基本固定,只要释放一定的free pages即可;Flush list flush,根据当前系统的更新繁忙程度,动态调整一次flush的dirty pages数量,量更大。

    Buffer Pool Usage Limitations

    此章节记录Buffer Pool的各种使用缺陷,及不同版本的优化策略。

    Drop Table

    在Mark Callaghan的最新一篇博文:Stalls during DDL中[6](备注:mysqlops网站上也有相关文章分析这个严重问题,链接地址:http://www.mysqlops.com/2012/04/01/mysql-innodb-file-per-table.html),其提到InnoDB存储引擎在进行Drop Table操作时,会短暂hang住整个系统,而且这个hang的时间的长短与Buffer Pool的大小相关。主要原因在于InnoDB在drop table时,会连续两次遍历buf pool LRU 链表,遍历的过程加锁,因此导致系统hang住。那么MySQL数据库InnoDB存储引擎在drop table时为何需要遍历LRU链表呢?

    // 1. 从LRU链表尾部开始遍历

    // 2. 对于每一个属于Drop Table的page,判断page中是否有项进入

    //      adaptive hash,若有,则收集当前page

    // 3. 收集到1024个这样的page后,释放buf pool mutex,集中调用函数

    //      buf_LRU_drop_page_hash_batch,释放page在adaptive hash中的项

    // 4. 重新获取buf pool mutex,继续遍历buf pool LRU 链表,直至链表头

    // 5. 最终,是否buf pool mutex,退出

    // 再次遍历buf pool LRU 链表,释放所有drop table对应的page

    buf_LRU_invalidate_tablespace_buf_pool_instance();

    // 简要的处理流程描述:

    // 1. 获取buf pool mutex

    // 2. 遍历buffer pool LRU链表

    // 3. 若为dirty page,则将dirty page设置为clean page,并从flush list中移除

    // 4. 将page从LRU list中移除,并且添加入free list

    // 5. 最后,释放buf pool mutex

    总结:

    l  确实需要遍历两遍buf pool LRU 链表

    一遍用于释放adaptive hash中的记录;二遍是用于释放page。

    l  第一遍遍历LRU链表,会定期释放buf pool mutex,因此对于系统hang的影响较小;而第二遍会一直持有,对系统hang的影响较大。

  • 相关阅读:
    JDK6和JDK7中的substring()方法
    考试结束
    今天之总结
    暂别
    珍惜
    放弃
    我男神
    心态
    稳住,我或许能赢
    还是做好自己吧
  • 原文地址:https://www.cnblogs.com/yuyue2014/p/4109130.html
Copyright © 2011-2022 走看看