Browse Source

MDEV-19513: Rename dict_operation_lock to dict_sys.latch

dict_sys.lock(), dict_sys_lock(): Acquire both mutex and latch.

dict_sys.unlock(), dict_sys_unlock(): Release both mutex and latch.

dict_sys.assert_locked(): Assert that both mutex and latch are held.
bb-10.4-MDEV-19002
Marko Mäkelä 7 years ago
parent
commit
198ed24cac
  1. 3
      storage/innobase/dict/dict0crea.cc
  2. 18
      storage/innobase/dict/dict0defrag_bg.cc
  3. 54
      storage/innobase/dict/dict0dict.cc
  4. 17
      storage/innobase/dict/dict0load.cc
  5. 82
      storage/innobase/dict/dict0stats.cc
  6. 2
      storage/innobase/dict/dict0stats_bg.cc
  7. 11
      storage/innobase/fil/fil0fil.cc
  8. 6
      storage/innobase/handler/ha_innodb.cc
  9. 40
      storage/innobase/handler/handler0alter.cc
  10. 30
      storage/innobase/handler/i_s.cc
  11. 36
      storage/innobase/include/dict0dict.h
  12. 7
      storage/innobase/include/dict0mem.h
  13. 2
      storage/innobase/include/fil0fil.h
  14. 4
      storage/innobase/include/log0log.ic
  15. 2
      storage/innobase/include/row0mysql.h
  16. 6
      storage/innobase/include/trx0trx.h
  17. 10
      storage/innobase/row/row0import.cc
  18. 6
      storage/innobase/row/row0ins.cc
  19. 2
      storage/innobase/row/row0log.cc
  20. 15
      storage/innobase/row/row0merge.cc
  21. 32
      storage/innobase/row/row0mysql.cc
  22. 16
      storage/innobase/row/row0purge.cc
  23. 4
      storage/innobase/row/row0umod.cc
  24. 2
      storage/innobase/row/row0undo.cc
  25. 6
      storage/innobase/row/row0upd.cc
  26. 8
      storage/innobase/srv/srv0srv.cc

3
storage/innobase/dict/dict0crea.cc

@ -2327,8 +2327,7 @@ dict_delete_tablespace_and_datafiles(
{
dberr_t err = DB_SUCCESS;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
ut_ad(srv_sys_tablespaces_open);
trx->op_info = "delete tablespace and datafiles from dictionary";

18
storage/innobase/dict/dict0defrag_bg.cc

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2016, 2018, MariaDB Corporation.
Copyright (c) 2016, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -244,8 +244,7 @@ dict_stats_save_defrag_summary(
return DB_SUCCESS;
}
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
ret = dict_stats_save_index_stat(index, now, "n_pages_freed",
index->stat_defrag_n_pages_freed,
@ -254,8 +253,7 @@ dict_stats_save_defrag_summary(
" last defragmentation run.",
NULL);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return (ret);
}
@ -295,9 +293,7 @@ dict_stats_save_defrag_stats(
return DB_SUCCESS;
}
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
ret = dict_stats_save_index_stat(index, now, "n_page_split",
index->stat_defrag_n_page_split,
NULL,
@ -327,8 +323,6 @@ dict_stats_save_defrag_stats(
NULL);
end:
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
return (ret);
dict_sys_unlock();
return ret;
}

54
storage/innobase/dict/dict0dict.cc

@ -87,16 +87,6 @@ ib_warn_row_too_big(const dict_table_t* table);
/** the dictionary system */
dict_sys_t dict_sys;
/** @brief the data dictionary rw-latch protecting dict_sys
table create, drop, etc. reserve this in X-mode; implicit or
backround operations purge, rollback, foreign key checks reserve this
in S-mode; we cannot trust that MySQL protects implicit or background
operations a table drop since MySQL does not know of them; therefore
we need this; NOTE: a transaction which reserves this must keep book
on the mode in trx_t::dict_operation_lock_mode */
rw_lock_t* dict_operation_lock;
/** Percentage of compression failures that are allowed in a single
round */
ulong zip_failure_threshold_pct = 5;
@ -530,8 +520,7 @@ dict_table_close_and_drop(
{
dberr_t err = DB_SUCCESS;
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
ut_ad(trx->dict_operation != TRX_DICT_OP_NONE);
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
@ -1034,9 +1023,6 @@ dict_table_col_in_clustered_key(
void dict_sys_t::create()
{
ut_ad(!is_initialised());
dict_operation_lock = static_cast<rw_lock_t*>(
ut_zalloc_nokey(sizeof(*dict_operation_lock)));
ut_d(m_initialised= true);
UT_LIST_INIT(table_LRU, &dict_table_t::table_LRU);
UT_LIST_INIT(table_non_LRU, &dict_table_t::table_LRU);
@ -1050,8 +1036,7 @@ void dict_sys_t::create()
table_id_hash= hash_create(hash_size);
temp_id_hash= hash_create(hash_size);
rw_lock_create(dict_operation_lock_key,
dict_operation_lock, SYNC_DICT_OPERATION);
rw_lock_create(dict_operation_lock_key, &latch, SYNC_DICT_OPERATION);
if (!srv_read_only_mode)
{
@ -1260,9 +1245,7 @@ dict_table_can_be_evicted(
/*======================*/
dict_table_t* table) /*!< in: table to test */
{
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
ut_a(table->can_be_evicted);
ut_a(table->foreign_set.empty());
ut_a(table->referenced_set.empty());
@ -1328,8 +1311,7 @@ dict_make_room_in_cache(
ut_a(pct_check > 0);
ut_a(pct_check <= 100);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
ut_ad(dict_lru_validate());
i = len = UT_LIST_GET_LEN(dict_sys.table_LRU);
@ -1939,9 +1921,7 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep)
and free the index pages. */
trx_t* trx = trx_create();
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
/* Mimic row_mysql_lock_data_dictionary(). */
trx->dict_operation_lock_mode = RW_X_LATCH;
@ -5817,8 +5797,7 @@ dict_index_set_merge_threshold(
ut_ad(!dict_table_is_comp(dict_sys.sys_tables));
ut_ad(!dict_table_is_comp(dict_sys.sys_indexes));
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t)
+ sizeof(que_fork_t) + sizeof(upd_node_t)
@ -5866,8 +5845,7 @@ dict_index_set_merge_threshold(
mtr_commit(&mtr);
mem_heap_free(heap);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
}
#ifdef UNIV_DEBUG
@ -6449,11 +6427,7 @@ void dict_sys_t::close()
mutex_exit(&mutex);
mutex_free(&mutex);
rw_lock_free(dict_operation_lock);
ut_free(dict_operation_lock);
dict_operation_lock = NULL;
rw_lock_free(&latch);
mutex_free(&dict_foreign_err_mutex);
@ -6806,8 +6780,7 @@ dict_space_is_empty(
mtr_t mtr;
bool found = false;
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
@ -6828,8 +6801,7 @@ dict_space_is_empty(
}
mtr_commit(&mtr);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(!found);
}
@ -6847,8 +6819,7 @@ dict_space_get_id(
ulint name_len = strlen(name);
ulint id = ULINT_UNDEFINED;
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
@ -6877,8 +6848,7 @@ dict_space_get_id(
}
mtr_commit(&mtr);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(id);
}

17
storage/innobase/dict/dict0load.cc

@ -884,8 +884,7 @@ dict_update_filepath(
dberr_t err = DB_SUCCESS;
trx_t* trx;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
trx = trx_create();
trx->op_info = "update filepath";
@ -952,8 +951,7 @@ dict_replace_tablespace_and_filepath(
DBUG_EXECUTE_IF("innodb_fail_to_update_tablespace_dict",
return(DB_INTERRUPTED););
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
ut_ad(filepath);
trx = trx_create();
@ -1350,8 +1348,7 @@ static ulint dict_check_sys_tables()
DBUG_ENTER("dict_check_sys_tables");
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
mtr_start(&mtr);
@ -1487,8 +1484,7 @@ void dict_check_tablespaces_and_store_max_id()
DBUG_ENTER("dict_check_tablespaces_and_store_max_id");
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
/* Initialize the max space_id from sys header */
mtr_start(&mtr);
@ -1505,8 +1501,7 @@ void dict_check_tablespaces_and_store_max_id()
max_space_id = dict_check_sys_tables();
fil_set_max_space_id_if_bigger(max_space_id);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
DBUG_VOID_RETURN;
}
@ -2833,7 +2828,7 @@ dict_load_tablespace(
}
/* Try to open the tablespace. We set the 2nd param (fix_dict) to
false because we do not have an x-lock on dict_operation_lock */
false because we do not have an x-lock on dict_sys.latch */
table->space = fil_ibd_open(
true, false, FIL_TYPE_TABLESPACE, table->space_id,
dict_tf_to_fsp_flags(table->flags),

82
storage/innobase/dict/dict0stats.cc

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2018, MariaDB Corporation.
Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -283,8 +283,7 @@ dict_stats_exec_sql(
dberr_t err;
bool trx_started = false;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
if (!dict_stats_persistent_storage_check(true)) {
pars_info_free(pinfo);
@ -2313,8 +2312,7 @@ dict_stats_save_index_stat(
char table_utf8[MAX_TABLE_UTF8_LEN];
ut_ad(!trx || trx->internal || trx->mysql_thd);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
dict_fs2utf8(index->table->name.m_name, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
@ -2449,8 +2447,7 @@ dict_stats_save(
table_utf8, sizeof(table_utf8));
now = ut_time();
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
pinfo = pars_info_create();
@ -2488,13 +2485,10 @@ dict_stats_save(
if (ret != DB_SUCCESS) {
ib::error() << "Cannot save table statistics for table "
<< table->name << ": " << ut_strerr(ret);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
func_exit:
dict_sys_unlock();
dict_stats_snapshot_free(table);
return(ret);
return ret;
}
trx_t* trx = trx_create();
@ -2595,13 +2589,7 @@ dict_stats_save(
end:
trx_free(trx);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_stats_snapshot_free(table);
return(ret);
goto func_exit;
}
/*********************************************************************//**
@ -3406,8 +3394,7 @@ dict_stats_drop_index(
pars_info_add_str_literal(pinfo, "index_name", iname);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
ret = dict_stats_exec_sql(
pinfo,
@ -3419,8 +3406,7 @@ dict_stats_drop_index(
"index_name = :index_name;\n"
"END;\n", NULL);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
@ -3468,8 +3454,7 @@ dict_stats_delete_from_table_stats(
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@ -3504,8 +3489,7 @@ dict_stats_delete_from_index_stats(
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@ -3541,8 +3525,7 @@ dict_stats_drop_table(
char table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
/* skip tables that do not contain a database name
e.g. if we are dropping SYS_TABLES */
@ -3617,8 +3600,7 @@ dict_stats_rename_table_in_table_stats(
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@ -3661,8 +3643,7 @@ dict_stats_rename_table_in_index_stats(
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@ -3705,9 +3686,6 @@ dict_stats_rename_table(
char new_table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(!mutex_own(&dict_sys.mutex));
/* skip innodb_table_stats and innodb_index_stats themselves */
if (strcmp(old_name, TABLE_STATS_NAME) == 0
|| strcmp(old_name, INDEX_STATS_NAME) == 0
@ -3723,8 +3701,7 @@ dict_stats_rename_table(
dict_fs2utf8(new_name, new_db_utf8, sizeof(new_db_utf8),
new_table_utf8, sizeof(new_table_utf8));
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
ulint n_attempts = 0;
do {
@ -3744,11 +3721,9 @@ dict_stats_rename_table(
}
if (ret != DB_SUCCESS) {
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
os_thread_sleep(200000 /* 0.2 sec */);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
}
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
@ -3776,8 +3751,7 @@ dict_stats_rename_table(
TABLE_STATS_NAME_PRINT,
new_db_utf8, new_table_utf8,
old_db_utf8, old_table_utf8);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(ret);
}
/* else */
@ -3800,19 +3774,16 @@ dict_stats_rename_table(
}
if (ret != DB_SUCCESS) {
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
os_thread_sleep(200000 /* 0.2 sec */);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
}
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
|| ret == DB_LOCK_WAIT_TIMEOUT)
&& n_attempts < 5);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
if (ret != DB_SUCCESS) {
snprintf(errstr, errstr_sz,
@ -3853,12 +3824,10 @@ dict_stats_rename_index(
const char* old_index_name, /*!< in: old index name */
const char* new_index_name) /*!< in: new index name */
{
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys.mutex);
dict_sys_lock();
if (!dict_stats_persistent_storage_check(true)) {
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(DB_STATS_DO_NOT_EXIST);
}
@ -3891,8 +3860,7 @@ dict_stats_rename_index(
"index_name = :old_index_name;\n"
"END;\n", NULL);
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(ret);
}

2
storage/innobase/dict/dict0stats_bg.cc

@ -313,7 +313,7 @@ dict_stats_thread_init()
dict_stats_update_if_needed() is called and it may be acquired
inside that function (thus a level <=SYNC_DICT would do).
3) from row_drop_table_for_mysql() after dict_sys.mutex (SYNC_DICT)
and dict_operation_lock (SYNC_DICT_OPERATION) have been locked
and dict_sys.latch (SYNC_DICT_OPERATION) have been locked
(thus a level <SYNC_DICT && <SYNC_DICT_OPERATION would do)
So we choose SYNC_STATS_AUTO_RECALC to be about below SYNC_DICT. */

11
storage/innobase/fil/fil0fil.cc

@ -3178,11 +3178,12 @@ fil_ibd_open(
ulint tablespaces_found = 0;
ulint valid_tablespaces_found = 0;
ut_ad(!fix_dict || rw_lock_own(dict_operation_lock, RW_LOCK_X));
if (fix_dict) {
ut_d(dict_sys.assert_locked());
ut_ad(!srv_read_only_mode);
ut_ad(srv_log_file_size != 0);
}
ut_ad(!fix_dict || mutex_own(&dict_sys.mutex));
ut_ad(!fix_dict || !srv_read_only_mode);
ut_ad(!fix_dict || srv_log_file_size != 0);
ut_ad(fil_type_is_data(purpose));
/* Table flags can be ULINT_UNDEFINED if
@ -4766,7 +4767,7 @@ fil_space_validate_for_mtr_commit(
/* We are serving mtr_commit(). While there is an active
mini-transaction, we should have !space->stop_new_ops. This is
guaranteed by meta-data locks or transactional locks, or
dict_operation_lock (X-lock in DROP, S-lock in purge).
dict_sys.latch (X-lock in DROP, S-lock in purge).
However, a file I/O thread can invoke change buffer merge
while fil_check_pending_operations() is waiting for operations

6
storage/innobase/handler/ha_innodb.cc

@ -20452,10 +20452,10 @@ for purge thread */
static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table)
{
if (THDVAR(thd, background_thread)) {
/* Purge thread acquires dict_operation_lock while
processing undo log record. Release the dict_operation_lock
/* Purge thread acquires dict_sys.latch while
processing undo log record. Release it
before acquiring MDL on the table. */
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
return innodb_acquire_mdl(thd, table);
} else {
if (table->vc_templ->mysql_table_query_id

40
storage/innobase/handler/handler0alter.cc

@ -746,8 +746,7 @@ inline void dict_table_t::rollback_instant(
const char* old_v_col_names,
const ulint* col_map)
{
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
dict_index_t* index = indexes.start;
mtr_t mtr;
mtr.start();
@ -4741,8 +4740,7 @@ innobase_update_gis_column_type(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
info = pars_info_create();
@ -6733,7 +6731,7 @@ new_clustered_failed:
ut_a(ctx->new_table == temp_table);
/* n_ref_count must be 1, because purge cannot
be executing on this very table as we are
holding dict_operation_lock X-latch. */
holding dict_sys.latch X-latch. */
DBUG_ASSERT(ctx->new_table->get_ref_count() == 1);
DBUG_ASSERT(ctx->new_table->id != 0);
DBUG_ASSERT(ctx->new_table->id == ctx->trx->table_id);
@ -6946,8 +6944,7 @@ error_handling_drop_uncached:
op_ok:
#endif /* UNIV_DEBUG */
ut_ad(ctx->trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
DICT_TF2_FLAG_SET(ctx->new_table, DICT_TF2_FTS);
if (ctx->need_rebuild()) {
@ -7091,7 +7088,7 @@ error_handled:
trx_commit_for_mysql(ctx->trx);
/* n_ref_count must be 1, because purge cannot
be executing on this very table as we are
holding dict_operation_lock X-latch. */
holding dict_sys.latch X-latch. */
DBUG_ASSERT(user_table->get_ref_count() == 1 || ctx->online);
online_retry_drop_indexes_with_trx(user_table, ctx->trx);
@ -7233,9 +7230,7 @@ rename_index_try(
trx_t* trx)
{
DBUG_ENTER("rename_index_try");
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
pars_info_t* pinfo;
@ -7293,9 +7288,7 @@ void
innobase_rename_index_cache(dict_index_t* index, const char* new_name)
{
DBUG_ENTER("innobase_rename_index_cache");
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
size_t old_name_len = strlen(index->name);
size_t new_name_len = strlen(new_name);
@ -8261,10 +8254,7 @@ ha_innobase::inplace_alter_table(
bool rebuild_templ = false;
DBUG_ENTER("inplace_alter_table");
DBUG_ASSERT(!srv_read_only_mode);
ut_ad(!sync_check_iterate(sync_check()));
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_S));
DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter");
@ -8476,10 +8466,7 @@ innobase_online_rebuild_log_free(
dict_table_t* table)
{
dict_index_t* clust_index = dict_table_get_first_index(table);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
rw_lock_x_lock(&clust_index->lock);
if (clust_index->online_log) {
@ -8752,8 +8739,7 @@ innobase_drop_foreign_try(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
/* Drop the constraint from the data dictionary. */
static const char sql[] =
@ -8811,8 +8797,7 @@ innobase_rename_column_try(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
if (new_clustered) {
goto rename_foreign;
@ -9088,8 +9073,7 @@ innobase_rename_or_enlarge_column_try(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
ulint n_base;
@ -10512,7 +10496,7 @@ alter_stats_norebuild(
in a separate transaction from trx, because lock waits are not
allowed in a data dictionary transaction. (Lock waits are possible
on the statistics table, because it is directly accessible by users,
not covered by the dict_operation_lock.)
not covered by the dict_sys.latch.)
Because the data dictionary changes were already committed, orphaned
rows may be left in the statistics table if the system crashes.

30
storage/innobase/handler/i_s.cc

@ -2869,19 +2869,19 @@ i_s_fts_deleted_generic_fill(
}
/* Prevent DDL to drop fts aux tables. */
rw_lock_s_lock(dict_operation_lock);
rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_name(
fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE);
if (!user_table) {
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
} else if (!dict_table_has_fts_index(user_table)) {
dict_table_close(user_table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@ -2917,7 +2917,7 @@ i_s_fts_deleted_generic_fill(
dict_table_close(user_table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(ret);
}
@ -3730,13 +3730,13 @@ i_s_fts_index_table_fill(
}
/* Prevent DDL to drop fts aux tables. */
rw_lock_s_lock(dict_operation_lock);
rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_name(
fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE);
if (!user_table) {
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@ -3757,7 +3757,7 @@ i_s_fts_index_table_fill(
dict_table_close(user_table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
ut_free(conv_str.f_str);
@ -3899,19 +3899,19 @@ i_s_fts_config_fill(
fields = table->field;
/* Prevent DDL to drop fts aux tables. */
rw_lock_s_lock(dict_operation_lock);
rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_name(
fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE);
if (!user_table) {
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
} else if (!dict_table_has_fts_index(user_table)) {
dict_table_close(user_table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@ -3971,7 +3971,7 @@ i_s_fts_config_fill(
dict_table_close(user_table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(ret);
}
@ -6338,7 +6338,7 @@ i_s_sys_tables_fill_table_stats(
}
heap = mem_heap_create(1000);
rw_lock_s_lock(dict_operation_lock);
rw_lock_s_lock(&dict_sys.latch);
mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
@ -6372,11 +6372,11 @@ i_s_sys_tables_fill_table_stats(
err_msg);
}
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
mem_heap_empty(heap);
/* Get the next record */
rw_lock_s_lock(dict_operation_lock);
rw_lock_s_lock(&dict_sys.latch);
mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
@ -6385,7 +6385,7 @@ i_s_sys_tables_fill_table_stats(
mtr_commit(&mtr);
mutex_exit(&dict_sys.mutex);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
mem_heap_free(heap);
DBUG_RETURN(0);

36
storage/innobase/include/dict0dict.h

@ -1471,6 +1471,15 @@ public:
and DROP TABLE, as well as reading
the dictionary data for a table from
system tables */
/** @brief the data dictionary rw-latch protecting dict_sys
Table create, drop, etc. reserve this in X-mode; implicit or
backround operations purge, rollback, foreign key checks reserve this
in S-mode; not all internal InnoDB operations are covered by MDL.
This latch also prevents lock waits when accessing the InnoDB
data dictionary tables. @see trx_t::dict_operation_lock_mode */
rw_lock_t latch;
row_id_t row_id; /*!< the next row id to assign;
NOTE that at a checkpoint this
must be written to the dict system
@ -1501,7 +1510,6 @@ private:
/** hash table of temporary table IDs */
hash_table_t* temp_id_hash;
public:
/** @return a new temporary table ID */
table_id_t get_temporary_table_id() {
return temp_table_id.fetch_add(1, std::memory_order_relaxed);
@ -1603,14 +1611,36 @@ public:
}
/** Acquire a reference to a cached table. */
inline void acquire(dict_table_t* table);
#ifdef UNIV_DEBUG
/** Assert that the data dictionary is locked */
void assert_locked()
{
ut_ad(mutex_own(&mutex));
ut_ad(rw_lock_own(&latch, RW_LOCK_X));
}
#endif
/** Lock the data dictionary cache. */
void lock(const char* file, unsigned line)
{
rw_lock_x_lock_func(&latch, 0, file, line);
mutex_enter_loc(&mutex, file, line);
}
/** Unlock the data dictionary cache. */
void unlock()
{
mutex_exit(&mutex);
rw_lock_x_unlock(&latch);
}
};
/** the data dictionary cache */
extern dict_sys_t dict_sys;
/** the data dictionary rw-latch protecting dict_sys */
extern rw_lock_t* dict_operation_lock;
#define dict_table_prevent_eviction(table) dict_sys.prevent_eviction(table)
#define dict_sys_lock() dict_sys.lock(__FILE__, __LINE__)
#define dict_sys_unlock() dict_sys.unlock()
/** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */
extern dict_index_t* dict_ind_redundant;

7
storage/innobase/include/dict0mem.h

@ -948,12 +948,12 @@ struct dict_index_t {
dictionary cache */
unsigned to_be_dropped:1;
/*!< TRUE if the index is to be dropped;
protected by dict_operation_lock */
protected by dict_sys.latch */
unsigned online_status:2;
/*!< enum online_index_status.
Transitions from ONLINE_INDEX_COMPLETE (to
ONLINE_INDEX_CREATION) are protected
by dict_operation_lock and
by dict_sys.latch and
dict_sys.mutex. Other changes are
protected by index->lock. */
unsigned uncommitted:1;
@ -1835,8 +1835,7 @@ public:
/** TRUE if the table is to be dropped, but not yet actually dropped
(could in the background drop list). It is turned on at the beginning
of row_drop_table_for_mysql() and turned off just before we start to
update system tables for the drop. It is protected by
dict_operation_lock. */
update system tables for the drop. It is protected by dict_sys.latch. */
unsigned to_be_dropped:1;
/** Number of non-virtual columns defined so far. */

2
storage/innobase/include/fil0fil.h

@ -134,7 +134,7 @@ struct fil_space_t {
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
/** Number of pending buffer pool operations accessing the tablespace
without holding a table lock or dict_operation_lock S-latch
without holding a table lock or dict_sys.latch S-latch
that would prevent the table (and tablespace) from being
dropped. An example is change buffer merge.
The tablespace cannot be dropped while this is nonzero,

4
storage/innobase/include/log0log.ic

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -485,7 +485,7 @@ log_free_check(void)
static const latch_level_t latches[] = {
SYNC_DICT, /* dict_sys.mutex during
commit_try_rebuild() */
SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during
SYNC_DICT_OPERATION, /* dict_sys.latch X-latch during
commit_try_rebuild() */
SYNC_FTS_CACHE, /* fts_cache_t::lock */
SYNC_INDEX_TREE /* index->lock */

2
storage/innobase/include/row0mysql.h

@ -418,7 +418,7 @@ will remain locked.
@param[in] create_failed true=create table failed
because e.g. foreign key column
@param[in] nonatomic Whether it is permitted to release
and reacquire dict_operation_lock
and reacquire dict_sys.latch
@return error code */
dberr_t
row_drop_table_for_mysql(

6
storage/innobase/include/trx0trx.h

@ -690,7 +690,7 @@ with exactly one user transaction. There are some exceptions to this:
* For DDL operations, a subtransaction is allocated that modifies the
data dictionary tables. Lock waits and deadlocks are prevented by
acquiring the dict_operation_lock before starting the subtransaction
acquiring the dict_sys.latch before starting the subtransaction
and releasing it after committing the subtransaction.
* The purge system uses a special transaction that is not associated
@ -924,8 +924,8 @@ public:
ib_uint32_t dict_operation_lock_mode;
/*!< 0, RW_S_LATCH, or RW_X_LATCH:
the latch mode trx currently holds
on dict_operation_lock. Protected
by dict_operation_lock. */
on dict_sys.latch. Protected
by dict_sys.latch. */
time_t start_time; /*!< time the state last time became
TRX_STATE_ACTIVE */

10
storage/innobase/row/row0import.cc

@ -3856,7 +3856,7 @@ row_import_for_mysql(
/* Prevent DDL operations while we are checking. */
rw_lock_s_lock_func(dict_operation_lock, 0, __FILE__, __LINE__);
rw_lock_s_lock(&dict_sys.latch);
row_import cfg;
@ -3881,14 +3881,14 @@ row_import_for_mysql(
autoinc = cfg.m_autoinc;
}
rw_lock_s_unlock_gen(dict_operation_lock, 0);
rw_lock_s_unlock(&dict_sys.latch);
DBUG_EXECUTE_IF("ib_import_set_index_root_failure",
err = DB_TOO_MANY_CONCURRENT_TRXS;);
} else if (cfg.m_missing) {
rw_lock_s_unlock_gen(dict_operation_lock, 0);
rw_lock_s_unlock(&dict_sys.latch);
/* We don't have a schema file, we will have to discover
the index root pages from the .ibd file and skip the schema
@ -3920,7 +3920,7 @@ row_import_for_mysql(
space_flags = fetchIndexRootPages.get_space_flags();
} else {
rw_lock_s_unlock_gen(dict_operation_lock, 0);
rw_lock_s_unlock(&dict_sys.latch);
}
if (err != DB_SUCCESS) {
@ -4011,7 +4011,7 @@ row_import_for_mysql(
/* Open the tablespace so that we can access via the buffer pool.
We set the 2nd param (fix_dict = true) here because we already
have an x-lock on dict_operation_lock and dict_sys.mutex.
have an x-lock on dict_sys.latch and dict_sys.mutex.
The tablespace is initially opened as a temporary one, because
we will not be writing any redo log for it before we have invoked
fil_space_t::set_imported() to declare it a persistent tablespace. */

6
storage/innobase/row/row0ins.cc

@ -1543,7 +1543,7 @@ row_ins_set_exclusive_rec_lock(
/***************************************************************//**
Checks if foreign key constraint fails for an index entry. Sets shared locks
which lock either the success or the failure of the constraint. NOTE that
the caller must have a shared latch on dict_operation_lock.
the caller must have a shared latch on dict_sys.latch.
@return DB_SUCCESS, DB_NO_REFERENCED_ROW, or DB_ROW_IS_REFERENCED */
dberr_t
row_ins_check_foreign_constraint(
@ -1584,7 +1584,7 @@ row_ins_check_foreign_constraint(
upd_node= NULL;
#endif /* WITH_WSREP */
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S));
err = DB_SUCCESS;
@ -1990,7 +1990,7 @@ row_ins_check_foreign_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
we will release dict_sys.latch temporarily!
But the counter on the table protects the referenced
table from being dropped while the check is running. */

2
storage/innobase/row/row0log.cc

@ -3111,7 +3111,7 @@ row_log_table_apply(
stage->begin_phase_log_table();
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_S));
ut_ad(!rw_lock_own(&dict_sys.latch, RW_LOCK_S));
clust_index = dict_table_get_first_index(old_table);
if (clust_index->online_log->n_rows == 0) {

15
storage/innobase/row/row0merge.cc

@ -3755,10 +3755,9 @@ row_merge_drop_index_dict(
pars_info_t* info;
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
info = pars_info_create();
pars_info_add_ull_literal(info, "indexid", index_id);
@ -3818,17 +3817,16 @@ row_merge_drop_indexes_dict(
pars_info_t* info;
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
/* It is possible that table->n_ref_count > 1 when
locked=TRUE. In this case, all code that should have an open
handle to the table be waiting for the next statement to execute,
or waiting for a meta-data lock.
A concurrent purge will be prevented by dict_operation_lock. */
A concurrent purge will be prevented by dict_sys.latch. */
info = pars_info_create();
pars_info_add_ull_literal(info, "tableid", table_id);
@ -3868,10 +3866,9 @@ row_merge_drop_indexes(
dict_index_t* next_index;
ut_ad(!srv_read_only_mode);
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
index = dict_table_get_first_index(table);
ut_ad(dict_index_is_clust(index));
@ -3885,7 +3882,7 @@ row_merge_drop_indexes(
handle to the table be waiting for the next statement to execute,
or waiting for a meta-data lock.
A concurrent purge will be prevented by dict_operation_lock. */
A concurrent purge will be prevented by dict_sys.latch. */
if (!locked && (table->get_ref_count() > 1
|| UT_LIST_GET_FIRST(table->locks))) {
@ -4320,7 +4317,7 @@ row_merge_rename_tables_dict(
ut_ad(!srv_read_only_mode);
ut_ad(old_table != new_table);
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE
|| trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);

32
storage/innobase/row/row0mysql.cc

@ -2121,7 +2121,7 @@ row_mysql_freeze_data_dictionary_func(
{
ut_a(trx->dict_operation_lock_mode == 0);
rw_lock_s_lock_inline(dict_operation_lock, 0, file, line);
rw_lock_s_lock_inline(&dict_sys.latch, 0, file, line);
trx->dict_operation_lock_mode = RW_S_LATCH;
}
@ -2137,7 +2137,7 @@ row_mysql_unfreeze_data_dictionary(
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
trx->dict_operation_lock_mode = 0;
}
@ -2321,14 +2321,8 @@ row_mysql_lock_data_dictionary_func(
{
ut_a(trx->dict_operation_lock_mode == 0
|| trx->dict_operation_lock_mode == RW_X_LATCH);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks or lock waits can occur then in these operations */
rw_lock_x_lock_inline(dict_operation_lock, 0, file, line);
dict_sys.lock(file, line);
trx->dict_operation_lock_mode = RW_X_LATCH;
mutex_enter(&dict_sys.mutex);
}
/*********************************************************************//**
@ -2339,16 +2333,9 @@ row_mysql_unlock_data_dictionary(
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(lock_trx_has_sys_table_locks(trx) == NULL);
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
mutex_exit(&dict_sys.mutex);
rw_lock_x_unlock(dict_operation_lock);
trx->dict_operation_lock_mode = 0;
dict_sys.unlock();
}
/*********************************************************************//**
@ -2370,8 +2357,7 @@ row_create_table_for_mysql(
que_thr_t* thr;
dberr_t err;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
DBUG_EXECUTE_IF(
@ -2511,8 +2497,7 @@ row_create_index_for_mysql(
ulint len;
dict_table_t* table = index->table;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys.mutex));
ut_d(dict_sys.assert_locked());
for (i = 0; i < index->n_def; i++) {
/* Check that prefix_len and actual length
@ -3303,7 +3288,7 @@ will remain locked.
@param[in] create_failed true=create table failed
because e.g. foreign key column
@param[in] nonatomic Whether it is permitted to release
and reacquire dict_operation_lock
and reacquire dict_sys.latch
@return error code or DB_SUCCESS */
dberr_t
row_drop_table_for_mysql(
@ -3342,8 +3327,7 @@ row_drop_table_for_mysql(
nonatomic = true;
}
ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_d(dict_sys.assert_locked());
table = dict_table_open_on_name(
name, TRUE, FALSE,

16
storage/innobase/row/row0purge.cc

@ -102,7 +102,7 @@ row_purge_remove_clust_if_poss_low(
purge_node_t* node, /*!< in/out: row purge node */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
dict_index_t* index = dict_table_get_first_index(node->table);
@ -790,7 +790,7 @@ whose old history can no longer be observed.
@param[in,out] mtr mini-transaction (will be started and committed) */
static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
{
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
/* Reset DB_TRX_ID, DB_ROLL_PTR for old records. */
mtr->start();
@ -867,7 +867,7 @@ row_purge_upd_exist_or_extern_func(
{
mem_heap_t* heap;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
ut_ad(!node->table->skip_alter_undo);
@ -1058,7 +1058,7 @@ row_purge_parse_undo_rec(
for this row */
try_again:
rw_lock_s_lock_inline(dict_operation_lock, 0, __FILE__, __LINE__);
rw_lock_s_lock_inline(&dict_sys.latch, 0, __FILE__, __LINE__);
node->table = dict_table_open_on_id(
table_id, FALSE, DICT_TABLE_OP_NORMAL);
@ -1089,7 +1089,7 @@ try_again:
if (!mysqld_server_started) {
dict_table_close(node->table, FALSE, FALSE);
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
return(false);
}
@ -1119,7 +1119,7 @@ inaccessible:
dict_table_close(node->table, FALSE, FALSE);
node->table = NULL;
err_exit:
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
node->skip(table_id, trx_id);
return(false);
}
@ -1255,10 +1255,10 @@ row_purge(
node, undo_rec, thr, updated_extern);
if (!node->vcol_info.is_used()) {
rw_lock_s_unlock(dict_operation_lock);
rw_lock_s_unlock(&dict_sys.latch);
}
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_S));
ut_ad(!rw_lock_own(&dict_sys.latch, RW_LOCK_S));
if (purged
|| srv_shutdown_state != SRV_SHUTDOWN_NONE

4
storage/innobase/row/row0umod.cc

@ -270,7 +270,7 @@ row_undo_mod_clust(
ut_ad(thr_get_trx(thr) == node->trx);
ut_ad(node->trx->dict_operation_lock_mode);
ut_ad(node->trx->in_rollback);
ut_ad(rw_lock_own_flagged(dict_operation_lock,
ut_ad(rw_lock_own_flagged(&dict_sys.latch,
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
log_free_check();
@ -327,7 +327,7 @@ row_undo_mod_clust(
}
/* Online rebuild cannot be initiated while we are holding
dict_operation_lock and index->lock. (It can be aborted.) */
dict_sys.latch and index->lock. (It can be aborted.) */
ut_ad(online || !dict_index_is_online_ddl(index));
if (err == DB_SUCCESS && online) {

2
storage/innobase/row/row0undo.cc

@ -420,7 +420,7 @@ row_undo(
/* Prevent DROP TABLE etc. while we are rolling back this row.
If we are doing a TABLE CREATE or some other dictionary operation,
then we already have dict_operation_lock locked in x-mode. Do not
then we already have dict_sys.latch locked in x-mode. Do not
try to lock again, because that would cause a hang. */
trx_t* trx = node->trx;

6
storage/innobase/row/row0upd.cc

@ -122,7 +122,7 @@ row_upd_changes_first_fields_binary(
Checks if index currently is mentioned as a referenced index in a foreign
key constraint.
NOTE that since we do not hold dict_operation_lock when leaving the
NOTE that since we do not hold dict_sys.latch when leaving the
function, it may be that the referencing table has been dropped when
we leave this function: this function is only for heuristic use!
@ -289,7 +289,7 @@ row_upd_check_references_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
we will release dict_sys.latch temporarily!
But the inc_fk_checks() protects foreign_table from
being dropped while the check is running. */
@ -397,7 +397,7 @@ wsrep_row_upd_check_foreign_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
we will release dict_sys.latch temporarily!
But the counter on the table protects 'foreign' from
being dropped while the check is running. */

8
storage/innobase/srv/srv0srv.cc

@ -1996,16 +1996,12 @@ srv_master_evict_from_table_cache(
{
ulint n_tables_evicted = 0;
rw_lock_x_lock(dict_operation_lock);
dict_mutex_enter_for_mysql();
dict_sys_lock();
n_tables_evicted = dict_make_room_in_cache(
innobase_get_table_cache_size(), pct_check);
dict_mutex_exit_for_mysql();
rw_lock_x_unlock(dict_operation_lock);
dict_sys_unlock();
return(n_tables_evicted);
}

Loading…
Cancel
Save