Skip to content

Commit b393e2c

Browse files
committed
add innodb_debug_sync var to support DEBUG_SYNC from purge threads
1 parent 6d7a826 commit b393e2c

File tree

8 files changed

+174
-13
lines changed

8 files changed

+174
-13
lines changed

storage/innobase/handler/ha_innodb.cc

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19376,6 +19376,33 @@ innodb_log_checksums_update(
1937619376
thd, *static_cast<const my_bool*>(save));
1937719377
}
1937819378

19379+
#ifdef UNIV_DEBUG
19380+
static
19381+
void
19382+
innobase_debug_sync_callback(srv_slot_t *slot, const void *value)
19383+
{
19384+
const char *value_str = *static_cast<const char* const*>(value);
19385+
size_t len = strlen(value_str) + 1;
19386+
19387+
19388+
// One allocatoin for list node object and value.
19389+
void *buf = ut_malloc_nokey(sizeof(srv_slot_t::debug_sync_t) + len);
19390+
srv_slot_t::debug_sync_t *sync = new(buf) srv_slot_t::debug_sync_t();
19391+
strcpy(sync->str, value_str);
19392+
19393+
rw_lock_x_lock(&slot->debug_sync_lock);
19394+
UT_LIST_ADD_LAST(slot->debug_sync, sync);
19395+
rw_lock_x_unlock(&slot->debug_sync_lock);
19396+
}
19397+
static
19398+
void
19399+
innobase_debug_sync_set(THD *thd, st_mysql_sys_var*, void *, const void *value)
19400+
{
19401+
srv_for_each_thread(SRV_WORKER, innobase_debug_sync_callback, value);
19402+
srv_for_each_thread(SRV_PURGE, innobase_debug_sync_callback, value);
19403+
}
19404+
#endif
19405+
1937919406
static SHOW_VAR innodb_status_variables_export[]= {
1938019407
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
1938119408
{NullS, NullS, SHOW_LONG}
@@ -19881,7 +19908,8 @@ static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
1988119908
NULL, NULL,
1988219909
4, /* Default setting */
1988319910
1, /* Minimum value */
19884-
32, 0); /* Maximum value */
19911+
srv_max_purge_threads,/* Maximum value */
19912+
0);
1988519913

1988619914
static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size,
1988719915
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
@@ -20982,6 +21010,16 @@ static MYSQL_SYSVAR_BOOL(debug_force_scrubbing,
2098221010
0,
2098321011
"Perform extra scrubbing to increase test exposure",
2098421012
NULL, NULL, FALSE);
21013+
21014+
char *innobase_debug_sync;
21015+
static MYSQL_SYSVAR_STR(debug_sync, innobase_debug_sync,
21016+
PLUGIN_VAR_NOCMDARG,
21017+
"debug_sync for innodb purge threads. "
21018+
"Use it t oset up sync points for all purge threads "
21019+
"at once. The commands will be applied sequentially at "
21020+
"the beginning of purging the next node ",
21021+
NULL,
21022+
innobase_debug_sync_set, NULL);
2098521023
#endif /* UNIV_DEBUG */
2098621024

2098721025
static MYSQL_SYSVAR_BOOL(instrument_semaphores, innodb_instrument_semaphores,
@@ -21204,6 +21242,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
2120421242
MYSQL_SYSVAR(background_scrub_data_check_interval),
2120521243
#ifdef UNIV_DEBUG
2120621244
MYSQL_SYSVAR(debug_force_scrubbing),
21245+
MYSQL_SYSVAR(debug_sync),
2120721246
#endif
2120821247
MYSQL_SYSVAR(instrument_semaphores),
2120921248
MYSQL_SYSVAR(buf_dump_status_frequency),

storage/innobase/include/que0que.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ struct que_thr_t{
385385
related delete/updates */
386386
row_prebuilt_t*prebuilt;/*!< prebuilt structure processed by
387387
the query thread */
388+
389+
ut_d(srv_slot_t *thread_slot;)/*!< a slot from srv_sys.sys_threads
390+
* if any */
388391
};
389392

390393
#define QUE_THR_MAGIC_N8476583

storage/innobase/include/srv0srv.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,8 @@ extern ulong srv_fatal_semaphore_wait_threshold;
615615
/** Buffer pool dump status frequence in percentages */
616616
extern ulong srv_buf_dump_status_frequency;
617617

618+
constexpr uint srv_max_purge_threads = 32;
619+
618620
# ifdef UNIV_PFS_THREAD
619621
/* Keys to register InnoDB threads with performance schema */
620622
extern mysql_pfs_key_tbuf_dump_thread_key;
@@ -1128,8 +1130,26 @@ struct srv_slot_t{
11281130
to do */
11291131
que_thr_t* thr;/*!< suspended query thread
11301132
(only used for user threads) */
1133+
#ifdef UNIV_DEBUG
1134+
struct debug_sync_t {
1135+
UT_LIST_NODE_T(debug_sync_t)
1136+
debug_sync_list;
1137+
char str[0];
1138+
};
1139+
UT_LIST_BASE_NODE_T(debug_sync_t)
1140+
debug_sync;
1141+
rw_lock_t debug_sync_lock;
1142+
#endif
11311143
};
11321144

1145+
#ifdef UNIV_DEBUG
1146+
typedef void srv_slot_callback_t(srv_slot_t*, const void*);
1147+
1148+
void srv_for_each_thread(srv_thread_type type,
1149+
srv_slot_callback_t callback,
1150+
const void *arg);
1151+
#endif
1152+
11331153
#ifdef WITH_WSREP
11341154
UNIV_INTERN
11351155
void

storage/innobase/include/trx0purge.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,12 @@ trx_purge(
6767
submit to task queue. */
6868
ulint limit,/*!< in: the maximum number of
6969
records to purge in one batch */
70-
booltruncate);/*!< in: truncate history if true */
70+
booltruncate/*!< in: truncate history if true */
71+
#ifdef UNIV_DEBUG
72+
, srv_slot_t *slot/*!< in/out: purge coordinator
73+
thread slot */
74+
#endif
75+
);
7176
/*******************************************************************//**
7277
Stop purge and wait for it to stop, move to PURGE_STATE_STOP. */
7378
void

storage/innobase/que/que0que.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,9 @@ que_run_threads_low(
10821082
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
10831083
ut_ad(!trx_mutex_own(thr_get_trx(thr)));
10841084

1085+
/* slot can be received from purge thread for debug_sync setup */
1086+
ut_d(srv_slot_t *slot = thr->thread_slot);
1087+
10851088
/* cumul_resource counts how much resources the OS thread (NOT the
10861089
query thread) has spent in this function */
10871090

storage/innobase/row/row0purge.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Created 3/14/1997 Heikki Tuuri
4646
#include "handler.h"
4747
#include "ha_innodb.h"
4848
#include "fil0fil.h"
49+
#include "debug_sync.h"
4950

5051
/*************************************************************************
5152
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -1209,6 +1210,25 @@ row_purge_step(
12091210

12101211
node->start();
12111212

1213+
#ifdef UNIV_DEBUG
1214+
srv_slot_t *slot = thr->thread_slot;
1215+
ut_ad(slot);
1216+
1217+
rw_lock_x_lock(&slot->debug_sync_lock);
1218+
while (UT_LIST_GET_LEN(slot->debug_sync)) {
1219+
srv_slot_t::debug_sync_t *sync =
1220+
UT_LIST_GET_FIRST(slot->debug_sync);
1221+
bool result = debug_sync_set_action(current_thd,
1222+
sync->str,
1223+
strlen(sync->str));
1224+
ut_a(!result);
1225+
1226+
UT_LIST_REMOVE(slot->debug_sync, sync);
1227+
ut_free(sync);
1228+
}
1229+
rw_lock_x_unlock(&slot->debug_sync_lock);
1230+
#endif
1231+
12121232
if (!(node->undo_recs == NULL || ib_vector_is_empty(node->undo_recs))) {
12131233
trx_purge_rec_t*purge_rec;
12141234

storage/innobase/srv/srv0srv.cc

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,8 @@ struct srv_sys_t{
619619
ulint n_sys_threads;/*!< size of the sys_threads
620620
array */
621621

622-
srv_slot_tsys_threads[32 + 1];/*!< server thread table;
622+
srv_slot_t
623+
sys_threads[srv_max_purge_threads + 1];/*!< server thread table;
623624
os_event_set() and
624625
os_event_reset() on
625626
sys_threads[]->event are
@@ -661,11 +662,15 @@ and/or load it during startup. */
661662
charsrv_buffer_pool_dump_at_shutdown = TRUE;
662663
charsrv_buffer_pool_load_at_startup = TRUE;
663664

665+
/** Slot index in the srv_sys.sys_threads array for the master thread. */
666+
constexpr ulint SRV_MASTER_SLOT = 0;
667+
664668
/** Slot index in the srv_sys.sys_threads array for the purge thread. */
665-
static const ulint SRV_PURGE_SLOT = 1;
669+
constexpr ulint SRV_PURGE_SLOT = 1;
666670

667-
/** Slot index in the srv_sys.sys_threads array for the master thread. */
668-
static const ulint SRV_MASTER_SLOT = 0;
671+
/** Slot index in the srv_sys.sys_threads array from which purge workers start.
672+
*/
673+
constexpr ulint SRV_WORKER_SLOTS_START = 2;
669674

670675
#ifdef HAVE_PSI_STAGE_INTERFACE
671676
/** Performance schema stage event for monitoring ALTER TABLE progress
@@ -813,7 +818,7 @@ srv_reserve_slot(
813818

814819
case SRV_WORKER:
815820
/* Find an empty slot, skip the master and purge slots. */
816-
for (slot = &srv_sys.sys_threads[2];
821+
for (slot = &srv_sys.sys_threads[SRV_WORKER_SLOTS_START];
817822
slot->in_use;
818823
++slot) {
819824

@@ -2530,10 +2535,11 @@ srv_purge_should_exit(ulint n_purged)
25302535

25312536
/*********************************************************************//**
25322537
Fetch and execute a task from the work queue.
2538+
@param [in,out] slot purge worker thread slot
25332539
@return true if a task was executed */
25342540
static
25352541
bool
2536-
srv_task_execute(void)
2542+
srv_task_execute(ut_d(srv_slot_t *slot))
25372543
/*==================*/
25382544
{
25392545
que_thr_t* thr = NULL;
@@ -2555,6 +2561,7 @@ srv_task_execute(void)
25552561
mutex_exit(&srv_sys.tasks_mutex);
25562562

25572563
if (thr != NULL) {
2564+
ut_d(thr->thread_slot = slot);
25582565

25592566
que_run_threads(thr);
25602567

@@ -2591,6 +2598,13 @@ DECLARE_THREAD(srv_worker_thread)(
25912598

25922599
slot = srv_reserve_slot(SRV_WORKER);
25932600

2601+
#ifdef UNIV_DEBUG
2602+
UT_LIST_INIT(slot->debug_sync,
2603+
&srv_slot_t::debug_sync_t::debug_sync_list);
2604+
rw_lock_create(PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock,
2605+
SYNC_NO_ORDER_CHECK);
2606+
#endif
2607+
25942608
ut_a(srv_n_purge_threads > 1);
25952609
ut_a(ulong(my_atomic_loadlint(&srv_sys.n_threads_active[SRV_WORKER]))
25962610
< srv_n_purge_threads);
@@ -2603,7 +2617,7 @@ DECLARE_THREAD(srv_worker_thread)(
26032617
srv_suspend_thread(slot);
26042618
srv_resume_thread(slot);
26052619

2606-
if (srv_task_execute()) {
2620+
if (srv_task_execute(ut_d(slot))) {
26072621

26082622
/* If there are tasks in the queue, wakeup
26092623
the purge coordinator thread. */
@@ -2640,10 +2654,15 @@ DECLARE_THREAD(srv_worker_thread)(
26402654

26412655
/** Do the actual purge operation.
26422656
@param[in,out] n_total_purged total number of purged pages
2657+
@param[in,out] slot purge coordinator thread slot
26432658
@return length of history list before the last purge batch. */
26442659
static
26452660
ulint
2646-
srv_do_purge(ulint* n_total_purged)
2661+
srv_do_purge(ulint* n_total_purged
2662+
#ifdef UNIV_DEBUG
2663+
, srv_slot_t *slot
2664+
#endif
2665+
)
26472666
{
26482667
ulint n_pages_purged;
26492668

@@ -2709,7 +2728,11 @@ srv_do_purge(ulint* n_total_purged)
27092728

27102729
n_pages_purged = trx_purge(
27112730
n_use_threads, srv_purge_batch_size,
2712-
(++count % rseg_truncate_frequency) == 0);
2731+
(++count % rseg_truncate_frequency) == 0
2732+
#ifdef UNIV_DEBUG
2733+
, slot
2734+
#endif
2735+
);
27132736

27142737
*n_total_purged += n_pages_purged;
27152738
} while (!srv_purge_should_exit(n_pages_purged)
@@ -2829,6 +2852,12 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
28292852

28302853
slot = srv_reserve_slot(SRV_PURGE);
28312854

2855+
#ifdef UNIV_DEBUG
2856+
UT_LIST_INIT(slot->debug_sync,
2857+
&srv_slot_t::debug_sync_t::debug_sync_list);
2858+
rw_lock_create(PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock,
2859+
SYNC_NO_ORDER_CHECK);
2860+
#endif
28322861
ulint rseg_history_len = trx_sys->rseg_history_len;
28332862

28342863
do {
@@ -2851,7 +2880,11 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
28512880

28522881
n_total_purged = 0;
28532882

2854-
rseg_history_len = srv_do_purge(&n_total_purged);
2883+
rseg_history_len = srv_do_purge(&n_total_purged
2884+
#ifdef UNIV_DEBUG
2885+
, slot
2886+
#endif
2887+
);
28552888
} while (!srv_purge_should_exit(n_total_purged));
28562889

28572890
/* The task queue should always be empty, independent of fast
@@ -3012,3 +3045,35 @@ srv_was_tablespace_truncated(const fil_space_t* space)
30123045
return (!is_system_tablespace(space->id)
30133046
&& truncate_t::was_tablespace_truncated(space->id));
30143047
}
3048+
3049+
#ifdef UNIV_DEBUG
3050+
static uint get_first_slot(srv_thread_type type)
3051+
{
3052+
switch (type) {
3053+
case SRV_MASTER:
3054+
return SRV_MASTER_SLOT;
3055+
case SRV_PURGE:
3056+
return SRV_PURGE_SLOT;
3057+
case SRV_WORKER:
3058+
/* Find an empty slot, skip the master and purge slots. */
3059+
return SRV_WORKER_SLOTS_START;
3060+
default:
3061+
ut_error;
3062+
}
3063+
}
3064+
3065+
void srv_for_each_thread(srv_thread_type type,
3066+
srv_slot_callback_t callback,
3067+
const void *arg)
3068+
{
3069+
int slot_idx= get_first_slot(type);
3070+
while(slot_idx < srv_sys.n_sys_threads
3071+
&& srv_sys.sys_threads[slot_idx].in_use
3072+
&& srv_sys.sys_threads[slot_idx].type == type)
3073+
{
3074+
srv_slot_t *slot= &srv_sys.sys_threads[slot_idx];
3075+
callback(slot, arg);
3076+
slot_idx++;
3077+
}
3078+
}
3079+
#endif

storage/innobase/trx/trx0purge.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1675,7 +1675,12 @@ trx_purge(
16751675
to submit to the work queue */
16761676
ulint batch_size,/*!< in: the maximum number of records
16771677
to purge in one batch */
1678-
booltruncate)/*!< in: truncate history if true */
1678+
booltruncate/*!< in: truncate history if true */
1679+
#ifdef UNIV_DEBUG
1680+
, srv_slot_t *slot/*!< in/out: purge coordinator
1681+
thread slot */
1682+
#endif
1683+
)
16791684
{
16801685
que_thr_t* thr = NULL;
16811686
ulint n_pages_handled;
@@ -1730,6 +1735,7 @@ trx_purge(
17301735
run_synchronously:
17311736
++purge_sys->n_submitted;
17321737

1738+
ut_d(thr->thread_slot = slot);
17331739
que_run_threads(thr);
17341740

17351741
my_atomic_addlint(

0 commit comments

Comments
 (0)