diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2019-07-25 22:17:04 +1000 |
---|---|---|
committer | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-04-27 11:51:17 +0300 |
commit | 300253acf12bf66fdea8e64abae5d717c289e559 (patch) | |
tree | 1166e1aca1f0378d147c76d73bb9ca02cc2001d5 /storage | |
parent | a35cde8cd8364edc0a23752fc5fde442c8b78a0a (diff) | |
download | mariadb-git-300253acf12bf66fdea8e64abae5d717c289e559.tar.gz |
revive innodb_debug_sync
innodb_debug_sync was introduced in commit
b393e2cb0c079b30563dcc87a62002c9c778643c and reverted in
commit fc58c1721631fcc6c9414482b3b7e90cd8e7325d due to memory leak reported
by valgrind, see MDEV-21336.
The leak is now fixed by adding `rw_lock_free(&slot->debug_sync_lock)`
after background thread working loop is finished, and the patch is
reapplied, with respect to c++98 fixes by Marko.
The missing DEBUG_SYNC for MDEV-18546 in row0vers.cc is also reapplied.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 38 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 10 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.cc | 20 | ||||
-rw-r--r-- | storage/innobase/row/row0vers.cc | 1 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 17 |
5 files changed, 86 insertions, 0 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 91d12f64fa5..22fe3b5d9ed 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19559,6 +19559,33 @@ innodb_log_checksums_update( thd, *static_cast<const my_bool*>(save)); } +#ifdef UNIV_DEBUG +static +void +innobase_debug_sync_callback(srv_slot_t *slot, const void *value) +{ + const char *value_str = *static_cast<const char* const*>(value); + size_t len = strlen(value_str) + 1; + + + // One allocation for list node object and value. + void *buf = ut_malloc_nokey(sizeof(srv_slot_t::debug_sync_t) + len-1); + srv_slot_t::debug_sync_t *sync = new(buf) srv_slot_t::debug_sync_t(); + strcpy(sync->str, value_str); + + rw_lock_x_lock(&slot->debug_sync_lock); + UT_LIST_ADD_LAST(slot->debug_sync, sync); + rw_lock_x_unlock(&slot->debug_sync_lock); +} +static +void +innobase_debug_sync_set(THD *thd, st_mysql_sys_var*, void *, const void *value) +{ + srv_for_each_thread(SRV_WORKER, innobase_debug_sync_callback, value); + srv_for_each_thread(SRV_PURGE, innobase_debug_sync_callback, value); +} +#endif + static SHOW_VAR innodb_status_variables_export[]= { {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, {NullS, NullS, SHOW_LONG} @@ -21205,6 +21232,16 @@ static MYSQL_SYSVAR_BOOL(debug_force_scrubbing, 0, "Perform extra scrubbing to increase test exposure", NULL, NULL, FALSE); + +char *innobase_debug_sync; +static MYSQL_SYSVAR_STR(debug_sync, innobase_debug_sync, + PLUGIN_VAR_NOCMDARG, + "debug_sync for innodb purge threads. " + "Use it to set up sync points for all purge threads " + "at once. The commands will be applied sequentially at" + " the beginning of purging the next undo record.", + NULL, + innobase_debug_sync_set, NULL); #endif /* UNIV_DEBUG */ static MYSQL_SYSVAR_BOOL(instrument_semaphores, innodb_instrument_semaphores, @@ -21428,6 +21465,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(background_scrub_data_check_interval), #ifdef UNIV_DEBUG MYSQL_SYSVAR(debug_force_scrubbing), + MYSQL_SYSVAR(debug_sync), #endif MYSQL_SYSVAR(instrument_semaphores), MYSQL_SYSVAR(buf_dump_status_frequency), diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index d196a4d6db6..62d7c139ee2 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -1142,6 +1142,16 @@ struct srv_slot_t{ to do */ que_thr_t* thr; /*!< suspended query thread (only used for user threads) */ +#ifdef UNIV_DEBUG + struct debug_sync_t { + UT_LIST_NODE_T(debug_sync_t) + debug_sync_list; + char str[1]; + }; + UT_LIST_BASE_NODE_T(debug_sync_t) + debug_sync; + rw_lock_t debug_sync_lock; +#endif }; #ifdef UNIV_DEBUG diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 024625e9e0a..10a0b91f8f8 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -46,6 +46,7 @@ Created 3/14/1997 Heikki Tuuri #include "handler.h" #include "ha_innodb.h" #include "fil0fil.h" +#include "debug_sync.h" /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -1208,6 +1209,25 @@ row_purge_step( node->start(); +#ifdef UNIV_DEBUG + srv_slot_t *slot = thr->thread_slot; + ut_ad(slot); + + rw_lock_x_lock(&slot->debug_sync_lock); + while (UT_LIST_GET_LEN(slot->debug_sync)) { + srv_slot_t::debug_sync_t *sync = + UT_LIST_GET_FIRST(slot->debug_sync); + bool result = debug_sync_set_action(current_thd, + sync->str, + strlen(sync->str)); + ut_a(!result); + + UT_LIST_REMOVE(slot->debug_sync, sync); + ut_free(sync); + } + rw_lock_x_unlock(&slot->debug_sync_lock); +#endif + if (!(node->undo_recs == NULL || ib_vector_is_empty(node->undo_recs))) { trx_purge_rec_t*purge_rec; diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 2d8704764d1..b9bc8418366 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -467,6 +467,7 @@ row_vers_build_clust_v_col( vcol_info->set_used(); maria_table = vcol_info->table(); } + DEBUG_SYNC(current_thd, "ib_clust_v_col_before_row_allocated"); ib_vcol_row vc(NULL); byte *record = vc.record(thd, index, &maria_table); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 44e0946f067..56c717e142b 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2601,6 +2601,13 @@ DECLARE_THREAD(srv_worker_thread)( slot = srv_reserve_slot(SRV_WORKER); +#ifdef UNIV_DEBUG + UT_LIST_INIT(slot->debug_sync, + &srv_slot_t::debug_sync_t::debug_sync_list); + rw_lock_create(PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock, + SYNC_NO_ORDER_CHECK); +#endif + ut_a(srv_n_purge_threads > 1); ut_a(ulong(my_atomic_loadlint(&srv_sys.n_threads_active[SRV_WORKER])) < srv_n_purge_threads); @@ -2625,6 +2632,8 @@ DECLARE_THREAD(srv_worker_thread)( purge_sys->latch here. */ } while (purge_sys->state != PURGE_STATE_EXIT); + ut_d(rw_lock_free(&slot->debug_sync_lock)); + srv_free_slot(slot); rw_lock_x_lock(&purge_sys->latch); @@ -2848,6 +2857,12 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( slot = srv_reserve_slot(SRV_PURGE); +#ifdef UNIV_DEBUG + UT_LIST_INIT(slot->debug_sync, + &srv_slot_t::debug_sync_t::debug_sync_list); + rw_lock_create(PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock, + SYNC_NO_ORDER_CHECK); +#endif ulint rseg_history_len = trx_sys->rseg_history_len; do { @@ -2881,6 +2896,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( shutdown state. */ ut_a(srv_get_task_queue_length() == 0); + ut_d(rw_lock_free(&slot->debug_sync_lock)); + srv_free_slot(slot); /* Note that we are shutting down. */ |