summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-03-03 10:13:56 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-03-03 10:13:56 +0200
commit5bd994b0d56d11bf62717a84172c49ca9ed37de4 (patch)
treef7889bec400f12c98686289d2d5b83d3a6449b65
parentddbc6126920c1ad0300f7f9734348309f5073de7 (diff)
downloadmariadb-git-5bd994b0d56d11bf62717a84172c49ca9ed37de4.tar.gz
MDEV-24811 Assertion find(table) failed with innodb_evict_tables_on_commit_debug
This is a backport of commit 18535a402817d8a2b8452df0f75c15dda9199acb from 10.6. lock_release(): Implement innodb_evict_tables_on_commit_debug. Before releasing any locks, collect the identifiers of tables to be evicted. After releasing all locks, look up for the tables and evict them if it is safe to do so. trx_commit_in_memory(): Invoke trx_update_mod_tables_timestamp() before lock_release(), so that our locks will protect the tables from being evicted.
-rw-r--r--storage/innobase/lock/lock0lock.cc33
-rw-r--r--storage/innobase/trx/trx0trx.cc50
2 files changed, 37 insertions, 46 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index da3dba73bee..ee57a493119 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -4263,6 +4263,19 @@ lock_check_dict_lock(
and release possible other transactions waiting because of these locks. */
void lock_release(trx_t* trx)
{
+#ifdef UNIV_DEBUG
+ std::set<table_id_t> to_evict;
+ if (innodb_evict_tables_on_commit_debug && !trx->is_recovered)
+# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
+ if (!mutex_own(&dict_sys->mutex))
+# else /* this would be more proper way to do it */
+ if (!trx->dict_operation_lock_mode && !trx->dict_operation)
+# endif
+ for (trx_mod_tables_t::const_iterator it= trx->mod_tables.begin();
+ it != trx->mod_tables.end(); ++it)
+ if (!it->first->is_temporary())
+ to_evict.insert(it->first->id);
+#endif
ulint count = 0;
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
@@ -4311,6 +4324,26 @@ void lock_release(trx_t* trx)
}
lock_mutex_exit();
+
+#ifdef UNIV_DEBUG
+ if (to_evict.empty()) {
+ return;
+ }
+ mutex_enter(&dict_sys->mutex);
+ lock_mutex_enter();
+ for (std::set<table_id_t>::const_iterator i = to_evict.begin();
+ i != to_evict.end(); ++i) {
+ if (dict_table_t *table = dict_table_open_on_id(
+ *i, TRUE, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED)) {
+ if (!table->get_ref_count()
+ && !UT_LIST_GET_LEN(table->locks)) {
+ dict_table_remove_from_cache_low(table, true);
+ }
+ }
+ }
+ lock_mutex_exit();
+ mutex_exit(&dict_sys->mutex);
+#endif
}
/* True if a lock mode is S or X */
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 609ab63ff4c..90ed4141633 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1276,22 +1276,6 @@ trx_update_mod_tables_timestamp(
const time_t now = time(NULL);
trx_mod_tables_t::const_iterator end = trx->mod_tables.end();
-#ifdef UNIV_DEBUG
-# if MYSQL_VERSION_ID >= 100405
-# define dict_sys_mutex dict_sys.mutex
-# else
-# define dict_sys_mutex dict_sys->mutex
-# endif
-
- const bool preserve_tables = !innodb_evict_tables_on_commit_debug
- || trx->is_recovered /* avoid trouble with XA recovery */
-# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
- || mutex_own(&dict_sys_mutex)
-# else /* this would be more proper way to do it */
- || trx->dict_operation_lock_mode || trx->dict_operation
-# endif
- ;
-#endif
for (trx_mod_tables_t::const_iterator it = trx->mod_tables.begin();
it != end;
@@ -1307,30 +1291,6 @@ trx_update_mod_tables_timestamp(
intrusive. */
dict_table_t* table = it->first;
table->update_time = now;
-#ifdef UNIV_DEBUG
- if (preserve_tables || table->get_ref_count()
- || UT_LIST_GET_LEN(table->locks)) {
- /* do not evict when committing DDL operations
- or if some other transaction is holding the
- table handle */
- continue;
- }
- /* recheck while holding the mutex that blocks
- table->acquire() */
- mutex_enter(&dict_sys_mutex);
- mutex_enter(&lock_sys.mutex);
- const bool do_evict = !table->get_ref_count()
- && !UT_LIST_GET_LEN(table->locks);
- mutex_exit(&lock_sys.mutex);
- if (do_evict) {
-# if MYSQL_VERSION_ID >= 100405
- dict_sys.remove(table, true);
-# else
- dict_table_remove_from_cache_low(table, true);
-# endif
- }
- mutex_exit(&dict_sys_mutex);
-#endif
}
trx->mod_tables.clear();
@@ -1398,16 +1358,10 @@ trx_commit_in_memory(
while (UNIV_UNLIKELY(trx->is_referenced())) {
ut_delay(srv_spin_wait_delay);
}
-
- trx->release_locks();
- trx->id = 0;
} else {
ut_ad(trx->read_only || !trx->rsegs.m_redo.rseg);
- trx->release_locks();
}
- DEBUG_SYNC_C("after_trx_committed_in_memory");
-
if (trx->read_only || !trx->rsegs.m_redo.rseg) {
MONITOR_INC(MONITOR_TRX_RO_COMMIT);
} else {
@@ -1415,6 +1369,10 @@ trx_commit_in_memory(
MONITOR_INC(MONITOR_TRX_RW_COMMIT);
trx->is_recovered = false;
}
+
+ trx->release_locks();
+ trx->id = 0;
+ DEBUG_SYNC_C("after_trx_committed_in_memory");
}
ut_ad(!trx->rsegs.m_redo.undo);