diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-03-03 10:13:56 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-03-03 10:13:56 +0200 |
commit | 5bd994b0d56d11bf62717a84172c49ca9ed37de4 (patch) | |
tree | f7889bec400f12c98686289d2d5b83d3a6449b65 | |
parent | ddbc6126920c1ad0300f7f9734348309f5073de7 (diff) | |
download | mariadb-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.cc | 33 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 50 |
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); |