Skip to content

Commit bee4b04

Browse files
committed
MDEV-21751 innodb_fast_shutdown=0 can be unnecessarily slow
max out parallel purge worker tasks, on slow shutdown, to speedup
1 parent 839ad5e commit bee4b04

File tree

5 files changed

+47
-20
lines changed

5 files changed

+47
-20
lines changed

storage/innobase/include/srv0srv.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,16 @@ srv_que_task_enqueue_low(
757757
/*=====================*/
758758
que_thr_t* thr); /*!< in: query thread */
759759

760+
/**
761+
Flag which is set, whenever innodb_purge_threads changes.
762+
It is read and reset in srv_do_purge().
763+
764+
Thus it is Atomic_counter<int>, not bool, since unprotected
765+
reads are used. We just need an atomic with relaxed memory
766+
order, to please Thread Sanitizer.
767+
*/
768+
extern Atomic_counter<int> srv_purge_thread_count_changed;
769+
760770
#ifdef UNIV_DEBUG
761771
/** @return whether purge or master task is active */
762772
bool srv_any_background_activity();
@@ -796,7 +806,7 @@ ulint srv_get_task_queue_length();
796806
void srv_purge_shutdown();
797807

798808
/** Init purge tasks*/
799-
void srv_init_purge_tasks(uint n_max);
809+
void srv_init_purge_tasks();
800810

801811
#ifdef UNIV_DEBUG
802812
/** Disables master thread. It's used by:

storage/innobase/include/trx0types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ static const ulint TRX_SYS_SPACE = 0;
4848
/** Random value to check for corruption of trx_t */
4949
static const ulint TRX_MAGIC_N = 91118598;
5050

51+
constexpr uint innodb_purge_threads_MAX= 32;
52+
5153
/** Transaction execution states when trx->state == TRX_STATE_ACTIVE */
5254
enum trx_que_t {
5355
TRX_QUE_RUNNING, /*!< transaction is running */

storage/innobase/srv/srv0srv.cc

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Created 10/8/1995 Heikki Tuuri
7272
#include "fil0fil.h"
7373
#include "fil0crypt.h"
7474
#include "fil0pagecompress.h"
75+
#include "trx0types.h"
7576

7677

7778
#include <my_service_manager.h>
@@ -2060,6 +2061,15 @@ static bool srv_task_execute()
20602061
return false;
20612062
}
20622063

2064+
std::mutex purge_thread_count_mtx;
2065+
void srv_update_purge_thread_count(uint n)
2066+
{
2067+
std::lock_guard<std::mutex> lk(purge_thread_count_mtx);
2068+
srv_n_purge_threads = n;
2069+
srv_purge_thread_count_changed = 1;
2070+
}
2071+
2072+
Atomic_counter<int> srv_purge_thread_count_changed;
20632073

20642074
/** Do the actual purge operation.
20652075
@param[in,out] n_total_purged total number of purged pages
@@ -2072,7 +2082,7 @@ static uint32_t srv_do_purge(ulint* n_total_purged)
20722082
static ulint n_use_threads = 0;
20732083
static uint32_t rseg_history_len = 0;
20742084
ulint old_activity_count = srv_get_activity_count();
2075-
const ulint n_threads = srv_n_purge_threads;
2085+
static ulint n_threads = srv_n_purge_threads;
20762086

20772087
ut_a(n_threads > 0);
20782088
ut_ad(!srv_read_only_mode);
@@ -2088,7 +2098,20 @@ static uint32_t srv_do_purge(ulint* n_total_purged)
20882098
}
20892099

20902100
do {
2091-
if (trx_sys.rseg_history_len > rseg_history_len
2101+
if (UNIV_UNLIKELY(srv_purge_thread_count_changed)) {
2102+
/* Read the fresh value of srv_n_purge_threads, reset
2103+
the changed flag. Both variables are protected by
2104+
purge_thread_count_mtx.
2105+
2106+
This code does not run concurrently, it is executed
2107+
by a single purge_coordinator thread, and no races
2108+
involving srv_purge_thread_count_changed are possible.
2109+
*/
2110+
2111+
std::lock_guard<std::mutex> lk(purge_thread_count_mtx);
2112+
n_threads = n_use_threads = srv_n_purge_threads;
2113+
srv_purge_thread_count_changed = 0;
2114+
} else if (trx_sys.rseg_history_len > rseg_history_len
20922115
|| (srv_max_purge_lag > 0
20932116
&& rseg_history_len > srv_max_purge_lag)) {
20942117

@@ -2136,23 +2159,17 @@ static uint32_t srv_do_purge(ulint* n_total_purged)
21362159

21372160
static std::queue<THD*> purge_thds;
21382161
static std::mutex purge_thd_mutex;
2139-
2140-
static void purge_create_background_thds(int n)
2141-
{
2142-
THD *thd= current_thd;
2143-
std::unique_lock<std::mutex> lk(purge_thd_mutex);
2144-
while (n--)
2145-
purge_thds.push(innobase_create_background_thd("InnoDB purge worker"));
2146-
set_current_thd(thd);
2147-
}
2148-
21492162
extern void* thd_attach_thd(THD*);
21502163
extern void thd_detach_thd(void *);
21512164

21522165
THD* acquire_thd(void **ctx)
21532166
{
21542167
std::unique_lock<std::mutex> lk(purge_thd_mutex);
2155-
ut_a(!purge_thds.empty());
2168+
if (purge_thds.empty()) {
2169+
THD* thd = current_thd;
2170+
purge_thds.push(innobase_create_background_thd("InnoDB purge worker"));
2171+
set_current_thd(thd);
2172+
}
21562173
THD* thd = purge_thds.front();
21572174
purge_thds.pop();
21582175
lk.unlock();
@@ -2251,10 +2268,8 @@ static void purge_coordinator_callback(void*)
22512268
purge_state.m_running= 0;
22522269
}
22532270

2254-
void srv_init_purge_tasks(uint n_tasks)
2271+
void srv_init_purge_tasks()
22552272
{
2256-
purge_task_group.set_max_tasks(n_tasks - 1);
2257-
purge_create_background_thds(n_tasks);
22582273
purge_coordinator_timer= srv_thread_pool->create_timer
22592274
(purge_coordinator_timer_callback, nullptr);
22602275
}
@@ -2310,6 +2325,7 @@ ulint srv_get_task_queue_length()
23102325
void srv_purge_shutdown()
23112326
{
23122327
if (purge_sys.enabled()) {
2328+
srv_update_purge_thread_count(innodb_purge_threads_MAX);
23132329
while(!srv_purge_should_exit()) {
23142330
ut_a(!purge_sys.paused());
23152331
srv_wake_purge_thread_if_not_active();

storage/innobase/srv/srv0start.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,8 +1962,7 @@ dberr_t srv_start(bool create_new_db)
19621962

19631963
if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL
19641964
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
1965-
1966-
srv_init_purge_tasks(srv_n_purge_threads);
1965+
srv_init_purge_tasks();
19671966
purge_sys.coordinator_startup();
19681967
srv_wake_purge_thread_if_not_active();
19691968
srv_start_state_set(SRV_START_STATE_PURGE);

storage/innobase/trx/trx0purge.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ purge_graph_build()
149149
NULL, NULL, QUE_FORK_PURGE, heap);
150150
fork->trx = trx;
151151

152-
for (ulint i = 0; i < srv_n_purge_threads; ++i) {
152+
for (auto i = innodb_purge_threads_MAX; i; i--) {
153153
que_thr_t* thr = que_thr_create(fork, heap, NULL);
154154
thr->child = new(mem_heap_alloc(heap, sizeof(purge_node_t)))
155155
purge_node_t(thr);

0 commit comments

Comments
 (0)