Commit 947b0b57 authored by Marko Mäkelä's avatar Marko Mäkelä

Implement innodb_evict_tables_on_commit_debug

Some bugs are detected only after a table definition has been evicted
and then reloaded to the InnoDB data dictionary cache.

For debug builds, introduce the settable Boolean configuration parameter
innodb_evict_tables_on_commit_debug that can be set to request InnoDB
to attempt to evict table definitions from the data dictionary cache
whenever a transaction is committed.

This has been tested on 10.3 and 10.4 with the following:

./mysql-test-run.pl --mysqld=--loose-innodb-evict-tables-on-commit-debug

You can also use the following:

SET GLOBAL innodb_evict_tables_on_commit_debug=ON;
SET GLOBAL innodb_evict_tables_on_commit_debug=OFF;

The parameter affects the commit (or rollback or abort) of
transactions that have modified persistent InnoDB tables.
parent b96e4424
......@@ -5,6 +5,7 @@ variable_name not in (
'innodb_disallow_writes', # only available WITH_WSREP
'innodb_numa_interleave', # only available WITH_NUMA
'innodb_sched_priority_cleaner', # linux only
'innodb_evict_tables_on_commit_debug', # one may want to override this
'innodb_use_native_aio', # default value depends on OS
'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing
order by variable_name;
......
......@@ -12,6 +12,7 @@ select * from information_schema.system_variables
'innodb_disallow_writes', # only available WITH_WSREP
'innodb_numa_interleave', # only available WITH_NUMA
'innodb_sched_priority_cleaner', # linux only
'innodb_evict_tables_on_commit_debug', # one may want to override this
'innodb_use_native_aio', # default value depends on OS
'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing
order by variable_name;
......@@ -235,6 +235,7 @@ extern my_bool srv_background_scrub_data_compressed;
extern uint srv_background_scrub_data_interval;
extern uint srv_background_scrub_data_check_interval;
#ifdef UNIV_DEBUG
my_bool innodb_evict_tables_on_commit_debug;
extern my_bool srv_scrub_force_testing;
#endif
......@@ -19900,6 +19901,11 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug,
" but the each purges were not done yet.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(evict_tables_on_commit_debug,
innodb_evict_tables_on_commit_debug, PLUGIN_VAR_OPCMDARG,
"On transaction commit, try to evict tables from the data dictionary cache.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_UINT(data_file_size_debug,
srv_sys_space_size_debug,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
......@@ -20265,6 +20271,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(trx_rseg_n_slots_debug),
MYSQL_SYSVAR(limit_optimistic_insert_debug),
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
MYSQL_SYSVAR(evict_tables_on_commit_debug),
MYSQL_SYSVAR(data_file_size_debug),
MYSQL_SYSVAR(fil_make_page_dirty_debug),
MYSQL_SYSVAR(saved_page_number_debug),
......
......@@ -3,7 +3,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2018, MariaDB Corporation.
Copyright (c) 2013, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -536,6 +536,7 @@ extern my_bool srv_ibuf_disable_background_merge;
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
#ifdef UNIV_DEBUG
extern my_bool innodb_evict_tables_on_commit_debug;
extern my_bool srv_sync_debug;
extern my_bool srv_purge_view_update_only_debug;
......
......@@ -1230,6 +1230,22 @@ 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;
......@@ -1243,7 +1259,27 @@ trx_update_mod_tables_timestamp(
"garbage" in table->update_time is justified because
protecting it with a latch here would be too performance
intrusive. */
it->first->update_time = now;
dict_table_t* table = it->first;
table->update_time = now;
#ifdef UNIV_DEBUG
if (preserve_tables || table->get_ref_count()) {
/* 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);
if (!table->get_ref_count()) {
# 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();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment