commit 6532572a783ea5a025561eda9b1a9350c73405a6 Author: Nickolay Ihalainen Date: Wed Nov 25 10:17:30 2015 +0300 Partial fix for lp:1433432, avoid redundant CPU spinning in the LRU manager thread when previous iteration isn't able to flush. Deadlock with innodb_empty_free_list_algorithm=backoff is not resolved. diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index d9893fc..97c86ee 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2209,9 +2209,10 @@ Clears up tail of the LRU lists: * Put replaceable pages at the tail of LRU to the free list * Flush dirty pages at the tail of LRU to the disk The depth to which we scan each buffer pool is controlled by dynamic -config parameter innodb_LRU_scan_depth. */ +config parameter innodb_LRU_scan_depth. +@return number of pages flushed */ UNIV_INTERN -void +ulint buf_flush_LRU_tail(void) /*====================*/ { @@ -2313,6 +2314,7 @@ buf_flush_LRU_tail(void) MONITOR_LRU_BATCH_PAGES, total_flushed); } + return(total_flushed); } /*********************************************************************//** @@ -2608,19 +2610,24 @@ static void page_cleaner_adapt_lru_sleep_time( /*==============================*/ - ulint* lru_sleep_time) /*!< in/out: desired page cleaner thread sleep + ulint* lru_sleep_time, /*!< in/out: desired page cleaner thread sleep time for LRU flushes */ + ulint lru_n_flushed) /*!< in: number of flushed in previous batch */ + { ulint free_len = buf_get_total_free_list_length(); ulint max_free_len = srv_LRU_scan_depth * srv_buf_pool_instances; - if (free_len < max_free_len / 100) { + if (free_len < max_free_len / 100 && lru_n_flushed) { - /* Free lists filled less than 1%, no sleep */ + /* Free lists filled less than 1% + and iteration was able to flush, no sleep */ *lru_sleep_time = 0; - } else if (free_len > max_free_len / 5) { + } else if (free_len > max_free_len / 5 + || (free_len < max_free_len / 100 && lru_n_flushed == 0)) { - /* Free lists filled more than 20%, sleep a bit more */ + /* Free lists filled more than 20% + or no pages flushed in previous batch, sleep a bit more */ *lru_sleep_time += 50; if (*lru_sleep_time > srv_cleaner_max_lru_time) *lru_sleep_time = srv_cleaner_max_lru_time; @@ -2826,6 +2833,7 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( { ulint next_loop_time = ut_time_ms() + 1000; ulint lru_sleep_time = srv_cleaner_max_lru_time; + ulint lru_n_flushed = 1; #ifdef UNIV_PFS_THREAD pfs_register_thread(buf_lru_manager_thread_key); @@ -2852,11 +2860,11 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( page_cleaner_sleep_if_needed(next_loop_time); - page_cleaner_adapt_lru_sleep_time(&lru_sleep_time); + page_cleaner_adapt_lru_sleep_time(&lru_sleep_time, lru_n_flushed); next_loop_time = ut_time_ms() + lru_sleep_time; - buf_flush_LRU_tail(); + lru_n_flushed = buf_flush_LRU_tail(); } buf_lru_manager_is_active = false; diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index b73037d..2cd8eef 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -202,9 +202,10 @@ Clears up tail of the LRU lists: * Put replaceable pages at the tail of LRU to the free list * Flush dirty pages at the tail of LRU to the disk The depth to which we scan each buffer pool is controlled by dynamic -config parameter innodb_LRU_scan_depth. */ +config parameter innodb_LRU_scan_depth. +@return number of pages flushed */ UNIV_INTERN -void +ulint buf_flush_LRU_tail(void); /*====================*/ /*********************************************************************//**