diff --git a/mysql-test/suite/perfschema/r/bug91541.result b/mysql-test/suite/perfschema/r/bug91541.result new file mode 100644 index 00000000000..f0cbc850947 --- /dev/null +++ b/mysql-test/suite/perfschema/r/bug91541.result @@ -0,0 +1,28 @@ +# +# Test for bug bug91541 ("Flush status" statement adds twice to global values) +# +SET @saved_show_compatibility_56 = @@global.show_compatibility_56; +SET GLOBAL show_compatibility_56 = OFF; +# +# 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] +SET GLOBAL show_compatibility_56 = @saved_show_compatibility_56; diff --git a/mysql-test/suite/perfschema/t/bug91541.test b/mysql-test/suite/perfschema/t/bug91541.test new file mode 100644 index 00000000000..4048979b47e --- /dev/null +++ b/mysql-test/suite/perfschema/t/bug91541.test @@ -0,0 +1,67 @@ +--echo # +--echo # Test for bug bug91541 ("Flush status" statement adds twice to global values) +--echo # + +--source include/have_perfschema.inc + +SET @saved_show_compatibility_56 = @@global.show_compatibility_56; +SET GLOBAL show_compatibility_56 = OFF; + +--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 + +SET GLOBAL show_compatibility_56 = @saved_show_compatibility_56; diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc index e8d36f8fdb5..bb89e746e6e 100644 --- a/storage/perfschema/pfs_account.cc +++ b/storage/perfschema/pfs_account.cc @@ -541,7 +541,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; } @@ -561,7 +561,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 f7362892189..ec80a434bdb 100644 --- a/storage/perfschema/pfs_con_slice.h +++ b/storage/perfschema/pfs_con_slice.h @@ -235,9 +235,10 @@ private: public: - void aggregate_status_stats(const STATUS_VAR *status_vars) + void aggregate_status_stats(const STATUS_VAR *status_vars, + bool already_aggregated) { - m_status_stats.aggregate_from(status_vars); + m_status_stats.aggregate_from(status_vars, already_aggregated); } /** diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc index fd08b5c6cd8..f9c46328cde 100644 --- a/storage/perfschema/pfs_host.cc +++ b/storage/perfschema/pfs_host.cc @@ -278,7 +278,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 4d3cb4bb678..2952daea56e 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1725,18 +1725,21 @@ void aggregate_thread_status(PFS_thread *thread, if (likely(safe_account != NULL)) { - safe_account->aggregate_status_stats(&thd->status_var); + safe_account->aggregate_status_stats(&thd->status_var, + thd->status_var_aggregated); return; } if (safe_user != NULL) { - safe_user->aggregate_status_stats(&thd->status_var); + safe_user->aggregate_status_stats(&thd->status_var, + thd->status_var_aggregated); } if (safe_host != NULL) { - safe_host->aggregate_status_stats(&thd->status_var); + safe_host->aggregate_status_stats(&thd->status_var, + thd->status_var_aggregated); } return; } diff --git a/storage/perfschema/pfs_status.cc b/storage/perfschema/pfs_status.cc index 5d67bf2fa6f..9ddc6b98f0f 100644 --- a/storage/perfschema/pfs_status.cc +++ b/storage/perfschema/pfs_status.cc @@ -41,6 +41,8 @@ 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,24 +53,28 @@ void PFS_status_stats::aggregate(const PFS_status_stats *from) 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 STATUS_VAR *from) +void PFS_status_stats::aggregate_from(const 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(STATUS_VAR *to) +void PFS_status_stats::aggregate_to(STATUS_VAR *to, bool include_aggregated) { if (m_has_stats) { @@ -80,6 +86,16 @@ void PFS_status_stats::aggregate_to(STATUS_VAR *to) { *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 26b9974deda..7f8bf2528a7 100644 --- a/storage/perfschema/pfs_status.h +++ b/storage/perfschema/pfs_status.h @@ -27,11 +27,12 @@ struct PFS_status_stats void reset(); void aggregate(const PFS_status_stats *from); - void aggregate_from(const STATUS_VAR *from); - void aggregate_to(STATUS_VAR *to); + void aggregate_from(const STATUS_VAR *from, bool already_aggregated); + void aggregate_to(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 25ba1d9df1c..657eee3fdf8 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -1365,17 +1365,17 @@ 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 *pfs)