From fbb6bba1cff0cf9c0f52305bf946ac6e2be87f34 Mon Sep 17 00:00:00 2001 From: Prerit Jain Date: Sun, 29 Sep 2024 05:24:14 -0700 Subject: [PATCH] Perform thd_status aggregation using mdl mutex Summary: We have seen that there is high contention and stalls during status aggregation. The mutex used over there does not work well with scheduler. Rather, we want a mutex which allows the waiters to yield the scheduler when waiting for the lock and get notified of the lock when available. Differential Revision: D63607467 fbshipit-source-id: 7d5b7e06b344271619522f73aa2d196d0a19ef7a --- mysql-test/r/mysqld--help-notwin.result | 5 ++ mysql-test/suite/sys_vars/r/all_vars.result | 2 + mysql-test/t/all_persisted_variables.test | 1 + sql/binlog.cc | 11 ++- sql/mdl.cc | 25 ++++-- sql/mdl.h | 7 +- sql/mysqld.cc | 31 +++---- sql/mysqld.h | 3 +- sql/sql_class.cc | 50 +++++++---- sql/sql_class.h | 5 ++ sql/sql_parse.cc | 8 +- sql/sql_reload.cc | 2 +- sql/sql_show.cc | 83 ++++++++++++++----- sql/sys_vars.cc | 8 ++ storage/perfschema/pfs_variable.cc | 56 +++++-------- storage/perfschema/pfs_visitor.cc | 4 +- storage/perfschema/table_global_status.cc | 8 +- storage/perfschema/table_session_status.cc | 4 +- storage/perfschema/table_status_by_account.cc | 8 +- storage/perfschema/table_status_by_host.cc | 8 +- storage/perfschema/table_status_by_thread.cc | 9 +- storage/perfschema/table_status_by_user.cc | 8 +- 22 files changed, 221 insertions(+), 125 deletions(-) diff --git a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result index fb8b76dd94de..726474468699 100644 --- a/mysql-test/r/mysqld--help-notwin.result +++ b/mysql-test/r/mysqld--help-notwin.result @@ -3270,6 +3270,10 @@ The following options may be given as the first argument: mutex where instrumented. If disabled, the regular mutex is used. (Defaults to on; use --skip-use-mdl-mutex to disable.) + --use-status-mdl-mutex + Use thread pool friendly MDL lock instead of regular + mutex where instrumented for status variables. If + disabled, the regular mutex is used. -u, --user=name Run mysqld daemon as user. --validate-config Validate the server configuration specified by the user. --validate-schema-from-attributes @@ -4282,6 +4286,7 @@ update-table-create-timestamp-on-truncate FALSE upgrade AUTO use-fb-json-functions use-mdl-mutex TRUE +use-status-mdl-mutex FALSE validate-config FALSE validate-schema-from-attributes FALSE validate-user-plugins TRUE diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 9cc0f6f1ef0f..28e872e1cc66 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -273,6 +273,8 @@ update_binlog_pos_threshold update_table_create_timestamp_on_truncate update_table_create_timestamp_on_truncate use_secondary_engine +use_status_mdl_mutex +use_status_mdl_mutex wait_for_hlc_sleep_scaling_factor wait_for_hlc_sleep_scaling_factor wait_for_hlc_sleep_threshold_ms diff --git a/mysql-test/t/all_persisted_variables.test b/mysql-test/t/all_persisted_variables.test index d3531bde4d25..59e18f7de76f 100644 --- a/mysql-test/t/all_persisted_variables.test +++ b/mysql-test/t/all_persisted_variables.test @@ -77,6 +77,7 @@ let $total_excluded_vars=`SELECT COUNT(*) FROM performance_schema.global_variabl 'innodb_log_write_events', 'innodb_sync_pool_size', 'use_mdl_mutex', +'use_status_mdl_mutex', 'override_enable_raft_check', 'performance_schema_esms_by_thread_by_event_name', 'performance_schema_ews_by_thread_by_event_name', diff --git a/sql/binlog.cc b/sql/binlog.cc index bbe76fbab589..2d4f185dcb6a 100644 --- a/sql/binlog.cc +++ b/sql/binlog.cc @@ -13455,10 +13455,13 @@ bool show_raft_status(THD *thd) { std::vector> var_value_pairs; std::vector>::const_iterator itr; - mysql_mutex_lock(&LOCK_status); - int error = RUN_HOOK_STRICT(raft_replication, show_raft_status, - (current_thd, &var_value_pairs)); - mysql_mutex_unlock(&LOCK_status); + int error = 0; + { + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); + error = RUN_HOOK_STRICT(raft_replication, show_raft_status, + (current_thd, &var_value_pairs)); + } if (error) { errmsg = "Failure to run plugin hook"; goto err; diff --git a/sql/mdl.cc b/sql/mdl.cc index 85026eab13d6..600bfb072f47 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -5331,16 +5331,25 @@ void MDL_mutex::unlock(THD *thd, MDL_ticket *ticket) { Guard constructor locks the mutex. */ MDL_mutex_guard::MDL_mutex_guard(MDL_mutex *mdl_mutex, THD *thd, - mysql_mutex_t *mutex) - : m_mdl_mutex(mdl_mutex), m_thd(thd), m_mutex(mutex) { + mysql_mutex_t *mutex, + bool allow_caller_to_use_mdl_mutex, + bool allow_bypass) + : m_mdl_mutex(mdl_mutex), + m_thd(thd), + m_mutex(mutex), + m_allow_bypass(allow_bypass) { assert(m_mdl_mutex); // If regular mutex is not passed in then ignore use_mdl_mutex flag. - if (use_mdl_mutex || !m_mutex) { - assert(m_thd); - m_ticket = m_mdl_mutex->lock(m_thd); - } else { - mysql_mutex_lock(m_mutex); + if (!allow_bypass) { + bool enable_usage = use_mdl_mutex && allow_caller_to_use_mdl_mutex; + if (enable_usage || !m_mutex) { + assert(m_thd); + m_ticket = m_mdl_mutex->lock(m_thd); + } else { + assert(m_mutex); + mysql_mutex_lock(m_mutex); + } } } @@ -5352,7 +5361,7 @@ MDL_mutex_guard::~MDL_mutex_guard() { if (m_ticket) { assert(m_mdl_mutex); m_mdl_mutex->unlock(m_thd, m_ticket); - } else { + } else if (!m_allow_bypass) { assert(m_mutex); mysql_mutex_unlock(m_mutex); } diff --git a/sql/mdl.h b/sql/mdl.h index 90f15dc2e396..fdd4264df7b3 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -1863,7 +1863,9 @@ class MDL_mutex { */ class MDL_mutex_guard { public: - MDL_mutex_guard(MDL_mutex *mdl_mutex, THD *thd, mysql_mutex_t *mutex); + MDL_mutex_guard(MDL_mutex *mdl_mutex, THD *thd, mysql_mutex_t *mutex, + bool allow_caller_to_use_mdl_mutex = true, + bool allow_bypass = false); ~MDL_mutex_guard(); private: @@ -1878,6 +1880,9 @@ class MDL_mutex_guard { // Regular mutex to lock and unlock if MDL mutex is disabled. mysql_mutex_t *m_mutex{nullptr}; + + // Should the guard bypass the incoming request? + bool m_allow_bypass{false}; }; #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 84c9e6ecf32a..5c912f37265e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1692,6 +1692,7 @@ bool enable_optimizer_cputime_with_wallclock = true; bool enable_pfs_global_select = false; bool enable_rocksdb_intrinsic_tmp_table = false; bool use_mdl_mutex = true; +bool use_status_mdl_mutex = false; bool install_plugin_skip_registration = false; /** @@ -6331,6 +6332,7 @@ static int init_thread_environment() { // Init THD static objects. THD::init_mutex_thd_security_ctx(); + THD::init_mutex_thd_status_aggregation(); return 0; } @@ -13729,25 +13731,26 @@ class Reset_thd_status : public Do_THD_Impl { /** Reset global and session status variables. */ -void refresh_status() { - mysql_mutex_lock(&LOCK_status); +void refresh_status(THD *thd) { + { + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), thd, + &LOCK_status); - /* For all threads, add status to global status and then reset. */ - Reset_thd_status reset_thd_status; - Global_THD_manager::get_instance()->do_for_all_thd_copy(&reset_thd_status); + /* For all threads, add status to global status and then reset. */ + Reset_thd_status reset_thd_status; + Global_THD_manager::get_instance()->do_for_all_thd_copy(&reset_thd_status); #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE - /* Reset aggregated status counters. */ - reset_pfs_status_stats(); + /* Reset aggregated status counters. */ + reset_pfs_status_stats(); #endif - /* Reset some global variables. */ - reset_status_vars(); - - /* Reset the counters of all key caches (default and named). */ - process_key_caches(reset_key_cache_counters); - flush_status_time = time((time_t *)nullptr); - mysql_mutex_unlock(&LOCK_status); + /* Reset some global variables. */ + reset_status_vars(); + /* Reset the counters of all key caches (default and named). */ + process_key_caches(reset_key_cache_counters); + flush_status_time = time((time_t *)nullptr); + } /* Set max_used_connections to the number of currently open connections. Do this out of LOCK_status to avoid deadlocks. diff --git a/sql/mysqld.h b/sql/mysqld.h index 6cd1e496708b..7892fc5a6708 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -139,7 +139,7 @@ extern bool dynamic_plugins_are_initialized; bool signal_restart_server(); void kill_mysql(void); -void refresh_status(); +void refresh_status(THD *thd); void reset_status_by_thd(); bool is_secure_file_path(const char *path); ulong sql_rnd_with_mutex(); @@ -456,6 +456,7 @@ extern std::vector authentication_policy_list; extern bool opt_log_ddl; extern bool slave_high_priority_ddl; extern bool use_mdl_mutex; +extern bool use_status_mdl_mutex; extern bool install_plugin_skip_registration; extern ulonglong slave_high_priority_lock_wait_timeout_nsec; extern double slave_high_priority_lock_wait_timeout_double; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f56f04270a9a..eec2c27f6da9 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -138,6 +138,7 @@ using std::unique_ptr; // Static objects. MDL_mutex THD::mutex_thd_security_ctx[THD::mutex_thd_security_ctx_partitions]; +MDL_mutex THD::mutex_thd_status_aggregation; /* The following is used to initialise Table_ident with a internal @@ -913,6 +914,21 @@ MDL_mutex *THD::get_mutex_thd_security_ctx() { return &mutex_thd_security_ctx[partition]; } +/** + Initialize mutex_thd_status_aggregation. + */ +void THD::init_mutex_thd_status_aggregation() { + std::string thd_status_aggregation{"STATUS_AGGREGATION"}; + mutex_thd_status_aggregation.init(thd_status_aggregation); +} + +/** + Return mutex_thd_status_aggregation. + */ +MDL_mutex *THD::get_mutex_thd_status_aggregation() { + return &mutex_thd_status_aggregation; +} + void THD::copy_table_access_properties(THD *thd) { thread_stack = thd->thread_stack; variables.option_bits = thd->variables.option_bits & OPTION_BIN_LOG; @@ -1386,10 +1402,12 @@ void THD::cleanup_connection(void) { m_thd_life_cycle_stage = enum_thd_life_cycle_stages::ACTIVE; /* Aggregate to global status now that cleanup is done. */ - mysql_mutex_lock(&LOCK_status); - add_to_status(&global_status_var, &status_var); - reset_system_status_vars(&status_var); - mysql_mutex_unlock(&LOCK_status); + { + MDL_mutex_guard guard(get_mutex_thd_status_aggregation(), this, + &LOCK_status, use_status_mdl_mutex); + add_to_status(&global_status_var, &status_var); + reset_system_status_vars(&status_var); + } propagate_pending_global_disk_usage(); @@ -1673,19 +1691,21 @@ void THD::release_resources() { reset_connection_certificate(); - mysql_mutex_lock(&LOCK_status); - /* Add thread status to the global totals. */ - add_to_status(&global_status_var, &status_var); + { + MDL_mutex_guard guard(get_mutex_thd_status_aggregation(), this, + &LOCK_status, use_status_mdl_mutex); + /* Add thread status to the global totals. */ + add_to_status(&global_status_var, &status_var); #ifdef HAVE_PSI_THREAD_INTERFACE - /* Aggregate thread status into the Performance Schema. */ - if (m_psi != nullptr) { - PSI_THREAD_CALL(aggregate_thread_status)(m_psi); - } + /* Aggregate thread status into the Performance Schema. */ + if (m_psi != nullptr) { + PSI_THREAD_CALL(aggregate_thread_status)(m_psi); + } #endif /* HAVE_PSI_THREAD_INTERFACE */ - /* Ensure that the thread status is not re-aggregated to the global totals. */ - status_var_aggregated = true; - - mysql_mutex_unlock(&LOCK_status); + /* Ensure that the thread status is not re-aggregated to the global totals. + */ + status_var_aggregated = true; + } propagate_pending_global_disk_usage(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 176abee300ad..15fad76068be 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1258,10 +1258,15 @@ class THD : public MDL_context_owner, static constexpr int mutex_thd_security_ctx_partitions = 8; static MDL_mutex mutex_thd_security_ctx[mutex_thd_security_ctx_partitions]; + static MDL_mutex mutex_thd_status_aggregation; + public: static void init_mutex_thd_security_ctx(); MDL_mutex *get_mutex_thd_security_ctx(); + static void init_mutex_thd_status_aggregation(); + static MDL_mutex *get_mutex_thd_status_aggregation(); + /** Protects THD::db_read_only_hash. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bf246da5e891..d833389efb7b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2904,9 +2904,11 @@ bool dispatch_command(THD *thd, const COM_DATA *com_data, query_logger.general_log_print(thd, command, NullS); thd->status_var.com_stat[SQLCOM_SHOW_STATUS]++; - mysql_mutex_lock(&LOCK_status); - calc_sum_of_all_status(¤t_global_status_var); - mysql_mutex_unlock(&LOCK_status); + { + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), thd, + &LOCK_status, use_status_mdl_mutex); + calc_sum_of_all_status(¤t_global_status_var); + } if (!(uptime = (ulong)(thd->query_start_in_secs() - server_start_time))) queries_per_second1000 = 0; else diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 661bdfb0b112..72a548944083 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -344,7 +344,7 @@ bool handle_reload_request(THD *thd, unsigned long options, Table_ref *tables, } } if (options & REFRESH_HOSTS) hostname_cache_refresh(); - if (thd && (options & REFRESH_STATUS)) refresh_status(); + if (thd && (options & REFRESH_STATUS)) refresh_status(thd); if (options & REFRESH_THREADS) Per_thread_connection_handler::kill_blocked_pthreads(); if (options & REFRESH_MASTER) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index dcc3dbfcc5c1..f603b1bb85ab 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -900,11 +900,13 @@ bool Sql_cmd_show_status::execute(THD *thd) { thd->server_status &= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED); // Restore status variables, as we don't want 'show status' to cause changes - mysql_mutex_lock(&LOCK_status); - add_diff_to_status(&global_status_var, &thd->status_var, &old_status_var); - thd->status_var = old_status_var; - thd->initial_status_var = nullptr; - mysql_mutex_unlock(&LOCK_status); + { + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), thd, + &LOCK_status, use_status_mdl_mutex); + add_diff_to_status(&global_status_var, &thd->status_var, &old_status_var); + thd->status_var = old_status_var; + thd->initial_status_var = nullptr; + } return status; } @@ -4103,20 +4105,43 @@ static void shrink_var_array(Status_var_array *array) { The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF} */ bool add_status_vars(const SHOW_VAR *list) { - MUTEX_LOCK(lock, status_vars_inited ? &LOCK_status : nullptr); + bool skip_delete = true; + THD *thd = nullptr; - try { - while (list->name) all_status_vars.push_back(*list++); - } catch (const std::bad_alloc &) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), - static_cast(sizeof(Status_var_array::value_type))); - return true; + if (status_vars_inited) { + /** Do not enable plugins. */ + bool skip_creation = + !use_status_mdl_mutex || !Global_THD_manager::is_initialized(); + thd = current_thd || skip_creation ? current_thd : new THD(false); + if (!current_thd && thd) { + thd->thread_stack = (char *)&thd; + thd->store_globals(); + skip_delete = false; + } } - if (status_vars_inited) - std::sort(all_status_vars.begin(), all_status_vars.end(), Show_var_cmp()); + { + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), thd, + &LOCK_status, !skip_delete, !status_vars_inited); + + try { + while (list->name) all_status_vars.push_back(*list++); + } catch (const std::bad_alloc &) { + my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), + static_cast(sizeof(Status_var_array::value_type))); + return true; + } - status_var_array_version++; + if (status_vars_inited) + std::sort(all_status_vars.begin(), all_status_vars.end(), Show_var_cmp()); + + status_var_array_version++; + } + + if (!skip_delete) { + thd->restore_globals(); + delete thd; + } return false; } @@ -4258,7 +4283,9 @@ static bool get_recursive_status_var_inner(THD *thd, SHOW_VAR *list, bool get_recursive_status_var(THD *thd, const char *name, char *const value, enum_var_type var_type, size_t *length, const CHARSET_INFO **charset) { - MUTEX_LOCK(lock, status_vars_inited ? &LOCK_status : nullptr); + MDL_mutex_guard guard( + THD::get_mutex_thd_status_aggregation(), thd, &LOCK_status, + use_status_mdl_mutex && status_vars_inited, !status_vars_inited); for (SHOW_VAR var : all_status_vars) { if (get_recursive_status_var_inner(thd, &var, false, name, value, var_type, length, charset)) @@ -4282,8 +4309,22 @@ bool get_recursive_status_var(THD *thd, const char *name, char *const value, */ void remove_status_vars(SHOW_VAR *list) { + bool skip_delete = true; + THD *thd = nullptr; + if (status_vars_inited) { - mysql_mutex_lock(&LOCK_status); + /** Do not enable plugins. */ + bool skip_creation = + !use_status_mdl_mutex || !Global_THD_manager::is_initialized(); + thd = current_thd || skip_creation ? current_thd : new THD(false); + if (!current_thd && thd) { + thd->thread_stack = (char *)&thd; + thd->store_globals(); + skip_delete = false; + } + + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), thd, + &LOCK_status, !skip_delete); size_t a = 0, b = all_status_vars.size(), c = (a + b) / 2; for (; list->name; list++) { @@ -4301,7 +4342,6 @@ void remove_status_vars(SHOW_VAR *list) { } shrink_var_array(&all_status_vars); status_var_array_version++; - mysql_mutex_unlock(&LOCK_status); } else { uint i; for (; list->name; list++) { @@ -4314,6 +4354,11 @@ void remove_status_vars(SHOW_VAR *list) { shrink_var_array(&all_status_vars); status_var_array_version++; } + + if (!skip_delete) { + thd->restore_globals(); + delete thd; + } } /** @@ -4558,7 +4603,7 @@ class Add_status : public Do_THD_Impl { void calc_sum_of_all_status(System_status_var *to) { DBUG_TRACE; - mysql_mutex_assert_owner(&LOCK_status); + // mysql_mutex_assert_owner(&LOCK_status); /* Get global values as base. */ *to = global_status_var; Add_status add_status(to); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index acd2f3e247df..c30104326bda 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -10415,6 +10415,14 @@ static Sys_var_bool Sys_use_mdl_mutex( "instrumented. If disabled, the regular mutex is used.", READ_ONLY GLOBAL_VAR(use_mdl_mutex), CMD_LINE(OPT_ARG), DEFAULT(true)); +static Sys_var_bool Sys_use_status_mdl_mutex( + "use_status_mdl_mutex", + "Use thread pool friendly MDL lock instead of regular mutex where " + "instrumented for status variables. If disabled, the regular mutex is " + "used.", + READ_ONLY GLOBAL_VAR(use_status_mdl_mutex), CMD_LINE(OPT_ARG), + DEFAULT(false)); + static bool check_mta_binlog_statement_workers(sys_var * /*self*/, THD *thd, set_var *var) { uint prev_val = thd->variables.mta_binlog_statement_workers; diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc index 13359e9562da..d86aadb563cb 100644 --- a/storage/perfschema/pfs_variable.cc +++ b/storage/perfschema/pfs_variable.cc @@ -1193,15 +1193,11 @@ char *PFS_status_variable_cache::make_show_var_name(const char *prefix, */ bool PFS_status_variable_cache::do_initialize_session(void) { /* Acquire LOCK_status to guard against plugin load/unload. */ - if (m_current_thd->fill_status_recursion_level++ == 0) { - mysql_mutex_lock(&LOCK_status); - } - + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); bool ret = init_show_var_array(OPT_SESSION, true); - - if (m_current_thd->fill_status_recursion_level-- == 1) { - mysql_mutex_unlock(&LOCK_status); - } + m_current_thd->fill_status_recursion_level--; return ret; } @@ -1232,9 +1228,9 @@ int PFS_status_variable_cache::do_materialize_global(void) { DEBUG_SYNC(m_current_thd, "before_materialize_global_status_array"); /* Acquire LOCK_status to guard against plugin load/unload. */ - if (m_current_thd->fill_status_recursion_level++ == 0) { - mysql_mutex_lock(&LOCK_status); - } + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); /* Build array of SHOW_VARs from global status array. Do this within @@ -1263,9 +1259,7 @@ int PFS_status_variable_cache::do_materialize_global(void) { manifest(m_current_thd, m_show_var_array.begin(), &status_totals, "", false, true); - if (m_current_thd->fill_status_recursion_level-- == 1) { - mysql_mutex_unlock(&LOCK_status); - } + m_current_thd->fill_status_recursion_level--; m_materialized = true; DEBUG_SYNC(m_current_thd, "after_materialize_global_status_array"); @@ -1286,11 +1280,9 @@ int PFS_status_variable_cache::do_materialize_all(THD *unsafe_thd) { m_cache.clear(); /* Avoid recursive acquisition of LOCK_status. */ - std::unique_ptr status_lock_guard; - if (m_current_thd->fill_status_recursion_level++ == 0) { - status_lock_guard = std::unique_ptr( - new Mutex_lock(&LOCK_status, __FILE__, __LINE__)); - } + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); /* Build array of SHOW_VARs from global status array. Do this within @@ -1333,11 +1325,9 @@ int PFS_status_variable_cache::do_materialize_session(THD *unsafe_thd) { m_cache.clear(); /* Avoid recursive acquisition of LOCK_status. */ - std::unique_ptr status_lock_guard; - if (m_current_thd->fill_status_recursion_level++ == 0) { - status_lock_guard = std::unique_ptr( - new Mutex_lock(&LOCK_status, __FILE__, __LINE__)); - } + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); /* Build array of SHOW_VARs from global status array. Do this within @@ -1380,11 +1370,9 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) { m_cache.clear(); /* Acquire LOCK_status to guard against plugin load/unload. */ - std::unique_ptr status_lock_guard; - if (m_current_thd->fill_status_recursion_level++ == 0) { - status_lock_guard = std::unique_ptr( - new Mutex_lock(&LOCK_status, __FILE__, __LINE__)); - } + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1423,9 +1411,9 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) { m_cache.clear(); /* Acquire LOCK_status to guard against plugin load/unload. */ - if (m_current_thd->fill_status_recursion_level++ == 0) { - mysql_mutex_lock(&LOCK_status); - } + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex, + m_current_thd->fill_status_recursion_level++ != 0); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1443,9 +1431,7 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) { manifest(m_current_thd, m_show_var_array.begin(), &status_totals, "", false, true); - if (m_current_thd->fill_status_recursion_level-- == 1) { - mysql_mutex_unlock(&LOCK_status); - } + m_current_thd->fill_status_recursion_level--; m_materialized = true; return 0; diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc index da80e16b2c8d..9cb646114f41 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -1184,7 +1184,9 @@ PFS_connection_status_visitor::~PFS_connection_status_visitor() = default; /** Aggregate from global status. */ void PFS_connection_status_visitor::visit_global() { /* NOTE: Requires lock on LOCK_status. */ - mysql_mutex_assert_owner(&LOCK_status); + if (!use_mdl_mutex || !use_status_mdl_mutex) { + mysql_mutex_assert_owner(&LOCK_status); + } add_to_status(m_status_vars, &global_status_var); } diff --git a/storage/perfschema/table_global_status.cc b/storage/perfschema/table_global_status.cc index 49d649af1e78..b8cbfb1d8f4d 100644 --- a/storage/perfschema/table_global_status.cc +++ b/storage/perfschema/table_global_status.cc @@ -89,20 +89,20 @@ PFS_engine_table *table_global_status::create(PFS_engine_table_share *) { } int table_global_status::delete_all_rows(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); reset_status_by_thread(); reset_status_by_account(); reset_status_by_user(); reset_status_by_host(); reset_global_status(); - mysql_mutex_unlock(&LOCK_status); return 0; } ha_rows table_global_status::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); ha_rows status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return status_var_count; } diff --git a/storage/perfschema/table_session_status.cc b/storage/perfschema/table_session_status.cc index d3c45250b220..d12370235942 100644 --- a/storage/perfschema/table_session_status.cc +++ b/storage/perfschema/table_session_status.cc @@ -89,9 +89,9 @@ PFS_engine_table *table_session_status::create(PFS_engine_table_share *) { } ha_rows table_session_status::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); ha_rows status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return status_var_count; } diff --git a/storage/perfschema/table_status_by_account.cc b/storage/perfschema/table_status_by_account.cc index 2ea86f1392e9..df57ed3eb65c 100644 --- a/storage/perfschema/table_status_by_account.cc +++ b/storage/perfschema/table_status_by_account.cc @@ -106,17 +106,17 @@ PFS_engine_table *table_status_by_account::create(PFS_engine_table_share *) { } int table_status_by_account::delete_all_rows(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); reset_status_by_thread(); reset_status_by_account(); - mysql_mutex_unlock(&LOCK_status); return 0; } ha_rows table_status_by_account::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); size_t status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return (global_account_container.get_row_count() * status_var_count); } diff --git a/storage/perfschema/table_status_by_host.cc b/storage/perfschema/table_status_by_host.cc index 268263f5fae0..a376ccb12e0f 100644 --- a/storage/perfschema/table_status_by_host.cc +++ b/storage/perfschema/table_status_by_host.cc @@ -100,18 +100,18 @@ PFS_engine_table *table_status_by_host::create(PFS_engine_table_share *) { } int table_status_by_host::delete_all_rows(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); reset_status_by_thread(); reset_status_by_account(); reset_status_by_host(); - mysql_mutex_unlock(&LOCK_status); return 0; } ha_rows table_status_by_host::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); size_t status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return (global_host_container.get_row_count() * status_var_count); } diff --git a/storage/perfschema/table_status_by_thread.cc b/storage/perfschema/table_status_by_thread.cc index acba5db86f2f..2105533ba66b 100644 --- a/storage/perfschema/table_status_by_thread.cc +++ b/storage/perfschema/table_status_by_thread.cc @@ -101,18 +101,17 @@ PFS_engine_table *table_status_by_thread::create(PFS_engine_table_share *) { int table_status_by_thread::delete_all_rows(void) { /* Lock required to aggregate to global_status_var. */ - mysql_mutex_lock(&LOCK_status); - + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); reset_status_by_thread(); - mysql_mutex_unlock(&LOCK_status); return 0; } ha_rows table_status_by_thread::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); size_t status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return (global_thread_container.get_row_count() * status_var_count); } diff --git a/storage/perfschema/table_status_by_user.cc b/storage/perfschema/table_status_by_user.cc index 2435a0ade257..0ed867b2914b 100644 --- a/storage/perfschema/table_status_by_user.cc +++ b/storage/perfschema/table_status_by_user.cc @@ -101,18 +101,18 @@ PFS_engine_table *table_status_by_user::create(PFS_engine_table_share *) { } int table_status_by_user::delete_all_rows(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); reset_status_by_thread(); reset_status_by_account(); reset_status_by_user(); - mysql_mutex_unlock(&LOCK_status); return 0; } ha_rows table_status_by_user::get_row_count(void) { - mysql_mutex_lock(&LOCK_status); + MDL_mutex_guard guard(THD::get_mutex_thd_status_aggregation(), current_thd, + &LOCK_status, use_status_mdl_mutex); size_t status_var_count = all_status_vars.size(); - mysql_mutex_unlock(&LOCK_status); return (global_user_container.get_row_count() * status_var_count); }