Skip to content

Commit

Permalink
MDEV-35000: dict_table_close() is a performance hog
Browse files Browse the repository at this point in the history
dict_table_close(table): Replaced with table->release().

dict_table_close(table, thd, mdl): Remove the parameter "dict_locked".
Do not try to invalidate the statistics.

InnoDB_share::~InnoDB_share(): Deinitialize the statistics when the
last table handle is closed.

ha_innobase::innodb_share_register(): Register InnoDB_share(table)
so that the statistics will be deinitialized after the last
ha_innobase::close().

ha_innobase::statistics_init(): Replaces dict_stats_init(table).
  • Loading branch information
dr-m committed Jan 20, 2025
1 parent b89fbcc commit dd3f056
Show file tree
Hide file tree
Showing 19 changed files with 419 additions and 685 deletions.
18 changes: 9 additions & 9 deletions storage/innobase/dict/dict0defrag_bg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static void dict_stats_process_entry_from_defrag_pool(THD *thd)
? dict_table_find_index_on_id(table, index_id) : nullptr)
if (index->is_btree())
dict_stats_save_defrag_stats(index);
dict_table_close(table, false, thd, mdl);
dict_table_close(table, thd, mdl);
}
}

Expand Down Expand Up @@ -230,7 +230,7 @@ dberr_t dict_stats_save_defrag_summary(dict_index_t *index, THD *thd)
{
release_and_exit:
if (table_stats)
dict_table_close(table_stats, false, thd, mdl_table);
dict_table_close(table_stats, thd, mdl_table);
return DB_STATS_DO_NOT_EXIST;
}

Expand All @@ -246,7 +246,7 @@ dberr_t dict_stats_save_defrag_summary(dict_index_t *index, THD *thd)
goto release_and_exit;
if (strcmp(index_stats->name.m_name, INDEX_STATS_NAME))
{
dict_table_close(index_stats, false, thd, mdl_index);
dict_table_close(index_stats, thd, mdl_index);
goto release_and_exit;
}

Expand All @@ -272,9 +272,9 @@ dberr_t dict_stats_save_defrag_summary(dict_index_t *index, THD *thd)
trx->rollback();

if (table_stats)
dict_table_close(table_stats, true, thd, mdl_table);
dict_table_close(table_stats, thd, mdl_table);
if (index_stats)
dict_table_close(index_stats, true, thd, mdl_index);
dict_table_close(index_stats, thd, mdl_index);

row_mysql_unlock_data_dictionary(trx);
trx->free();
Expand Down Expand Up @@ -367,7 +367,7 @@ dict_stats_save_defrag_stats(
{
release_and_exit:
if (table_stats)
dict_table_close(table_stats, false, thd, mdl_table);
dict_table_close(table_stats, thd, mdl_table);
return DB_STATS_DO_NOT_EXIST;
}

Expand All @@ -384,7 +384,7 @@ dict_stats_save_defrag_stats(

if (strcmp(index_stats->name.m_name, INDEX_STATS_NAME))
{
dict_table_close(index_stats, false, thd, mdl_index);
dict_table_close(index_stats, thd, mdl_index);
goto release_and_exit;
}

Expand Down Expand Up @@ -424,9 +424,9 @@ dict_stats_save_defrag_stats(
trx->rollback();

if (table_stats)
dict_table_close(table_stats, true, thd, mdl_table);
dict_table_close(table_stats, thd, mdl_table);
if (index_stats)
dict_table_close(index_stats, true, thd, mdl_index);
dict_table_close(index_stats, thd, mdl_index);
row_mysql_unlock_data_dictionary(trx);
trx->free();

Expand Down
72 changes: 8 additions & 64 deletions storage/innobase/dict/dict0dict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,70 +195,6 @@ dict_tables_have_same_db(
return(FALSE);
}

/** Decrement the count of open handles */
void dict_table_close(dict_table_t *table)
{
if (table->get_ref_count() == 1 && table->stats_is_persistent() &&
strchr(table->name.m_name, '/'))
{
/* It looks like we are closing the last handle. The user could
have executed FLUSH TABLES in order to have the statistics reloaded
from the InnoDB persistent statistics tables. We must acquire
exclusive dict_sys.latch to prevent a race condition with another
thread concurrently acquiring a handle on the table. */
dict_sys.lock(SRW_LOCK_CALL);
if (table->release())
{
table->stats_mutex_lock();
if (table->get_ref_count() == 0)
dict_stats_deinit(table);
table->stats_mutex_unlock();
}
dict_sys.unlock();
}
else
table->release();
}

/** Decrements the count of open handles of a table.
@param[in,out] table table
@param[in] dict_locked whether dict_sys.latch is being held
@param[in] thd thread to release MDL
@param[in] mdl metadata lock or NULL if the thread
is a foreground one. */
void
dict_table_close(
dict_table_t* table,
bool dict_locked,
THD* thd,
MDL_ticket* mdl)
{
if (!dict_locked)
dict_table_close(table);
else
{
if (table->release() && table->stats_is_persistent() &&
strchr(table->name.m_name, '/'))
{
/* Force persistent stats re-read upon next open of the table so
that FLUSH TABLE can be used to forcibly fetch stats from disk if
they have been manually modified. */
table->stats_mutex_lock();
if (table->get_ref_count() == 0)
dict_stats_deinit(table);
table->stats_mutex_unlock();
}

ut_ad(dict_lru_validate());
ut_ad(dict_sys.find(table));
}

if (!thd || !mdl);
else if (MDL_context *mdl_context= static_cast<MDL_context*>
(thd_mdl_context(thd)))
mdl_context->release_lock(mdl);
}

/** Check if the table has a given (non_virtual) column.
@param[in] table table object
@param[in] col_name column name
Expand Down Expand Up @@ -585,6 +521,14 @@ dict_index_get_nth_field_pos(
return(ULINT_UNDEFINED);
}

void mdl_release(THD *thd, MDL_ticket *mdl) noexcept
{
if (!thd || !mdl);
else if (MDL_context *mdl_context= static_cast<MDL_context*>
(thd_mdl_context(thd)))
mdl_context->release_lock(mdl);
}

/** Parse the table file name into table name and database name.
@tparam dict_frozen whether the caller holds dict_sys.latch
@param[in,out] db_name database name buffer
Expand Down
Loading

0 comments on commit dd3f056

Please sign in to comment.