diff options
Diffstat (limited to 'storage/innobase/buf/buf0lru.cc')
-rw-r--r-- | storage/innobase/buf/buf0lru.cc | 108 |
1 files changed, 65 insertions, 43 deletions
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 8574a6101e7..7f9f9781874 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -81,6 +81,10 @@ are not blocked for extended period of time when using very large buffer pools. */ #define BUF_LRU_DROP_SEARCH_SIZE 1024 +/** We scan these many blocks when looking for a clean page to evict +during LRU eviction. */ +#define BUF_LRU_SEARCH_SCAN_THRESHOLD 100 + /** If we switch on the InnoDB monitor because there are too few available frames in the buffer pool, we set this to TRUE */ static ibool buf_lru_switched_on_innodb_mon = FALSE; @@ -961,7 +965,7 @@ buf_LRU_free_from_unzip_LRU_list( } for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU), - scanned = 1, freed = FALSE; + scanned = 0, freed = FALSE; block != NULL && !freed && (scan_all || scanned < srv_LRU_scan_depth); ++scanned) { @@ -978,11 +982,13 @@ buf_LRU_free_from_unzip_LRU_list( block = prev_block; } - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_LRU_UNZIP_SEARCH_SCANNED, - MONITOR_LRU_UNZIP_SEARCH_SCANNED_NUM_CALL, - MONITOR_LRU_UNZIP_SEARCH_SCANNED_PER_CALL, - scanned); + if (scanned) { + MONITOR_INC_VALUE_CUMULATIVE( + MONITOR_LRU_UNZIP_SEARCH_SCANNED, + MONITOR_LRU_UNZIP_SEARCH_SCANNED_NUM_CALL, + MONITOR_LRU_UNZIP_SEARCH_SCANNED_PER_CALL, + scanned); + } return(freed); } @@ -1004,21 +1010,30 @@ buf_LRU_free_from_common_LRU_list( ut_ad(buf_pool_mutex_own(buf_pool)); - for (bpage = UT_LIST_GET_LAST(buf_pool->LRU), - scanned = 1, freed = FALSE; + for (bpage = buf_pool->lru_scan_itr.start(), + scanned = 0, freed = false; bpage != NULL && !freed - && (scan_all || scanned < srv_LRU_scan_depth); - ++scanned) { + && (scan_all || scanned < BUF_LRU_SEARCH_SCAN_THRESHOLD); + ++scanned, bpage = buf_pool->lru_scan_itr.get()) { - unsigned accessed; - buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, - bpage); + buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); + buf_pool->lru_scan_itr.set(prev); + + ib_mutex_t* mutex = buf_page_get_mutex(bpage); + mutex_enter(mutex); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); - accessed = buf_page_is_accessed(bpage); - freed = buf_LRU_free_page(bpage, true); + unsigned accessed = buf_page_is_accessed(bpage); + + if (buf_flush_ready_for_replace(bpage)) { + mutex_exit(mutex); + freed = buf_LRU_free_page(bpage, true); + } else { + mutex_exit(mutex); + } + if (freed && !accessed) { /* Keep track of pages that are evicted without ever being accessed. This gives us a measure of @@ -1026,14 +1041,17 @@ buf_LRU_free_from_common_LRU_list( ++buf_pool->stat.n_ra_pages_evicted; } - bpage = prev_bpage; + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(!mutex_own(mutex)); } - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_LRU_SEARCH_SCANNED, - MONITOR_LRU_SEARCH_SCANNED_NUM_CALL, - MONITOR_LRU_SEARCH_SCANNED_PER_CALL, - scanned); + if (scanned) { + MONITOR_INC_VALUE_CUMULATIVE( + MONITOR_LRU_SEARCH_SCANNED, + MONITOR_LRU_SEARCH_SCANNED_NUM_CALL, + MONITOR_LRU_SEARCH_SCANNED_PER_CALL, + scanned); + } return(freed); } @@ -1217,8 +1235,6 @@ the free list. Even when we flush a page or find a page in LRU scan we put it to free list to be used. * iteration 0: * get a block from free list, success:done - * if there is an LRU flush batch in progress: - * wait for batch to end: retry free list * if buf_pool->try_LRU_scan is set * scan LRU up to srv_LRU_scan_depth to find a clean block * the above will put the block on free list @@ -1231,7 +1247,7 @@ we put it to free list to be used. * scan whole LRU list * scan LRU list even if buf_pool->try_LRU_scan is not set * iteration > 1: - * same as iteration 1 but sleep 100ms + * same as iteration 1 but sleep 10ms @return the free control block, in state BUF_BLOCK_READY_FOR_USE */ UNIV_INTERN buf_block_t* @@ -1269,20 +1285,6 @@ loop: return(block); } - if (buf_pool->init_flush[BUF_FLUSH_LRU] - && srv_use_doublewrite_buf - && buf_dblwr != NULL) { - - /* If there is an LRU flush happening in the background - then we wait for it to end instead of trying a single - page flush. If, however, we are not using doublewrite - buffer then it is better to do our own single page - flush instead of waiting for LRU flush to end. */ - buf_pool_mutex_exit(buf_pool); - buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU); - goto loop; - } - freed = FALSE; if (buf_pool->try_LRU_scan || n_iterations > 0) { /* If no block was in the free list, search from the @@ -1299,6 +1301,10 @@ loop: TRUE again when we flush a batch from this buffer pool. */ buf_pool->try_LRU_scan = FALSE; + + /* Also tell the page_cleaner thread that + there is work for it to do. */ + os_event_set(buf_flush_event); } } @@ -1347,12 +1353,10 @@ loop: /* If we have scanned the whole LRU and still are unable to find a free block then we should sleep here to let the - page_cleaner do an LRU batch for us. - TODO: It'd be better if we can signal the page_cleaner. Perhaps - we should use timed wait for page_cleaner. */ - if (n_iterations > 1) { + page_cleaner do an LRU batch for us. */ - os_thread_sleep(100000); + if (n_iterations > 1) { + os_thread_sleep(10000); } /* No free block was found: try to flush the LRU list. @@ -1503,6 +1507,20 @@ buf_unzip_LRU_remove_block_if_needed( } /******************************************************************//** +Adjust LRU hazard pointers if needed. */ + +void +buf_LRU_adjust_hp( +/*==============*/ + buf_pool_t* buf_pool,/*!< in: buffer pool instance */ + const buf_page_t* bpage) /*!< in: control block */ +{ + buf_pool->lru_hp.adjust(bpage); + buf_pool->lru_scan_itr.adjust(bpage); + buf_pool->single_scan_itr.adjust(bpage); +} + +/******************************************************************//** Removes a block from the LRU list. */ UNIV_INLINE void @@ -1521,6 +1539,10 @@ buf_LRU_remove_block( ut_ad(bpage->in_LRU_list); + /* Important that we adjust the hazard pointers before removing + bpage from the LRU list. */ + buf_LRU_adjust_hp(buf_pool, bpage); + /* If the LRU_old pointer is defined and points to just this block, move it backward one step */ |