diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result new file mode 100644 index 00000000000..6d703c8cf95 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -0,0 +1,25 @@ +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +i +1 +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_ready'; +Variable_name Value +wsrep_ready OFF +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SELECT * FROM t1; +ERROR 08S01: WSREP has not yet prepared node for application use +SET @@session.wsrep_dirty_reads=ON; +SELECT * FROM t1; +i +1 +SELECT * FROM t1; +i +1 +DROP TABLE t1; +# End of test diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index e21207b659a..7642b937e05 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -34,6 +34,7 @@ push @::global_suppressions, qr(WSREP: Failed to send state UUID:), qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), + qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), ); diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test new file mode 100644 index 00000000000..855f4abdbf0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -0,0 +1,46 @@ +# +# Check the handling of @@wsrep_dirty_reads +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_2 +--let $wsrep_cluster_address_saved = `SELECT @@global.wsrep_cluster_address` + +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; + +SET @@global.wsrep_cluster_address = ''; +SET @@session.wsrep_dirty_reads=OFF; + +# Set wsrep_sync_wait to avoid ER_LOCK_WAIT_TIMEOUT (MDEV-6832). +SET SESSION wsrep_sync_wait=0; + +# Must return 'OFF' +SHOW STATUS LIKE 'wsrep_ready'; + +# Must return 'Non-primary' +SHOW STATUS LIKE 'wsrep_cluster_status'; + +--error ER_UNKNOWN_COM_ERROR +SELECT * FROM t1; + +SET @@session.wsrep_dirty_reads=ON; + +SELECT * FROM t1; + +--disable_query_log +--eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' +--enable_query_log +--source include/wait_until_connected_again.inc + +--connection node_1 +SELECT * FROM t1; +# Cleanup +DROP TABLE t1; + +--source include/galera_end.inc +--echo # End of test + diff --git a/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result new file mode 100644 index 00000000000..d2a62d6136f --- /dev/null +++ b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result @@ -0,0 +1,35 @@ +# +# wsrep_dirty_reads +# +# save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; +# default +SELECT @@global.wsrep_dirty_reads; +ERROR HY000: Variable 'wsrep_dirty_reads' is a SESSION variable +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +1 +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +0 + +# invalid values +SET @@session.wsrep_dirty_reads=NULL; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'NULL' +SET @@session.wsrep_dirty_reads='junk'; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'junk' + +# restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; +# End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test new file mode 100644 index 00000000000..a47524fcfe3 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test @@ -0,0 +1,35 @@ +--source include/have_wsrep.inc + +--echo # +--echo # wsrep_dirty_reads +--echo # + +--echo # save the initial value +SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; + +--echo # default +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@global.wsrep_dirty_reads; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # scope and valid values +SET @@session.wsrep_dirty_reads=OFF; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=ON; +SELECT @@session.wsrep_dirty_reads; +SET @@session.wsrep_dirty_reads=default; +SELECT @@session.wsrep_dirty_reads; + +--echo +--echo # invalid values +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@session.wsrep_dirty_reads='junk'; + +--echo +--echo # restore the initial values +SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; + +--echo # End of test diff --git a/sql/sql_class.h b/sql/sql_class.h index 5ab03388f01..9dbf85f2dca 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -654,6 +654,7 @@ typedef struct system_variables #ifdef WITH_WSREP my_bool wsrep_on; my_bool wsrep_causal_reads; + my_bool wsrep_dirty_reads; uint wsrep_sync_wait; ulong wsrep_retry_autocommit; #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 87810a65b0f..730adfe94ed 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2615,11 +2615,13 @@ mysql_execute_command(THD *thd) } /* - * bail out if DB snapshot has not been installed. We however, - * allow SET and SHOW queries - */ + Bail out if DB snapshot has not been installed. We however, + allow SET and SHOW queries. + */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && + !(thd->variables.wsrep_dirty_reads && + lex->sql_command == SQLCOM_SELECT) && !wsrep_is_show_query(lex->sql_command)) { #if DIRTY_HACK diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index f2592a3fd58..fe7e0135fe1 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4743,6 +4743,12 @@ static Sys_var_mybool Sys_wsrep_slave_UK_checks( static Sys_var_mybool Sys_wsrep_restart_slave( "wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_dirty_reads( + "wsrep_dirty_reads", "Do not reject SELECT queries even when the node " + "is not ready.", SESSION_ONLY(wsrep_dirty_reads), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + #endif /* WITH_WSREP */ static bool fix_host_cache_size(sys_var *, THD *, enum_var_type)