From 9293d40fa79c5f2aabef63e0258e42c35e69c190 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 19 May 2024 16:52:23 +0200 Subject: [PATCH] MDEV-33145 support for old-mode=OLD_FLUSH_STATUS add old-mode that restores inconsistent legacy behavior for FLUSH STATUS. It doesn't affect FLUSH { SESSION | GLOBAL } STATUS. --- include/mysql_com.h | 4 +- mysql-test/main/mysqld--help.result | 4 +- mysql-test/main/status.result | 25 ++++++++++ mysql-test/main/status.test | 28 +++++++++++ .../suite/sys_vars/r/old_mode_basic.result | 4 +- .../sys_vars/r/sysvars_server_embedded.result | 2 +- .../r/sysvars_server_notembedded.result | 2 +- .../suite/sys_vars/t/old_mode_basic.test | 2 +- sql/mysqld.cc | 46 +++++++++++++++++++ sql/mysqld.h | 1 + sql/sql_class.h | 1 + sql/sql_parse.cc | 4 ++ sql/sql_reload.cc | 2 + sql/sql_yacc.yy | 7 ++- sql/sys_vars.cc | 4 ++ 15 files changed, 126 insertions(+), 10 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index d36b1a9e1d08c..b9fae54e7f476 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -194,8 +194,7 @@ enum enum_indicator_type #define REFRESH_LOG (1ULL << 1) /* Start on new log file */ #define REFRESH_TABLES (1ULL << 2) /* close all tables */ #define REFRESH_HOSTS (1ULL << 3) /* Flush host cache */ -#define REFRESH_SESSION_STATUS (1ULL << 4) /* Flush status variables */ -#define REFRESH_STATUS REFRESH_SESSION_STATUS +#define REFRESH_STATUS (1ULL << 4) /* Flush status variables */ #define REFRESH_THREADS (1ULL << 5) /* Flush thread cache */ #define REFRESH_SLAVE (1ULL << 6) /* Reset master info and restart slave thread */ @@ -220,6 +219,7 @@ enum enum_indicator_type #define REFRESH_FOR_EXPORT (1ULL << 20) /* FLUSH TABLES ... FOR EXPORT */ #define REFRESH_SSL (1ULL << 21) #define REFRESH_GLOBAL_STATUS (1ULL << 22) /* Flush global status */ +#define REFRESH_SESSION_STATUS (1ULL << 23) /* Flush session status */ #define REFRESH_GENERIC (1ULL << 30) #define REFRESH_FAST (1ULL << 31) /* Intern flag */ diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 8a5068aa57dc9..1546735b8fedb 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -739,8 +739,8 @@ The following specify which files/extra groups are read (specified before remain NO_DUP_KEY_WARNINGS_WITH_IGNORE, NO_PROGRESS_INFO, ZERO_DATE_TIME_CAST, UTF8_IS_UTF8MB3, IGNORE_INDEX_ONLY_FOR_JOIN, COMPAT_5_1_CHECKSUM, - NO_NULL_COLLATION_IDS, LOCK_ALTER_TABLE_COPY, or ALL to - set all combinations + NO_NULL_COLLATION_IDS, LOCK_ALTER_TABLE_COPY, + OLD_FLUSH_STATUS, or ALL to set all combinations --old-passwords Use old password encryption method (needed for 4.0 and older clients) --old-style-user-limits diff --git a/mysql-test/main/status.result b/mysql-test/main/status.result index 290c74a355d6a..ebee9e3c79f4f 100644 --- a/mysql-test/main/status.result +++ b/mysql-test/main/status.result @@ -488,4 +488,29 @@ select $new_local_flush_status >= $local_flush_status as "1"; select $new_global_flush_status < $new_local_flush_status as "1"; 1 1 +create or replace table t1 (a int, key(a)) engine=MyISAM; +insert into t1 values (1),(2); +connect con1,localhost,root; +set old_mode=OLD_FLUSH_STATUS; +Warnings: +Warning 1287 'OLD_FLUSH_STATUS' is deprecated and will be removed in a future release +insert into t1 values (3),(4); +drop table t1; +select t1.variable_name, t1.variable_value as global_value, t2.variable_value as session_value +from information_schema.global_status t1 join information_schema.session_status t2 +on t1.variable_name = t2.variable_name +where t1.variable_name in ('Key_writes','Com_insert'); +variable_name global_value session_value +COM_INSERT 2 1 +KEY_WRITES 2 2 +flush status; +select t1.variable_name, t1.variable_value as global_value, t2.variable_value as session_value +from information_schema.global_status t1 join information_schema.session_status t2 +on t1.variable_name = t2.variable_name +where t1.variable_name in ('Key_writes','Com_insert'); +variable_name global_value session_value +COM_INSERT 2 0 +KEY_WRITES 0 0 +disconnect con1; +connection default; # end of 11.5 tests diff --git a/mysql-test/main/status.test b/mysql-test/main/status.test index c9c1f97560c3d..a1cc028b98a39 100644 --- a/mysql-test/main/status.test +++ b/mysql-test/main/status.test @@ -506,4 +506,32 @@ let $new_local_flush_status= `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESS --evalp select $new_local_flush_status >= $local_flush_status as "1" --evalp select $new_global_flush_status < $new_local_flush_status as "1" +# +# Test OLD_FLUSH_STATUS +# + +create or replace table t1 (a int, key(a)) engine=MyISAM; +insert into t1 values (1),(2); + +--connect con1,localhost,root +set old_mode=OLD_FLUSH_STATUS; + +insert into t1 values (3),(4); +drop table t1; + +select t1.variable_name, t1.variable_value as global_value, t2.variable_value as session_value +from information_schema.global_status t1 join information_schema.session_status t2 + on t1.variable_name = t2.variable_name +where t1.variable_name in ('Key_writes','Com_insert'); + +flush status; + +select t1.variable_name, t1.variable_value as global_value, t2.variable_value as session_value +from information_schema.global_status t1 join information_schema.session_status t2 + on t1.variable_name = t2.variable_name +where t1.variable_name in ('Key_writes','Com_insert'); + +disconnect con1; +connection default; + --echo # end of 11.5 tests diff --git a/mysql-test/suite/sys_vars/r/old_mode_basic.result b/mysql-test/suite/sys_vars/r/old_mode_basic.result index 3032a82581b32..d8f6cf9600c08 100644 --- a/mysql-test/suite/sys_vars/r/old_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/old_mode_basic.result @@ -132,8 +132,8 @@ Warning 1287 'ZERO_DATE_TIME_CAST' is deprecated and will be removed in a future SELECT @@global.old_mode; @@global.old_mode ZERO_DATE_TIME_CAST -SET @@global.old_mode = 256; -ERROR 42000: Variable 'old_mode' can't be set to the value of '256' +SET @@global.old_mode = 6536; +ERROR 42000: Variable 'old_mode' can't be set to the value of '6536' SELECT @@global.old_mode; @@global.old_mode ZERO_DATE_TIME_CAST diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 86cc1fd8f0ca4..42990ead42f00 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2329,7 +2329,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,LOCK_ALTER_TABLE_COPY +ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,LOCK_ALTER_TABLE_COPY,OLD_FLUSH_STATUS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD_PASSWORDS diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 8d1b615b56708..fd6c13b94ec70 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2539,7 +2539,7 @@ VARIABLE_COMMENT Used to emulate old behavior from earlier MariaDB or MySQL vers NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,LOCK_ALTER_TABLE_COPY +ENUM_VALUE_LIST NO_DUP_KEY_WARNINGS_WITH_IGNORE,NO_PROGRESS_INFO,ZERO_DATE_TIME_CAST,UTF8_IS_UTF8MB3,IGNORE_INDEX_ONLY_FOR_JOIN,COMPAT_5_1_CHECKSUM,NO_NULL_COLLATION_IDS,LOCK_ALTER_TABLE_COPY,OLD_FLUSH_STATUS READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OLD_PASSWORDS diff --git a/mysql-test/suite/sys_vars/t/old_mode_basic.test b/mysql-test/suite/sys_vars/t/old_mode_basic.test index c3fc4c5718945..89aca99271a12 100644 --- a/mysql-test/suite/sys_vars/t/old_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/old_mode_basic.test @@ -172,7 +172,7 @@ SET @@global.old_mode = 4; SELECT @@global.old_mode; --Error ER_WRONG_VALUE_FOR_VAR -SET @@global.old_mode = 256; +SET @@global.old_mode = 6536; SELECT @@global.old_mode; # use of decimal values diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d93ef06f39815..5e65da0f41f35 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9227,6 +9227,52 @@ void refresh_global_status() max_used_connections_time= time(nullptr); } +/** Emulate the legacy FLUSH STATUS inconsistent behavior + + * additive session variables are added to global and set to 0 in session + * non-additive global variables are set to 0 +*/ +void refresh_status_legacy(THD *thd) +{ + mysql_mutex_lock(&LOCK_status); + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + /* Reset aggregated status counters. */ + reset_pfs_status_stats(); +#endif + + /* Add thread's status variabes to global status */ + add_to_status(&global_status_var, &thd->status_var); + + /* Reset thread's status variables */ + thd->set_status_var_init(); + thd->status_var.global_memory_used= 0; + bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); + thd->start_bytes_received= 0; + + /* Reset some global variables */ + reset_status_vars(); +#ifdef WITH_WSREP + if (WSREP_ON) + { + Wsrep_server_state::instance().provider().reset_status(); + } +#endif /* WITH_WSREP */ + + /* Reset the counters of all key caches (default and named). */ + process_key_caches(reset_key_cache_counters, 0); + global_status_var.flush_status_time= my_time(0); + mysql_mutex_unlock(&LOCK_status); + + /* + Set max_used_connections to the number of currently open + connections. This is not perfect, but status data is not exact anyway. + */ + max_used_connections= connection_count + extra_connection_count; + max_used_connections_time= time(nullptr); +} + + #ifdef HAVE_PSI_INTERFACE static PSI_file_info all_server_files[]= diff --git a/sql/mysqld.h b/sql/mysqld.h index f9de1c2f6f03d..07505d123c052 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -80,6 +80,7 @@ void close_connection(THD *thd, uint sql_errno= 0); void handle_connection_in_main_thread(CONNECT *thd); void create_thread_to_handle_connection(CONNECT *connect); void unlink_thd(THD *thd); +void refresh_status_legacy(THD *thd); void refresh_session_status(THD *thd); void refresh_global_status(); bool is_secure_file_path(char *path); diff --git a/sql/sql_class.h b/sql/sql_class.h index a46c6d45ca19c..372ec82017b63 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -207,6 +207,7 @@ enum enum_binlog_row_image { #define OLD_MODE_COMPAT_5_1_CHECKSUM (1 << 5) #define OLD_MODE_NO_NULL_COLLATION_IDS (1 << 6) #define OLD_MODE_LOCK_ALTER_TABLE_COPY (1 << 7) +#define OLD_MODE_OLD_FLUSH_STATUS (1 << 8) #define OLD_MODE_DEFAULT_VALUE OLD_MODE_UTF8_IS_UTF8MB3 diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 47dc3ad500173..b94397b1407d4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2183,6 +2183,9 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * if (trans_commit_implicit(thd)) break; thd->release_transactional_locks(); + if (options & REFRESH_STATUS && + !(thd->variables.old_behavior & OLD_MODE_OLD_FLUSH_STATUS)) + options= (options & ~REFRESH_STATUS) | REFRESH_SESSION_STATUS; if ((options & ~REFRESH_SESSION_STATUS) && check_global_access(thd,RELOAD_ACL)) break; @@ -5277,6 +5280,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) #ifdef HAVE_QUERY_CACHE REFRESH_QUERY_CACHE_FREE | #endif /* HAVE_QUERY_CACHE */ + REFRESH_STATUS | REFRESH_SESSION_STATUS | REFRESH_GLOBAL_STATUS | REFRESH_USER_RESOURCES)) diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 1caeac8612280..da4b6743eefd7 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -379,6 +379,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, #endif if (options & REFRESH_HOSTS) hostname_cache_refresh(); + if (thd && (options & REFRESH_STATUS)) + refresh_status_legacy(thd); if (thd && (options & REFRESH_SESSION_STATUS)) refresh_session_status(thd); if ((options & REFRESH_GLOBAL_STATUS)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bbdd4eafb4d5e..39eba50458820 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -14673,7 +14673,12 @@ flush_option: Lex->relay_log_connection_name= empty_clex_str; } | STATUS_SYM - { Lex->type|= REFRESH_SESSION_STATUS; } + { + if (thd->variables.old_behavior & OLD_MODE_OLD_FLUSH_STATUS) + Lex->type|= REFRESH_STATUS; + else + Lex->type|= REFRESH_SESSION_STATUS; + } | SESSION_SYM STATUS_SYM { Lex->type|= REFRESH_SESSION_STATUS; } | GLOBAL_SYM STATUS_SYM diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 55f11167fd429..6ecb0a70a5896 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3955,6 +3955,7 @@ static const char *old_mode_names[]= "COMPAT_5_1_CHECKSUM", // 5: deprecated since 11.3 "NO_NULL_COLLATION_IDS", // 6: deprecated since 11.3 "LOCK_ALTER_TABLE_COPY", // 7: deprecated since 11.3 + "OLD_FLUSH_STATUS", // 8: deprecated since 11.5 0 }; @@ -3974,6 +3975,9 @@ static bool old_mode_deprecated(sys_var *self, THD *thd, set_var *var) for (; i <= 7; i++) if ((1ULL<(thd, old_mode_names[i]); + for (; i <= 8; i++) + if ((1ULL<(thd, old_mode_names[i]); return false; }