diff --git a/mysql-test/suite/perfschema/r/bug91541.result b/mysql-test/suite/perfschema/r/bug91541.result new file mode 100644 index 00000000000..6f3bb3f675c --- /dev/null +++ b/mysql-test/suite/perfschema/r/bug91541.result @@ -0,0 +1,25 @@ +# +# Test for bug bug91541 ("Flush status" statement adds twice to global values) +# +# +# default connection +# +# +# first connection +# +include/assert.inc [Global value requested from the first session must not change] +SET long_query_time = 2; +SELECT SLEEP(3); +SLEEP(3) +0 +SET long_query_time = @@global.long_query_time; +include/assert.inc [Global value requested from the first session after SLEEP() must inccrease by 1] +include/assert.inc [First session value must increase by 1] +# +# default connection +# +include/assert.inc [Global value requested from the default session after DISCONNECT must remain the same] +include/assert.inc [Default session value must remain zero] +FLUSH STATUS; +include/assert.inc [Global value requested from the default session after FLUSH must remain the same] +include/assert.inc [Default session value after FLUSH must remain zero] diff --git a/mysql-test/suite/perfschema/t/bug91541.test b/mysql-test/suite/perfschema/t/bug91541.test new file mode 100644 index 00000000000..d191d0c5351 --- /dev/null +++ b/mysql-test/suite/perfschema/t/bug91541.test @@ -0,0 +1,60 @@ +--echo # +--echo # Test for bug bug91541 ("Flush status" statement adds twice to global values) +--echo # + +--echo # +--echo # default connection +--echo # +--let $initial_global_value = query_get_value(SHOW GLOBAL STATUS LIKE 'Slow_queries', Value, 1) + +--source include/count_sessions.inc + +--echo # +--echo # first connection +--echo # +--connect (con1,localhost,root,,) +--let $current_global_value = query_get_value(SHOW GLOBAL STATUS LIKE 'Slow_queries', Value, 1) +--let $assert_cond = $current_global_value - $initial_global_value = 0 +--let $assert_text = Global value requested from the first session must not change +--source include/assert.inc + +SET long_query_time = 2; +SELECT SLEEP(3); +SET long_query_time = @@global.long_query_time; + +--let $current_global_value = query_get_value(SHOW GLOBAL STATUS LIKE 'Slow_queries', Value, 1) +--let $first_session_value = query_get_value(SHOW SESSION STATUS LIKE 'Slow_queries', Value, 1) +--let $assert_cond = $current_global_value - $initial_global_value = 1 +--let $assert_text = Global value requested from the first session after SLEEP() must inccrease by 1 +--source include/assert.inc +--let $assert_cond = $first_session_value = 1 +--let $assert_text = First session value must increase by 1 +--source include/assert.inc + +--connection default +--disconnect con1 +--source include/wait_until_count_sessions.inc + +--echo # +--echo # default connection +--echo # +--connection default +--let $current_global_value = query_get_value(SHOW GLOBAL STATUS LIKE 'Slow_queries', Value, 1) +--let $default_session_value = query_get_value(SHOW SESSION STATUS LIKE 'Slow_queries', Value, 1) +--let $assert_cond = $current_global_value - $initial_global_value = 1 +--let $assert_text = Global value requested from the default session after DISCONNECT must remain the same +--source include/assert.inc +--let $assert_cond = $default_session_value = 0 +--let $assert_text = Default session value must remain zero +--source include/assert.inc + +FLUSH STATUS; + +--let $current_global_value = query_get_value(SHOW GLOBAL STATUS LIKE 'Slow_queries', Value, 1) +--let $default_session_value = query_get_value(SHOW SESSION STATUS LIKE 'Slow_queries', Value, 1) +--let $assert_cond = $current_global_value - $initial_global_value = 1 +--let $assert_text = Global value requested from the default session after FLUSH must remain the same +--source include/assert.inc +--let $assert_cond = $default_session_value = 0 +--let $assert_text = Default session value after FLUSH must remain zero +--source include/assert.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 474a17a230b..69da2f8c48f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1366,6 +1366,10 @@ struct System_status_var *get_thd_status_var(THD *thd) { return &thd->status_var; } +bool is_thd_status_var_aggregated(const THD *thd) { + return thd->status_var_aggregated; +} + static void option_error_reporter(enum loglevel level, const char *format, ...) MY_ATTRIBUTE((format(printf, 2, 3))); diff --git a/sql/mysqld.h b/sql/mysqld.h index db246888a28..61552739c1d 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -121,6 +121,7 @@ bool is_secure_file_path(const char *path); ulong sql_rnd_with_mutex(); struct System_status_var *get_thd_status_var(THD *thd); +bool is_thd_status_var_aggregated(const THD *thd); // These are needed for unit testing. void set_remaining_args(int argc, char **argv); diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc index 3f4f8e36820..b72fe397a62 100644 --- a/storage/perfschema/pfs_account.cc +++ b/storage/perfschema/pfs_account.cc @@ -557,7 +557,7 @@ void PFS_account::aggregate_status(PFS_user *safe_user, PFS_host *safe_host) { - GLOBAL_STATUS */ safe_user->m_status_stats.aggregate(&m_status_stats); - m_status_stats.aggregate_to(&global_status_var); + m_status_stats.aggregate_to(&global_status_var, false); m_status_stats.reset(); return; } @@ -576,7 +576,7 @@ void PFS_account::aggregate_status(PFS_user *safe_user, PFS_host *safe_host) { Aggregate STATUS_BY_ACCOUNT to: - GLOBAL_STATUS */ - m_status_stats.aggregate_to(&global_status_var); + m_status_stats.aggregate_to(&global_status_var, false); m_status_stats.reset(); return; } diff --git a/storage/perfschema/pfs_con_slice.h b/storage/perfschema/pfs_con_slice.h index 5192f065aca..d70476b0c94 100644 --- a/storage/perfschema/pfs_con_slice.h +++ b/storage/perfschema/pfs_con_slice.h @@ -226,8 +226,9 @@ struct PFS_connection_slice { PFS_error_stat *m_instr_class_errors_stats; public: - void aggregate_status_stats(const System_status_var *status_vars) { - m_status_stats.aggregate_from(status_vars); + void aggregate_status_stats(const System_status_var *status_vars, + bool already_aggregated) { + m_status_stats.aggregate_from(status_vars, already_aggregated); } /** diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc index 415e0d56e23..372e9bd17ef 100644 --- a/storage/perfschema/pfs_host.cc +++ b/storage/perfschema/pfs_host.cc @@ -275,7 +275,7 @@ void PFS_host::aggregate_status() { Aggregate STATUS_BY_HOST to: - GLOBAL_STATUS */ - m_status_stats.aggregate_to(&global_status_var); + m_status_stats.aggregate_to(&global_status_var, false); m_status_stats.reset(); } diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index e1b12bba79a..3ae2f9b4a26 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1688,16 +1688,19 @@ void aggregate_thread_status(PFS_thread *thread, PFS_account *safe_account, System_status_var *status_var = get_thd_status_var(thd); if (likely(safe_account != NULL)) { - safe_account->aggregate_status_stats(status_var); + safe_account->aggregate_status_stats(status_var, + is_thd_status_var_aggregated(thd)); return; } if (safe_user != NULL) { - safe_user->aggregate_status_stats(status_var); + safe_user->aggregate_status_stats(status_var, + is_thd_status_var_aggregated(thd)); } if (safe_host != NULL) { - safe_host->aggregate_status_stats(status_var); + safe_host->aggregate_status_stats(status_var, + is_thd_status_var_aggregated(thd)); } return; diff --git a/storage/perfschema/pfs_status.cc b/storage/perfschema/pfs_status.cc index 707758a59ac..9817a7178b6 100644 --- a/storage/perfschema/pfs_status.cc +++ b/storage/perfschema/pfs_status.cc @@ -44,6 +44,8 @@ PFS_status_stats::PFS_status_stats() { reset(); } void PFS_status_stats::reset() { m_has_stats = false; memset(&m_stats, 0, sizeof(m_stats)); + memset(&m_stats_aggregated_in_global, 0, + sizeof(m_stats_aggregated_in_global)); } void PFS_status_stats::aggregate(const PFS_status_stats *from) { @@ -51,26 +53,39 @@ void PFS_status_stats::aggregate(const PFS_status_stats *from) { m_has_stats = true; for (int i = 0; i < COUNT_GLOBAL_STATUS_VARS; i++) { m_stats[i] += from->m_stats[i]; + m_stats_aggregated_in_global[i]+= from->m_stats_aggregated_in_global[i]; } } } -void PFS_status_stats::aggregate_from(const System_status_var *from) { +void PFS_status_stats::aggregate_from(const System_status_var *from, + bool already_aggregated) { ulonglong *from_var = (ulonglong *)from; + ulonglong *to_var = + already_aggregated ? m_stats_aggregated_in_global : m_stats; + m_has_stats = true; for (int i = 0; i < COUNT_GLOBAL_STATUS_VARS; i++, from_var++) { - m_stats[i] += *from_var; + to_var[i] += *from_var; } } -void PFS_status_stats::aggregate_to(System_status_var *to) { +void PFS_status_stats::aggregate_to(System_status_var *to, + bool include_aggregated) { if (m_has_stats) { ulonglong *to_var = (ulonglong *)to; for (int i = 0; i < COUNT_GLOBAL_STATUS_VARS; i++, to_var++) { *to_var += m_stats[i]; } + if (include_aggregated) + { + to_var= (ulonglong *)to; + for (int i= 0; i < COUNT_GLOBAL_STATUS_VARS;i++, to_var++) { + *to_var += m_stats_aggregated_in_global[i]; + } + } } } diff --git a/storage/perfschema/pfs_status.h b/storage/perfschema/pfs_status.h index ecafdeb9d9a..4655b24bc36 100644 --- a/storage/perfschema/pfs_status.h +++ b/storage/perfschema/pfs_status.h @@ -36,11 +36,12 @@ struct PFS_status_stats { void reset(); void aggregate(const PFS_status_stats *from); - void aggregate_from(const System_status_var *from); - void aggregate_to(System_status_var *to); + void aggregate_from(const System_status_var *from, bool already_aggregated); + void aggregate_to(System_status_var *to, bool include_aggregated); bool m_has_stats; ulonglong m_stats[COUNT_GLOBAL_STATUS_VARS]; + ulonglong m_stats_aggregated_in_global[COUNT_GLOBAL_STATUS_VARS]; }; void reset_status_by_thread(); diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc index f5b3f18a314..dd78a793961 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -1146,15 +1146,15 @@ void PFS_connection_status_visitor::visit_global() { } void PFS_connection_status_visitor::visit_host(PFS_host *pfs) { - pfs->m_status_stats.aggregate_to(m_status_vars); + pfs->m_status_stats.aggregate_to(m_status_vars, true); } void PFS_connection_status_visitor::visit_user(PFS_user *pfs) { - pfs->m_status_stats.aggregate_to(m_status_vars); + pfs->m_status_stats.aggregate_to(m_status_vars, true); } void PFS_connection_status_visitor::visit_account(PFS_account *pfs) { - pfs->m_status_stats.aggregate_to(m_status_vars); + pfs->m_status_stats.aggregate_to(m_status_vars, true); } void PFS_connection_status_visitor::visit_thread(PFS_thread *) {} diff --git a/storage/perfschema/unittest/pfs_server_stubs.cc b/storage/perfschema/unittest/pfs_server_stubs.cc index a6eff716c4e..6e5da4e1c3b 100644 --- a/storage/perfschema/unittest/pfs_server_stubs.cc +++ b/storage/perfschema/unittest/pfs_server_stubs.cc @@ -51,6 +51,10 @@ struct System_status_var *get_thd_status_var(THD *) { return NULL; } +bool is_thd_status_var_aggregated(const THD *) { + return false; +} + unsigned int mysql_errno_to_sqlstate_index(unsigned int) { return 0; } SERVICE_TYPE(registry) * mysql_plugin_registry_acquire() { return NULL; }