summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-07-21 15:44:32 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-07-22 10:11:35 +0300
commita4dc9265792919eb1ad156780e1a93dc4c7c6ce8 (patch)
tree2bab3b20b4d733e9518777e94098a0cb4bec7790
parent641f09398fdc37c6f3b0ec6731d5f246ecf24866 (diff)
downloadmariadb-git-a4dc9265792919eb1ad156780e1a93dc4c7c6ce8.tar.gz
MDEV-26193: Wake up purge less often
Starting with commit 6e12ebd4a748eba738e08ad1d7f5dec782ff63ee (MDEV-25062), srv_wake_purge_thread_if_not_active() became more expensive operation, especially on NUMA systems, because instead of reading an atomic global variable trx_sys.rseg_history_len we are traversing up to 128 cache lines in trx_sys.history_exists(). trx_t::commit_cleanup(): Do not wake up purge at all. We will wake up purge about once per second in srv_master_callback(). srv_master_do_active_tasks(), srv_master_do_idle_tasks(): Move some duplicated code to srv_master_callback(). srv_master_callback(): Invoke purge_coordinator_timer_callback() to ensure that purge will be periodically woken up, even if the latest execution of trx_t::commit_cleanup() allowed the purge view to advance but did not wake up purge. Do not call log_free_check(), because every thread that is going to generate redo log is supposed to call that function anyway, before acquiring any page latches. Additional calls to the function every few seconds should not make any difference. srv_shutdown_threads(): Ensure that srv_shutdown_state can be at most SRV_SHUTDOWN_INITIATED in srv_master_callback(), by first invoking srv_master_timer.reset() before changing srv_shutdown_state. (Note: We first terminate the srv_master_callback and only then terminate the purge tasks. Thus, the purge subsystem should exist when srv_master_callback() invokes purge_coordinator_timer_callback() if it was initiated in the first place.
-rw-r--r--storage/innobase/srv/srv0srv.cc100
-rw-r--r--storage/innobase/srv/srv0start.cc2
-rw-r--r--storage/innobase/trx/trx0trx.cc2
3 files changed, 20 insertions, 84 deletions
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 8692eaa0e89..81e0a3d2b79 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1552,97 +1552,34 @@ void srv_master_thread_enable()
}
#endif /* UNIV_DEBUG */
-/*********************************************************************//**
-Perform the tasks that the master thread is supposed to do when the
-server is active. There are two types of tasks. The first category is
-of such tasks which are performed at each inovcation of this function.
-We assume that this function is called roughly every second when the
-server is active. The second category is of such tasks which are
-performed at some interval e.g.: purge, dict_LRU cleanup etc. */
-static
-void
-srv_master_do_active_tasks(void)
-/*============================*/
+/** Perform periodic tasks whenever the server is active.
+@param counter_time microsecond_interval_timer() */
+static void srv_master_do_active_tasks(ulonglong counter_time)
{
- time_t cur_time = time(NULL);
- ulonglong counter_time = microsecond_interval_timer();
-
- /* First do the tasks that we are suppose to do at each
- invocation of this function. */
-
++srv_main_active_loops;
MONITOR_INC(MONITOR_MASTER_ACTIVE_LOOPS);
- ut_d(srv_master_do_disabled_loop());
-
- if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
- return;
- }
-
- /* make sure that there is enough reusable space in the redo
- log files */
- srv_main_thread_op_info = "checking free log space";
- log_free_check();
-
- /* Flush logs if needed */
- srv_main_thread_op_info = "flushing log";
- srv_sync_log_buffer_in_background();
- MONITOR_INC_TIME_IN_MICRO_SECS(
- MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);
-
- /* Now see if various tasks that are performed at defined
- intervals need to be performed. */
-
- if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
- return;
- }
-
- if (cur_time % SRV_MASTER_DICT_LRU_INTERVAL == 0) {
+ if (!(counter_time % (SRV_MASTER_DICT_LRU_INTERVAL * 1000000ULL))) {
srv_main_thread_op_info = "enforcing dict cache limit";
- ulint n_evicted = dict_sys.evict_table_LRU(true);
- if (n_evicted != 0) {
+ if (ulint n_evicted = dict_sys.evict_table_LRU(true)) {
MONITOR_INC_VALUE(
- MONITOR_SRV_DICT_LRU_EVICT_COUNT_ACTIVE, n_evicted);
+ MONITOR_SRV_DICT_LRU_EVICT_COUNT_ACTIVE,
+ n_evicted);
}
MONITOR_INC_TIME_IN_MICRO_SECS(
MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);
}
}
-/*********************************************************************//**
-Perform the tasks that the master thread is supposed to do whenever the
-server is idle. We do check for the server state during this function
-and if the server has entered the shutdown phase we may return from
-the function without completing the required tasks.
-Note that the server can move to active state when we are executing this
-function but we don't check for that as we are suppose to perform more
-or less same tasks when server is active. */
-static
-void
-srv_master_do_idle_tasks(void)
-/*==========================*/
+/** Perform periodic tasks whenever the server is idle.
+@param counter_time microsecond_interval_timer() */
+static void srv_master_do_idle_tasks(ulonglong counter_time)
{
++srv_main_idle_loops;
MONITOR_INC(MONITOR_MASTER_IDLE_LOOPS);
- ut_d(srv_master_do_disabled_loop());
-
- if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
- return;
- }
-
- /* make sure that there is enough reusable space in the redo
- log files */
- srv_main_thread_op_info = "checking free log space";
- log_free_check();
-
- if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) {
- return;
- }
-
- ulonglong counter_time = microsecond_interval_timer();
srv_main_thread_op_info = "enforcing dict cache limit";
if (ulint n_evicted = dict_sys.evict_table_LRU(false)) {
MONITOR_INC_VALUE(
@@ -1650,11 +1587,6 @@ srv_master_do_idle_tasks(void)
}
MONITOR_INC_TIME_IN_MICRO_SECS(
MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
- MONITOR_INC_TIME_IN_MICRO_SECS(
- MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);
}
/**
@@ -1695,12 +1627,18 @@ void srv_master_callback(void*)
ut_a(srv_shutdown_state <= SRV_SHUTDOWN_INITIATED);
- srv_main_thread_op_info = "";
MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);
+ ut_d(srv_master_do_disabled_loop());
+ purge_coordinator_timer_callback(nullptr);
+ ulonglong counter_time = microsecond_interval_timer();
+ srv_sync_log_buffer_in_background();
+ MONITOR_INC_TIME_IN_MICRO_SECS(
+ MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);
+
if (srv_check_activity(&old_activity_count)) {
- srv_master_do_active_tasks();
+ srv_master_do_active_tasks(counter_time);
} else {
- srv_master_do_idle_tasks();
+ srv_master_do_idle_tasks(counter_time);
}
srv_main_thread_op_info = "sleeping";
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index bac9a3b25b5..3f0ccf44b1e 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -812,9 +812,9 @@ srv_open_tmp_tablespace(bool create_new_db)
static void srv_shutdown_threads()
{
ut_ad(!srv_undo_sources);
- srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
ut_d(srv_master_thread_enable());
srv_master_timer.reset();
+ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
if (purge_sys.enabled()) {
srv_purge_shutdown();
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 66ca04bbf04..3763ed67c98 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1392,8 +1392,6 @@ void trx_t::commit_cleanup()
mutex.wr_unlock();
ut_a(error_state == DB_SUCCESS);
- if (!srv_read_only_mode)
- srv_wake_purge_thread_if_not_active();
}
/** Commit the transaction in a mini-transaction.