diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-08-19 11:18:56 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-08-19 11:18:56 +0300 |
commit | 309302a3dad5f06cb62b0846dcb8a3671d91ff29 (patch) | |
tree | 08bea0450995bb89ea713a81b0357c24fe647887 /storage/innobase/srv | |
parent | 1509363970e9cb574005e3af560299c055dda983 (diff) | |
download | mariadb-git-309302a3dad5f06cb62b0846dcb8a3671d91ff29.tar.gz |
MDEV-23475 InnoDB performance regression for write-heavy workloads
In commit fe39d02f51b96536dccca7ff89faf05e13548877 (MDEV-20638)
we removed some wake-up signaling of the master thread that should
have been there, to ensure a steady log checkpointing workload.
Common sense suggests that the commit omitted some necessary calls
to srv_inc_activity_count(). But, an attempt to add the call to
trx_flush_log_if_needed_low() as well as to reinstate the function
innobase_active_small() did not restore the performance for the
case where sync_binlog=1 is set.
Therefore, we will revert the entire commit in MariaDB Server 10.2.
In MariaDB Server 10.5, adding a srv_inc_activity_count() call to
trx_flush_log_if_needed_low() did restore the performance, so we
will not revert MDEV-20638 across all versions.
Diffstat (limited to 'storage/innobase/srv')
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 100 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 4 |
2 files changed, 79 insertions, 25 deletions
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 6bf8e3dd8f6..f1216dcd51e 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1982,6 +1982,33 @@ srv_get_active_thread_type(void) return(ret); } +/** Wake up the InnoDB master thread if it was suspended (not sleeping). */ +void +srv_active_wake_master_thread_low() +{ + ut_ad(!srv_read_only_mode); + ut_ad(!srv_sys_mutex_own()); + + srv_inc_activity_count(); + + if (my_atomic_loadlint(&srv_sys.n_threads_active[SRV_MASTER]) == 0) { + srv_slot_t* slot; + + srv_sys_mutex_enter(); + + slot = &srv_sys.sys_threads[SRV_MASTER_SLOT]; + + /* Only if the master thread has been started. */ + + if (slot->in_use) { + ut_a(srv_slot_get_type(slot) == SRV_MASTER); + os_event_set(slot->event); + } + + srv_sys_mutex_exit(); + } +} + /** Wake up the purge threads if there is work to do. */ void srv_wake_purge_thread_if_not_active() @@ -1996,6 +2023,14 @@ srv_wake_purge_thread_if_not_active() } } +/** Wake up the master thread if it is suspended or being suspended. */ +void +srv_wake_master_thread() +{ + srv_inc_activity_count(); + srv_release_threads(SRV_MASTER, 1); +} + /*******************************************************************//** Get current server activity count. We don't hold srv_sys::mutex while reading this value as it is only used in heuristics. @@ -2007,20 +2042,15 @@ srv_get_activity_count(void) return(srv_sys.activity_count); } -/** Check if there has been any activity. -@param[in,out] activity_count recent activity count to be returned -if there is a change +/*******************************************************************//** +Check if there has been any activity. @return FALSE if no change in activity counter. */ -bool srv_check_activity(ulint *activity_count) +ibool +srv_check_activity( +/*===============*/ + ulint old_activity_count) /*!< in: old activity count */ { - ulint new_activity_count= srv_sys.activity_count; - if (new_activity_count != *activity_count) - { - *activity_count= new_activity_count; - return true; - } - - return false; + return(srv_sys.activity_count != old_activity_count); } /********************************************************************//** @@ -2427,30 +2457,52 @@ DECLARE_THREAD(srv_master_thread)( slot = srv_reserve_slot(SRV_MASTER); ut_a(slot == srv_sys.sys_threads); +loop: while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { srv_master_sleep(); MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP); - if (srv_check_activity(&old_activity_count)) { + if (srv_check_activity(old_activity_count)) { + old_activity_count = srv_get_activity_count(); srv_master_do_active_tasks(); } else { srv_master_do_idle_tasks(); } } - ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS - || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP); - - if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP - && srv_fast_shutdown < 2) { - srv_shutdown(srv_fast_shutdown == 0); + switch (srv_shutdown_state) { + case SRV_SHUTDOWN_NONE: + case SRV_SHUTDOWN_INITIATED: + break; + case SRV_SHUTDOWN_FLUSH_PHASE: + case SRV_SHUTDOWN_LAST_PHASE: + ut_ad(0); + /* fall through */ + case SRV_SHUTDOWN_EXIT_THREADS: + /* srv_init_abort() must have been invoked */ + case SRV_SHUTDOWN_CLEANUP: + if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP + && srv_fast_shutdown < 2) { + srv_shutdown(srv_fast_shutdown == 0); + } + srv_suspend_thread(slot); + my_thread_end(); + os_thread_exit(); } + srv_main_thread_op_info = "suspending"; + srv_suspend_thread(slot); - my_thread_end(); - os_thread_exit(); - OS_THREAD_DUMMY_RETURN; + + /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql() + waits for database activity to die down when converting < 4.1.x + databases, and relies on this string being exactly as it is. InnoDB + manual also mentions this string in several places. */ + srv_main_thread_op_info = "waiting for server activity"; + + srv_resume_thread(slot); + goto loop; } /** Check if purge should stop. @@ -2647,13 +2699,15 @@ srv_do_purge(ulint* n_total_purged ++n_use_threads; } - } else if (srv_check_activity(&old_activity_count) + } else if (srv_check_activity(old_activity_count) && n_use_threads > 1) { /* History length same or smaller since last snapshot, use fewer threads. */ --n_use_threads; + + old_activity_count = srv_get_activity_count(); } /* Ensure that the purge threads are less than what diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a8f2b78d0a8..0d8ebbe98cd 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1238,7 +1238,7 @@ srv_shutdown_all_bg_threads() if (srv_start_state_is_set(SRV_START_STATE_MASTER)) { /* c. We wake the master thread so that it exits */ - srv_inc_activity_count(); + srv_wake_master_thread(); } if (srv_start_state_is_set(SRV_START_STATE_PURGE)) { @@ -2762,7 +2762,7 @@ srv_shutdown_bg_undo_sources() fts_optimize_shutdown(); dict_stats_shutdown(); while (row_get_background_drop_list_len_low()) { - srv_inc_activity_count(); + srv_wake_master_thread(); os_thread_yield(); } srv_undo_sources = false; |