Skip to content

Commit

Permalink
MDEV-23370 innodb_fts.innodb_fts_misc failed in buildbot, server cras…
Browse files Browse the repository at this point in the history
…hed in dict_table_autoinc_destroy

This issue is caused by MDEV-22456 ad6171b. Fix involves the backported version of 10.4 patch
MDEV-22778 5f2628d and few parts of
MDEV-17441 (e9a5f28).

dict_table_t::stats_latch_created: Removed

dict_table_t::stats_latch: make value member and always lock it for
simplicity even for stats cloned table.

zip_pad_info_t::mutex_created: Removed

zip_pad_info_t::mutex: make member value instead of pointer

os0once.h: Removed

dict_table_remove_from_cache_low(): Ensure that fts_free() is always
called, even if dict_mem_table_free() is deferred until
btr_search_lazy_free().

InnoDB would always zip_pad_info_t::mutex and
dict_table_t::autoinc_mutex, even for tables are not in
ROW_FORMAT=COMPRESSED nor include any AUTO_INCREMENT column.
  • Loading branch information
Thirunarayanan committed Oct 25, 2020
1 parent 987df9b commit 3ba8f61
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 399 deletions.
150 changes: 17 additions & 133 deletions storage/innobase/dict/dict0dict.cc
Expand Up @@ -60,7 +60,6 @@ extern uint ibuf_debug;
#include "lock0lock.h"
#include "mach0data.h"
#include "mem0mem.h"
#include "os0once.h"
#include "page0page.h"
#include "page0zip.h"
#include "pars0pars.h"
Expand Down Expand Up @@ -268,76 +267,6 @@ dict_mutex_exit_for_mysql(void)
mutex_exit(&dict_sys->mutex);
}

/** Allocate and init a dict_table_t's stats latch.
This function must not be called concurrently on the same table object.
@param[in,out] table_void table whose stats latch to create */
static
void
dict_table_stats_latch_alloc(
void* table_void)
{
dict_table_t* table = static_cast<dict_table_t*>(table_void);

/* Note: rw_lock_create() will call the constructor */

table->stats_latch = static_cast<rw_lock_t*>(
ut_malloc_nokey(sizeof(rw_lock_t)));

ut_a(table->stats_latch != NULL);

rw_lock_create(dict_table_stats_key, table->stats_latch,
SYNC_INDEX_TREE);
}

/** Deinit and free a dict_table_t's stats latch.
This function must not be called concurrently on the same table object.
@param[in,out] table table whose stats latch to free */
static
void
dict_table_stats_latch_free(
dict_table_t* table)
{
rw_lock_free(table->stats_latch);
ut_free(table->stats_latch);
}

/** Create a dict_table_t's stats latch or delay for lazy creation.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to create
@param[in] enabled if false then the latch is disabled
and dict_table_stats_lock()/unlock() become noop on this table. */
void
dict_table_stats_latch_create(
dict_table_t* table,
bool enabled)
{
if (!enabled) {
table->stats_latch = NULL;
table->stats_latch_created = os_once::DONE;
return;
}

/* We create this lazily the first time it is used. */
table->stats_latch = NULL;
table->stats_latch_created = os_once::NEVER_DONE;
}

/** Destroy a dict_table_t's stats latch.
This function is only called from either single threaded environment
or from a thread that has not shared the table object with other threads.
@param[in,out] table table whose stats latch to destroy */
void
dict_table_stats_latch_destroy(
dict_table_t* table)
{
if (table->stats_latch_created == os_once::DONE
&& table->stats_latch != NULL) {

dict_table_stats_latch_free(table);
}
}

/** Lock the appropriate latch to protect a given table's statistics.
@param[in] table table whose stats to lock
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
Expand All @@ -349,23 +278,12 @@ dict_table_stats_lock(
ut_ad(table != NULL);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

os_once::do_or_wait_for_done(
&table->stats_latch_created,
dict_table_stats_latch_alloc, table);

if (table->stats_latch == NULL) {
/* This is a dummy table object that is private in the current
thread and is not shared between multiple threads, thus we
skip any locking. */
return;
}

switch (latch_mode) {
case RW_S_LATCH:
rw_lock_s_lock(table->stats_latch);
rw_lock_s_lock(&table->stats_latch);
break;
case RW_X_LATCH:
rw_lock_x_lock(table->stats_latch);
rw_lock_x_lock(&table->stats_latch);
break;
case RW_NO_LATCH:
/* fall through */
Expand All @@ -385,19 +303,12 @@ dict_table_stats_unlock(
ut_ad(table != NULL);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);

if (table->stats_latch == NULL) {
/* This is a dummy table object that is private in the current
thread and is not shared between multiple threads, thus we
skip any locking. */
return;
}

switch (latch_mode) {
case RW_S_LATCH:
rw_lock_s_unlock(table->stats_latch);
rw_lock_s_unlock(&table->stats_latch);
break;
case RW_X_LATCH:
rw_lock_x_unlock(table->stats_latch);
rw_lock_x_unlock(&table->stats_latch);
break;
case RW_NO_LATCH:
/* fall through */
Expand Down Expand Up @@ -737,46 +648,14 @@ dict_table_get_nth_v_col_mysql(
return(dict_table_get_nth_v_col(table, i));
}

/** Allocate and init the autoinc latch of a given table.
This function must not be called concurrently on the same table object.
@param[in,out] table_void table whose autoinc latch to create */
static
void
dict_table_autoinc_alloc(
void* table_void)
{
dict_table_t* table = static_cast<dict_table_t*>(table_void);
table->autoinc_mutex = UT_NEW_NOKEY(ib_mutex_t());
ut_a(table->autoinc_mutex != NULL);
mutex_create(LATCH_ID_AUTOINC, table->autoinc_mutex);
}

/** Allocate and init the zip_pad_mutex of a given index.
This function must not be called concurrently on the same index object.
@param[in,out] index_void index whose zip_pad_mutex to create */
static
void
dict_index_zip_pad_alloc(
void* index_void)
{
dict_index_t* index = static_cast<dict_index_t*>(index_void);
index->zip_pad.mutex = UT_NEW_NOKEY(SysMutex());
ut_a(index->zip_pad.mutex != NULL);
mutex_create(LATCH_ID_ZIP_PAD_MUTEX, index->zip_pad.mutex);
}

/********************************************************************//**
Acquire the autoinc lock. */
void
dict_table_autoinc_lock(
/*====================*/
dict_table_t* table) /*!< in/out: table */
{
os_once::do_or_wait_for_done(
&table->autoinc_mutex_created,
dict_table_autoinc_alloc, table);

mutex_enter(table->autoinc_mutex);
mysql_mutex_lock(&table->autoinc_mutex);
}

/** Acquire the zip_pad_mutex latch.
Expand All @@ -786,11 +665,7 @@ void
dict_index_zip_pad_lock(
dict_index_t* index)
{
os_once::do_or_wait_for_done(
&index->zip_pad.mutex_created,
dict_index_zip_pad_alloc, index);

mutex_enter(index->zip_pad.mutex);
mysql_mutex_lock(&index->zip_pad.mutex);
}

/** Get all the FTS indexes on a table.
Expand Down Expand Up @@ -825,7 +700,7 @@ dict_table_autoinc_unlock(
/*======================*/
dict_table_t* table) /*!< in/out: table */
{
mutex_exit(table->autoinc_mutex);
mysql_mutex_unlock(&table->autoinc_mutex);
}

/** Looks for column n in an index.
Expand Down Expand Up @@ -1276,6 +1151,8 @@ dict_table_add_to_cache(

dict_table_add_system_columns(table, heap);

mysql_mutex_init(0, &table->autoinc_mutex, NULL);

table->cached = TRUE;

fold = ut_fold_string(table->name.m_name);
Expand Down Expand Up @@ -1419,7 +1296,7 @@ dict_index_t *dict_index_t::clone() const
(mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_sample_sizes));
index->stat_n_non_null_key_vals= static_cast<ib_uint64_t*>
(mem_heap_zalloc(heap, n_uniq * sizeof *stat_n_non_null_key_vals));
memset(&index->zip_pad, 0, sizeof index->zip_pad);
mysql_mutex_init(0, &index->zip_pad.mutex, NULL);
return index;
}

Expand Down Expand Up @@ -2133,8 +2010,15 @@ dict_table_remove_from_cache_low(
UT_DELETE(table->vc_templ);
}

mysql_mutex_destroy(&table->autoinc_mutex);
#ifdef BTR_CUR_HASH_ADAPT
if (UNIV_UNLIKELY(UT_LIST_GET_LEN(table->freed_indexes) != 0)) {
if (table->fts) {
fts_optimize_remove_table(table);
fts_free(table);
table->fts = NULL;
}

table->vc_templ = NULL;
table->id = 0;
return;
Expand Down
42 changes: 19 additions & 23 deletions storage/innobase/dict/dict0mem.cc
Expand Up @@ -118,20 +118,15 @@ static bool dict_mem_table_is_system(char *name)
}
}

/**********************************************************************//**
Creates a table memory object.
@return own: table object */
dict_table_t*
dict_mem_table_create(
/*==================*/
const char* name, /*!< in: table name */
ulint space, /*!< in: space where the clustered index of
the table is placed */
ulint n_cols, /*!< in: total number of columns including
virtual and non-virtual columns */
ulint n_v_cols,/*!< in: number of virtual columns */
ulint flags, /*!< in: table flags */
ulint flags2) /*!< in: table flags2 */
const char* name,
ulint space,
ulint n_cols,
ulint n_v_cols,
ulint flags,
ulint flags2,
bool init_stats_latch)
{
dict_table_t* table;
mem_heap_t* heap;
Expand Down Expand Up @@ -170,16 +165,9 @@ dict_mem_table_create(
table->v_cols = static_cast<dict_v_col_t*>(
mem_heap_alloc(heap, n_v_cols * sizeof(*table->v_cols)));

/* true means that the stats latch will be enabled -
dict_table_stats_lock() will not be noop. */
dict_table_stats_latch_create(table, true);

table->autoinc_lock = static_cast<ib_lock_t*>(
mem_heap_alloc(heap, lock_get_size()));

/* lazy creation of table autoinc latch */
dict_table_autoinc_create_lazy(table);

/* If the table has an FTS index or we are in the process
of building one, create the table->fts */
if (dict_table_has_fts_index(table)
Expand All @@ -194,6 +182,12 @@ dict_mem_table_create(
new(&table->foreign_set) dict_foreign_set();
new(&table->referenced_set) dict_foreign_set();

if (init_stats_latch) {
rw_lock_create(dict_table_stats_key, &table->stats_latch,
SYNC_INDEX_TREE);
table->stats_latch_inited = true;
}

return(table);
}

Expand Down Expand Up @@ -222,9 +216,7 @@ dict_mem_table_free(
}
}

dict_table_autoinc_destroy(table);
dict_mem_table_free_foreign_vcol_set(table);
dict_table_stats_latch_destroy(table);

table->foreign_set.~dict_foreign_set();
table->referenced_set.~dict_foreign_set();
Expand All @@ -245,6 +237,10 @@ dict_mem_table_free(
UT_DELETE(table->s_cols);
}

if (table->stats_latch_inited) {
rw_lock_free(&table->stats_latch);
}

mem_heap_free(table->heap);
}

Expand Down Expand Up @@ -767,7 +763,7 @@ dict_mem_index_create(
dict_mem_fill_index_struct(index, heap, table_name, index_name,
space, type, n_fields);

dict_index_zip_pad_mutex_create_lazy(index);
mysql_mutex_init(0, &index->zip_pad.mutex, NULL);

if (type & DICT_SPATIAL) {
index->rtr_track = static_cast<rtr_info_track_t*>(
Expand Down Expand Up @@ -1082,7 +1078,7 @@ dict_mem_index_free(
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);

dict_index_zip_pad_mutex_destroy(index);
mysql_mutex_destroy(&index->zip_pad.mutex);

if (dict_index_is_spatial(index)) {
rtr_info_active::iterator it;
Expand Down
10 changes: 4 additions & 6 deletions storage/innobase/dict/dict0stats.cc
Expand Up @@ -33,6 +33,7 @@ Created Jan 06, 2010 Vasil Dimov
#include "pars0pars.h"
#include <mysql_com.h>
#include "btr0btr.h"
#include "sync0sync.h"

#include <algorithm>
#include <map>
Expand Down Expand Up @@ -418,11 +419,6 @@ dict_stats_table_clone_create(

t->corrupted = table->corrupted;

/* This private object "t" is not shared with other threads, so
we do not need the stats_latch (thus we pass false below). The
dict_table_stats_lock()/unlock() routines will do nothing. */
dict_table_stats_latch_create(t, false);

UT_LIST_INIT(t->indexes, &dict_index_t::indexes);
#ifdef BTR_CUR_HASH_ADAPT
UT_LIST_INIT(t->freed_indexes, &dict_index_t::indexes);
Expand Down Expand Up @@ -490,6 +486,8 @@ dict_stats_table_clone_create(

ut_d(t->magic_n = DICT_TABLE_MAGIC_N);

rw_lock_create(dict_table_stats_key, &t->stats_latch, SYNC_INDEX_TREE);

return(t);
}

Expand All @@ -502,7 +500,7 @@ dict_stats_table_clone_free(
/*========================*/
dict_table_t* t) /*!< in: dummy table object to free */
{
dict_table_stats_latch_destroy(t);
rw_lock_free(&t->stats_latch);
mem_heap_free(t->heap);
}

Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/ibuf/ibuf0ibuf.cc
Expand Up @@ -1447,7 +1447,7 @@ ibuf_dummy_index_create(

table = dict_mem_table_create("IBUF_DUMMY",
DICT_HDR_SPACE, n, 0,
comp ? DICT_TF_COMPACT : 0, 0);
comp ? DICT_TF_COMPACT : 0, 0, false);

index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
DICT_HDR_SPACE, 0, n);
Expand Down

0 comments on commit 3ba8f61

Please sign in to comment.