diff options
Diffstat (limited to 'storage/innobase/dict/dict0stats_bg.cc')
-rw-r--r-- | storage/innobase/dict/dict0stats_bg.cc | 184 |
1 files changed, 65 insertions, 119 deletions
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 2d358f2c9e3..0b2e28b6476 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -43,24 +43,11 @@ Created Apr 25, 2012 Vasil Dimov /** Minimum time interval between stats recalc for a given table */ #define MIN_RECALC_INTERVAL 10 /* seconds */ - -/** Event to wake up dict_stats_thread on dict_stats_recalc_pool_add() -or shutdown. Not protected by any mutex. */ -os_event_t dict_stats_event; - -/** Variable to initiate shutdown the dict stats thread. Note we don't -use 'srv_shutdown_state' because we want to shutdown dict stats thread -before purge thread. */ -bool dict_stats_start_shutdown; - -/** Event to wait for shutdown of the dict stats thread */ -os_event_t dict_stats_shutdown_event; +static void dict_stats_schedule(int ms); #ifdef UNIV_DEBUG /** Used by SET GLOBAL innodb_dict_stats_disabled_debug = 1; */ my_bool innodb_dict_stats_disabled_debug; - -static os_event_t dict_stats_disabled_event; #endif /* UNIV_DEBUG */ /** This mutex protects the "recalc_pool" variable. */ @@ -119,7 +106,9 @@ static void dict_stats_recalc_pool_add( /*=======================*/ - const dict_table_t* table) /*!< in: table to add */ + const dict_table_t* table, /*!< in: table to add */ + bool schedule_dict_stats_task = true /*!< in: schedule dict stats task */ +) { ut_ad(!srv_read_only_mode); @@ -137,10 +126,11 @@ dict_stats_recalc_pool_add( } recalc_pool.push_back(table->id); - + if (recalc_pool.size() == 1 && schedule_dict_stats_task) { + dict_stats_schedule_now(); + } mutex_exit(&recalc_pool_mutex); - os_event_set(dict_stats_event); } #ifdef WITH_WSREP @@ -294,14 +284,9 @@ dict_stats_wait_bg_to_stop_using_table( /*****************************************************************//** Initialize global variables needed for the operation of dict_stats_thread() Must be called before dict_stats_thread() is started. */ -void -dict_stats_thread_init() +void dict_stats_init() { - ut_a(!srv_read_only_mode); - - dict_stats_event = os_event_create(0); - dict_stats_shutdown_event = os_event_create(0); - ut_d(dict_stats_disabled_event = os_event_create(0)); + ut_ad(!srv_read_only_mode); /* The recalc_pool_mutex is acquired from: 1) the background stats gathering thread before any other latch @@ -324,48 +309,38 @@ dict_stats_thread_init() } /*****************************************************************//** -Free resources allocated by dict_stats_thread_init(), must be called -after dict_stats_thread() has exited. */ -void -dict_stats_thread_deinit() -/*======================*/ +Free resources allocated by dict_stats_init(), must be called +after dict_stats task has exited. */ +void dict_stats_deinit() { - ut_a(!srv_read_only_mode); - ut_ad(!srv_dict_stats_thread_active); - if (!stats_initialised) { return; } + ut_ad(!srv_read_only_mode); stats_initialised = false; dict_stats_recalc_pool_deinit(); dict_defrag_pool_deinit(); mutex_free(&recalc_pool_mutex); - - ut_d(os_event_destroy(dict_stats_disabled_event)); - os_event_destroy(dict_stats_event); - os_event_destroy(dict_stats_shutdown_event); - dict_stats_start_shutdown = false; } -/*****************************************************************//** +/** Get the first table that has been added for auto recalc and eventually -update its stats. */ -static -void -dict_stats_process_entry_from_recalc_pool() -/*=======================================*/ +update its stats. +@return whether the first entry can be processed immediately */ +static bool dict_stats_process_entry_from_recalc_pool() { table_id_t table_id; ut_ad(!srv_read_only_mode); +next_table_id: /* pop the first table from the auto recalc pool */ if (!dict_stats_recalc_pool_get(&table_id)) { /* no tables for auto recalc */ - return; + return false; } dict_table_t* table; @@ -378,7 +353,7 @@ dict_stats_process_entry_from_recalc_pool() /* table does not exist, must have been DROPped after its id was enqueued */ mutex_exit(&dict_sys.mutex); - return; + goto next_table_id; } ut_ad(!table->is_temporary()); @@ -386,7 +361,7 @@ dict_stats_process_entry_from_recalc_pool() if (!fil_table_accessible(table)) { dict_table_close(table, TRUE, FALSE); mutex_exit(&dict_sys.mutex); - return; + goto next_table_id; } table->stats_bg_flag |= BG_STAT_IN_PROGRESS; @@ -399,7 +374,7 @@ dict_stats_process_entry_from_recalc_pool() find out that this is a problem, then the check below could eventually be replaced with something else, though a time interval is the natural approach. */ - + int ret; if (difftime(time(NULL), table->stats_last_recalc) < MIN_RECALC_INTERVAL) { @@ -407,11 +382,13 @@ dict_stats_process_entry_from_recalc_pool() too frequent stats updates we put back the table on the auto recalc list and do nothing. */ - dict_stats_recalc_pool_add(table); - + dict_stats_recalc_pool_add(table, false); + dict_stats_schedule(MIN_RECALC_INTERVAL*1000); + ret = false; } else { dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT); + ret = true; } mutex_enter(&dict_sys.mutex); @@ -421,6 +398,7 @@ dict_stats_process_entry_from_recalc_pool() dict_table_close(table, TRUE, FALSE); mutex_exit(&dict_sys.mutex); + return ret; } #ifdef UNIV_DEBUG @@ -430,89 +408,57 @@ dict_stats_process_entry_from_recalc_pool() void dict_stats_disabled_debug_update(THD*, st_mysql_sys_var*, void*, const void* save) { - /* This method is protected by mutex, as every SET GLOBAL .. */ - ut_ad(dict_stats_disabled_event != NULL); - const bool disable = *static_cast<const my_bool*>(save); - - const int64_t sig_count = os_event_reset(dict_stats_disabled_event); - - innodb_dict_stats_disabled_debug = disable; - - if (disable) { - os_event_set(dict_stats_event); - os_event_wait_low(dict_stats_disabled_event, sig_count); - } + if (disable) + dict_stats_shutdown(); + else + dict_stats_start(); } #endif /* UNIV_DEBUG */ +static tpool::timer* dict_stats_timer; +static std::mutex dict_stats_mutex; -/*****************************************************************//** -This is the thread for background stats gathering. It pops tables, from -the auto recalc list and proceeds them, eventually recalculating their -statistics. -@return this function does not return, it calls os_thread_exit() */ -extern "C" -os_thread_ret_t -DECLARE_THREAD(dict_stats_thread)(void*) +static void dict_stats_func(void*) { - my_thread_init(); - ut_a(!srv_read_only_mode); - -#ifdef UNIV_PFS_THREAD - /* JAN: TODO: MySQL 5.7 PSI - pfs_register_thread(dict_stats_thread_key); - */ -#endif /* UNIV_PFS_THREAD */ - - while (!dict_stats_start_shutdown) { - - /* Wake up periodically even if not signaled. This is - because we may lose an event - if the below call to - dict_stats_process_entry_from_recalc_pool() puts the entry back - in the list, the os_event_set() will be lost by the subsequent - os_event_reset(). */ - os_event_wait_time( - dict_stats_event, MIN_RECALC_INTERVAL * 1000000); - -#ifdef UNIV_DEBUG - while (innodb_dict_stats_disabled_debug) { - os_event_set(dict_stats_disabled_event); - if (dict_stats_start_shutdown) { - break; - } - os_event_wait_time( - dict_stats_event, 100000); - } -#endif /* UNIV_DEBUG */ - - if (dict_stats_start_shutdown) { - break; - } - - dict_stats_process_entry_from_recalc_pool(); - dict_defrag_process_entries_from_defrag_pool(); + while (dict_stats_process_entry_from_recalc_pool()) {} + dict_defrag_process_entries_from_defrag_pool(); +} - os_event_reset(dict_stats_event); - } - srv_dict_stats_thread_active = false; +void dict_stats_start() +{ + std::lock_guard<std::mutex> lk(dict_stats_mutex); + if (!dict_stats_timer) + dict_stats_timer= srv_thread_pool->create_timer(dict_stats_func); +} - os_event_set(dict_stats_shutdown_event); - my_thread_end(); - /* We count the number of threads in os_thread_exit(). A created - thread should always use that to exit instead of return(). */ - os_thread_exit(); +static void dict_stats_schedule(int ms) +{ + std::unique_lock<std::mutex> lk(dict_stats_mutex, std::defer_lock); + /* + Use try_lock() to avoid deadlock in dict_stats_shutdown(), which + uses dict_stats_mutex too. If there is simultaneous timer reschedule, + the first one will win, which is fine. + */ + if (!lk.try_lock()) + { + return; + } + if (dict_stats_timer) + dict_stats_timer->set_time(ms,0); +} - OS_THREAD_DUMMY_RETURN; +void dict_stats_schedule_now() +{ + dict_stats_schedule(0); } /** Shut down the dict_stats_thread. */ -void -dict_stats_shutdown() +void dict_stats_shutdown() { - dict_stats_start_shutdown = true; - os_event_set(dict_stats_event); - os_event_wait(dict_stats_shutdown_event); + std::lock_guard<std::mutex> lk(dict_stats_mutex); + delete dict_stats_timer; + dict_stats_timer= 0; } |