summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-11-08 17:34:34 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2022-11-08 17:34:34 +0200
commite572c745dc04ac7659a40849abce62f39a0b09d4 (patch)
tree4c2e87d76235a80bbfa297f02b18ecde95f7dc2b /storage/innobase/dict
parentf4519fb772b2c2c0a6dcb0b93cb147e5dc1627b2 (diff)
downloadmariadb-git-e572c745dc04ac7659a40849abce62f39a0b09d4.tar.gz
MDEV-29504/MDEV-29849 TRUNCATE breaks FOREIGN KEY locking
ha_innobase::referenced_by_foreign_key(): Protect the check with dict_sys.freeze(), to prevent races with TRUNCATE TABLE. The test innodb.instant_alter_crash has been adjusted for this additional locking. dict_table_is_referenced_by_foreign_key(): Removed (merged to the only caller). create_table_info_t::create_table(): Ignore missing indexes for FOREIGN KEY constraints if foreign_key_checks=0. create_table_info_t::create_table_update_dict(): Rewritten as a static function. Do not return any error. ha_innobase::create(): When trx!=nullptr and we are operating on a persistent table, do not rollback, commit, or release the data dictionary latch. ha_innobase::truncate(): Protect the entire critical section with an exclusive dict_sys.latch, so that ha_innobase::referenced_by_foreign_key() on referenced tables will return a consistent result. In case of a failure, invoke dict_load_foreigns() to restore also any FOREIGN KEY constraints. ha_innobase::free_foreign_key_create_info(): Define inline. lock_release(): Disregard innodb_evict_tables_on_commit_debug=ON when dict_sys.locked() holds. It would hold when fts_load_stopword() is invoked by create_table_info_t::create_table_update_dict(). dict_sys_t::locked(): Return whether the current thread is holding the exclusive dict_sys.latch. dict_sys_t::frozen_not_locked(): Return whether any thread is holding a shared dict_sys.latch. In the test main.mysql_upgrade, the InnoDB persistent statistics will no longer be recalculated in ha_innobase::open() as part of CHECK TABLE ... FOR UPGRADE. They were deleted earlier in the test. Tested by: Matthias Leich
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0dict.cc22
1 files changed, 5 insertions, 17 deletions
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 43ccf8c4d09..362b949e10f 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -685,8 +685,7 @@ dict_acquire_mdl_shared(dict_table_t *table,
}
else
{
- ut_ad(dict_sys.frozen());
- ut_ad(!dict_sys.locked());
+ ut_ad(dict_sys.frozen_not_locked());
db_len= dict_get_db_name_len(table->name.m_name);
}
@@ -1003,7 +1002,7 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
latch_ex_wait_start.store(0, std::memory_order_relaxed);
ut_ad(!latch_readers);
ut_ad(!latch_ex);
- ut_d(latch_ex= true);
+ ut_d(latch_ex= pthread_self());
return;
}
@@ -1021,15 +1020,15 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
latch.wr_lock(SRW_LOCK_ARGS(file, line));
ut_ad(!latch_readers);
ut_ad(!latch_ex);
- ut_d(latch_ex= true);
+ ut_d(latch_ex= pthread_self());
}
#ifdef UNIV_PFS_RWLOCK
ATTRIBUTE_NOINLINE void dict_sys_t::unlock()
{
- ut_ad(latch_ex);
+ ut_ad(latch_ex == pthread_self());
ut_ad(!latch_readers);
- ut_d(latch_ex= false);
+ ut_d(latch_ex= 0);
latch.wr_unlock();
}
@@ -2749,17 +2748,6 @@ dict_index_build_internal_fts(
}
/*====================== FOREIGN KEY PROCESSING ========================*/
-/*********************************************************************//**
-Checks if a table is referenced by foreign keys.
-@return TRUE if table is referenced by a foreign key */
-ibool
-dict_table_is_referenced_by_foreign_key(
-/*====================================*/
- const dict_table_t* table) /*!< in: InnoDB table */
-{
- return(!table->referenced_set.empty());
-}
-
/**********************************************************************//**
Removes a foreign constraint struct from the dictionary cache. */
void