From 2a729b5f4b14f9f04cf81e1d8dd4eec4ad6cb7cd Mon Sep 17 00:00:00 2001 From: sjaakola Date: Wed, 17 Feb 2016 11:20:48 +0200 Subject: [PATCH] refs MW-245 - merged wsrep_dirty_reads and wsrep_reject_queries from PXC --- .../suite/galera/r/galera_defaults.result | 3 +- .../galera/r/galera_schema_dirty_reads.result | 13 ++++++ .../r/galera_var_cluster_address.result | 3 +- .../galera/r/galera_var_dirty_reads.result | 7 ++-- .../galera/t/galera_schema_dirty_reads.test | 13 ++++++ .../galera/t/galera_var_cluster_address.test | 1 - .../galera/t/galera_var_dirty_reads.test | 3 -- .../suite/sys_vars/r/sysvars_wsrep.result | 14 +++++++ sql/sql_class.h | 8 ++++ sql/sql_parse.cc | 41 +++++++++++++++---- sql/sys_vars.cc | 10 ++++- sql/wsrep_mysqld.h | 7 ++++ sql/wsrep_var.cc | 25 +++++++++++ sql/wsrep_var.h | 1 + 14 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_schema_dirty_reads.result create mode 100644 mysql-test/suite/galera/t/galera_schema_dirty_reads.test diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index d3004735a0a..5c5fdabf432 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -1,6 +1,6 @@ SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; COUNT(*) = 43 -1 +0 SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%' @@ -40,6 +40,7 @@ WSREP_NOTIFY_CMD WSREP_ON ON WSREP_OSU_METHOD TOI WSREP_RECOVER OFF +WSREP_REJECT_QUERIES NONE WSREP_REPLICATE_MYISAM OFF WSREP_RESTART_SLAVE OFF WSREP_RETRY_AUTOCOMMIT 1 diff --git a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result new file mode 100644 index 00000000000..edf20da92c6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result @@ -0,0 +1,13 @@ +USE information_schema; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF +SET GLOBAL wsrep_reject_queries=ALL; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF +SET GLOBAL wsrep_reject_queries=NONE; +SET SESSION wsrep_dirty_reads=TRUE; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS ON diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result index 7c56e22eca2..8245cdf6093 100644 --- a/mysql-test/suite/galera/r/galera_var_cluster_address.result +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -1,7 +1,8 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; -ERROR 08S01: WSREP has not yet prepared node for application use +COUNT(*) > 0 +1 SHOW STATUS LIKE 'wsrep_ready'; Variable_name Value wsrep_ready OFF diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index f141b332b6c..5a108ddfcaa 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -33,11 +33,12 @@ SELECT 1; 1 1 USE information_schema; -ERROR 08S01: WSREP has not yet prepared node for application use SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; -ERROR 08S01: WSREP has not yet prepared node for application use +VARIABLE_NAME VARIABLE_VALUE +WSREP_DIRTY_READS OFF SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history; -ERROR 08S01: WSREP has not yet prepared node for application use +COUNT(*) >= 10 +1 USE test; SELECT * FROM t1; i diff --git a/mysql-test/suite/galera/t/galera_schema_dirty_reads.test b/mysql-test/suite/galera/t/galera_schema_dirty_reads.test new file mode 100644 index 00000000000..93e24244611 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_schema_dirty_reads.test @@ -0,0 +1,13 @@ +# +# Dirty reads from INFORMATION_SCHEMA tables. +# +--source include/galera_cluster.inc +--source include/have_innodb.inc +--disable_info +USE information_schema; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +SET GLOBAL wsrep_reject_queries=ALL; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; +SET GLOBAL wsrep_reject_queries=NONE; +SET SESSION wsrep_dirty_reads=TRUE; +SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test index 03706bbbb12..6d99d35cdac 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_address.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -24,7 +24,6 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; ---error ER_UNKNOWN_COM_ERROR SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; # Must return 'OFF' diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index cba8488b879..138b7c1c703 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -49,13 +49,10 @@ SELECT i, variable_name, variable_value FROM t1, information_schema.session_vari SELECT 1; ---error ER_UNKNOWN_COM_ERROR USE information_schema; ---error ER_UNKNOWN_COM_ERROR SELECT * FROM information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads"; ---error ER_UNKNOWN_COM_ERROR SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history; --disable_query_log diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index 0c206975c29..db932ae8223 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -421,6 +421,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME WSREP_REJECT_QUERIES +SESSION_VALUE NULL +GLOBAL_VALUE NONE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NONE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Variable to set to reject queries +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NONE,ALL,ALL_KILL +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME WSREP_REPLICATE_MYISAM SESSION_VALUE NULL GLOBAL_VALUE OFF diff --git a/sql/sql_class.h b/sql/sql_class.h index 91030145022..b42b6ece9d4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5475,6 +5475,14 @@ public: sent by the user (ie: stored procedure). */ #define CF_SKIP_QUESTIONS (1U << 1) +#ifdef WITH_WSREP +/** + Do not check that wsrep snapshot is ready before allowing this command +*/ +#define CF_SKIP_WSREP_CHECK (1U << 2) +#else +#define CF_SKIP_WSREP_CHECK 0 +#endif /* WITH_WSREP */ /** Do not check that wsrep snapshot is ready before allowing this command diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 97d743d9a42..6a10f50813b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2017, MariaDB + Copyright (c) 2008, 2018, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -284,6 +284,8 @@ void init_update_queries(void) server_command_flags[COM_QUERY]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_SET_OPTION]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_PREPARE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; + server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_STMT_FETCH]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_CLOSE]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; @@ -887,6 +889,25 @@ void cleanup_items(Item *item) } +#ifdef WITH_WSREP +static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) +{ + for (const TABLE_LIST *table= tables; table; table= table->next_global) + { + TABLE_CATEGORY c; + LEX_STRING db, tn; + lex_string_set(&db, table->db); + lex_string_set(&tn, table->table_name); + c= get_table_category(&db, &tn); + if (c != TABLE_CATEGORY_INFORMATION && + c != TABLE_CATEGORY_PERFORMANCE) + { + return false; + } + } + return true; +} +#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY #ifdef WITH_WSREP @@ -2659,14 +2680,18 @@ mysql_execute_command(THD *thd) We additionally allow all other commands that do not change data in case wsrep_dirty_reads is enabled. */ - if (lex->sql_command != SQLCOM_SET_OPTION && - !wsrep_is_show_query(lex->sql_command) && - !(thd->variables.wsrep_dirty_reads && - !is_update_query(lex->sql_command)) && - !(lex->sql_command == SQLCOM_SELECT && - !all_tables) && - !wsrep_node_is_ready(thd)) + if (thd->variables.wsrep_on && !thd->wsrep_applier && + !(wsrep_ready || + (thd->variables.wsrep_dirty_reads && + (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) || + wsrep_tables_accessible_when_detached(all_tables)) && + lex->sql_command != SQLCOM_SET_OPTION && + !wsrep_is_show_query(lex->sql_command)) + { + my_message(ER_UNKNOWN_COM_ERROR, + "WSREP has not yet prepared node for application use", MYF(0)); goto error; + } } #endif /* WITH_WSREP */ status_var_increment(thd->status_var.com_stat[lex->sql_command]); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 303633939c3..2ec886f0528 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2002, 2015, Oracle and/or its affiliates. - Copyright (c) 2012, 2015, MariaDB + Copyright (c) 2012, 2018, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4967,6 +4967,14 @@ static Sys_var_mybool Sys_wsrep_desync ( ON_CHECK(wsrep_desync_check), ON_UPDATE(wsrep_desync_update)); +static const char *wsrep_reject_queries_names[]= { "NONE", "ALL", "ALL_KILL", NullS }; +static Sys_var_enum Sys_wsrep_reject_queries( + "wsrep_reject_queries", "Variable to set to reject queries", + GLOBAL_VAR(wsrep_reject_queries), CMD_LINE(OPT_ARG), + wsrep_reject_queries_names, DEFAULT(WSREP_REJECT_NONE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_reject_queries_update)); + static const char *wsrep_binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", "NONE", NullS}; static Sys_var_enum Sys_wsrep_forced_binlog_format( diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index fd68fab991c..33af697a19b 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -80,6 +80,7 @@ extern const char* wsrep_notify_cmd; extern long wsrep_max_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; +extern ulong wsrep_reject_queries; extern my_bool wsrep_replicate_myisam; extern ulong wsrep_mysql_replication_bundle; extern my_bool wsrep_restart_slave; @@ -92,6 +93,12 @@ extern bool wsrep_gtid_mode; extern uint32 wsrep_gtid_domain_id; extern bool wsrep_dirty_reads; +enum enum_wsrep_reject_types { + WSREP_REJECT_NONE, /* nothing rejected */ + WSREP_REJECT_ALL, /* reject all queries, with UNKNOWN_COMMAND error */ + WSREP_REJECT_ALL_KILL /* kill existing connections and reject all queries*/ +}; + enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU, diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index ad1f4ec0eac..da53c0981af 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -34,6 +34,7 @@ const char* wsrep_node_name = 0; const char* wsrep_node_address = 0; const char* wsrep_node_incoming_address = 0; const char* wsrep_start_position = 0; +ulong wsrep_reject_queries; static long wsrep_prev_slave_threads = wsrep_slave_threads; @@ -384,6 +385,30 @@ void wsrep_provider_options_init(const char* value) wsrep_provider_options = (value) ? my_strdup(value, MYF(0)) : NULL; } +bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type) +{ + switch (wsrep_reject_queries) { + case WSREP_REJECT_NONE: + wsrep_ready_set(TRUE); + WSREP_INFO("Allowing client queries due to manual setting"); + break; + case WSREP_REJECT_ALL: + wsrep_ready_set(FALSE); + WSREP_INFO("Rejecting client queries due to manual setting"); + break; + case WSREP_REJECT_ALL_KILL: + wsrep_ready_set(FALSE); + wsrep_close_client_connections(FALSE); + WSREP_INFO("Rejecting client queries and killing connections due to manual setting"); + break; + default: + WSREP_INFO("Unknown value for wsrep_reject_queries: %lu", + wsrep_reject_queries); + return true; + } + return false; +} + static int wsrep_cluster_address_verify (const char* cluster_address_str) { /* There is no predefined address format, it depends on provider. */ diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 55eb2fbc501..53952173c83 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -93,6 +93,7 @@ extern bool wsrep_desync_update UPDATE_ARGS; extern bool wsrep_max_ws_size_check CHECK_ARGS; extern bool wsrep_max_ws_size_update UPDATE_ARGS; +extern bool wsrep_reject_queries_update UPDATE_ARGS; #else /* WITH_WSREP */