美文网首页
MySQL-Innodb-LRU

MySQL-Innodb-LRU

作者: 多血 | 来源:发表于2020-10-18 22:58 被阅读0次

    参数
    状态


    image.png

    made young表示old页移动到LRU头部,not young表示的是访问的old区的页,但是访问这页的时间与上次访问这个页的时间小于innodb_old_blocks_time,不需要移动到LRU的头部。
    LRU的插入,删除,以及make young。

    buf_page_get_gen
    ----buf_read_page /* 页如果需要从硬盘中读取的话,需要加入到LRU队列中。 */
    --------buf_read_page_low
    ------------buf_page_init_for_read
    ----------------buf_LRU_add_block(bpage, TRUE/* to old blocks */);
    --------------------buf_LRU_add_block_low
    ----buf_page_make_young_if_needed
    --------if (buf_page_peek_if_too_old(bpage)) {
                buf_page_make_young(bpage);
             }
    

    buf_LRU_add_block_low的具体逻辑,如果当前LRU的长度小于BUF_LRU_OLD_MIN_LEN,直接插入到LRU的头部,否则插入到old的头部,同时buf_LRU_old_adjust_len调整LRU。

    /******************************************************************//**
    Adds a block to the LRU list. Please make sure that the page_size is
    already set when invoking the function, so that we can get correct
    page_size from the buffer page when adding a block into LRU */
    UNIV_INLINE
    void
    buf_LRU_add_block_low(
    /*==================*/
        buf_page_t* bpage,  /*!< in: control block */
        ibool       old)    /*!< in: TRUE if should be put to the old blocks
                    in the LRU list, else put to the start; if the
                    LRU list is very short, the block is added to
                    the start, regardless of this parameter */
    {
        buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
    
        if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
    
            UT_LIST_ADD_FIRST(buf_pool->LRU, bpage);
    
            bpage->freed_page_clock = buf_pool->freed_page_clock;
        } else {
            UT_LIST_INSERT_AFTER(buf_pool->LRU, buf_pool->LRU_old,
                bpage);
            buf_pool->LRU_old_len++;
        }
    
        incr_LRU_size_in_bytes(bpage, buf_pool);
    
        if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
            /* Adjust the length of the old block list if necessary */
            buf_page_set_old(bpage, old);
            buf_LRU_old_adjust_len(buf_pool);
    
        } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
            /* The LRU list is now long enough for LRU_old to become
            defined: init it */
            buf_LRU_old_init(buf_pool);
        } else {
            buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
        }
    
        /* If this is a zipped block with decompressed frame as well
        then put it on the unzip_LRU list */
        if (buf_page_belongs_to_unzip_LRU(bpage)) {
            buf_unzip_LRU_add_block((buf_block_t*) bpage, old);
        }
    }
    

    buf_page_make_young_if_needed用来判断是否page是否需要移动到LRU列表的头部。如果page在old区,并且本次时间减去上次访问时间大于innodb_old_blocks_time,不移动,否则移动到LRU列表的头部,移动后还需要调整下列表

    /********************************************************************//**
    Recommends a move of a block to the start of the LRU list if there is danger
    of dropping from the buffer pool. NOTE: does not reserve the buffer pool
    mutex.
    @return TRUE if should be made younger */
    UNIV_INLINE
    ibool
    buf_page_peek_if_too_old(
    /*=====================*/
        const buf_page_t*   bpage)  /*!< in: block to make younger */
    {
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
    
        if (buf_pool->freed_page_clock == 0) {
            /* If eviction has not started yet, do not update the
            statistics or move blocks in the LRU list.  This is
            either the warm-up phase or an in-memory workload. */
            return(FALSE);
        } else if (buf_LRU_old_threshold_ms && bpage->old) {
            unsigned    access_time = buf_page_is_accessed(bpage);
    
            /* It is possible that the below comparison returns an
            unexpected result. 2^32 milliseconds pass in about 50 days,
            so if the difference between ut_time_monotonic_ms() and
            access_time is e.g. 50 days + 15 ms, then the below will behave
            as if it is 15 ms. This is known and fixing it would require to
            increase buf_page_t::access_time from 32 to 64 bits. */
            if (access_time > 0
                && ((ib_uint32_t) (ut_time_monotonic_ms() - access_time))
                >= buf_LRU_old_threshold_ms) {
                return(TRUE);
            }
    
            buf_pool->stat.n_pages_not_made_young++;
            return(FALSE);
        } else {
            return(!buf_page_peek_if_young(bpage));
        }
    }
    

    buf_page_get_gen简化版

    /** This is the general function used to get access to a database page.
    @return pointer to the block or NULL */
    buf_block_t*
    buf_page_get_gen(
        const page_id_t&    page_id,
        const page_size_t&  page_size,
        ulint           rw_latch,
        buf_block_t*        guess,
        ulint           mode,
        const char*     file,
        ulint           line,
        mtr_t*          mtr,
        bool            dirty_with_no_latch)
    {
        buf_block_t*    block;
        unsigned    access_time;
        rw_lock_t*  hash_lock;
        buf_block_t*    fix_block;
        ulint       retries = 0;
        buf_pool_t* buf_pool = buf_pool_get(page_id);
    
        buf_pool->stat.n_page_gets++;
        hash_lock = buf_page_hash_lock_get(buf_pool, page_id);
    loop:
        block = guess;
    
        if (block == NULL) {
            block = (buf_block_t*) buf_page_hash_get_low(buf_pool, page_id);
        }
    
        if (!block || buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
            rw_lock_s_unlock(hash_lock);
            block = NULL;
        }
    
        if (block == NULL) {
            /* Page not in buf_pool: needs to be read from file */
    
            if (buf_read_page(page_id, page_size)) {
                buf_read_ahead_random(page_id, page_size,
                              ibuf_inside(mtr));
    
                retries = 0;
            } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
                ++retries;
            } else {
                /* 打印错误日志*/
            }
            goto loop;
        } else {
            fix_block = block;
        }
    
    
    got_block:
    
    
        /* Check if this is the first access to the page */
        access_time = buf_page_is_accessed(&fix_block->page);
    
        /* This is a heuristic and we don't care about ordering issues. */
        if (access_time == 0) {
            buf_page_set_accessed(&fix_block->page);
        }
    
        if (mode != BUF_PEEK_IF_IN_POOL) {
            buf_page_make_young_if_needed(&fix_block->page);
        }
    
    
        if (mode != BUF_PEEK_IF_IN_POOL && !access_time) {
            /* In the case of a first access, try to apply linear
            read-ahead */
    
            buf_read_ahead_linear(page_id, page_size, ibuf_inside(mtr));
        }
    
        return(fix_block);
    }
    

    相关文章

      网友评论

          本文标题:MySQL-Innodb-LRU

          本文链接:https://www.haomeiwen.com/subject/ggchmktx.html