Commit 9b7e3801 authored by Nirbhay Choubey's avatar Nirbhay Choubey

MDEV-7476: Allow SELECT to succeed even when node is not ready

Added a SESSION-only system variable "wsrep_dirty_reads" to allow SELECT
queries to pass even when the node is not prepared to accept queries
(wsrep_ready=OFF). Added a test case.
parent 5b6f637c
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
......@@ -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.),
);
......
#
# 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
#
# 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
--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
......@@ -594,6 +594,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
......
......@@ -2392,11 +2392,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
......
......@@ -3951,6 +3951,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 Sys_var_charptr Sys_ignore_db_dirs(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment