mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
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.
This commit is contained in:
25
mysql-test/suite/galera/r/galera_var_dirty_reads.result
Normal file
25
mysql-test/suite/galera/r/galera_var_dirty_reads.result
Normal file
@ -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
|
@ -34,6 +34,7 @@ push @::global_suppressions,
|
|||||||
qr(WSREP: Failed to send state UUID:),
|
qr(WSREP: Failed to send state UUID:),
|
||||||
qr(WSREP: last inactive check more than .* skipping check),
|
qr(WSREP: last inactive check more than .* skipping check),
|
||||||
qr(WSREP: SQL statement was ineffective),
|
qr(WSREP: SQL statement was ineffective),
|
||||||
|
qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
46
mysql-test/suite/galera/t/galera_var_dirty_reads.test
Normal file
46
mysql-test/suite/galera/t/galera_var_dirty_reads.test
Normal file
@ -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
|
||||||
|
|
35
mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result
Normal file
35
mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result
Normal file
@ -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
|
35
mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test
Normal file
35
mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test
Normal file
@ -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
|
@ -654,6 +654,7 @@ typedef struct system_variables
|
|||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
my_bool wsrep_on;
|
my_bool wsrep_on;
|
||||||
my_bool wsrep_causal_reads;
|
my_bool wsrep_causal_reads;
|
||||||
|
my_bool wsrep_dirty_reads;
|
||||||
uint wsrep_sync_wait;
|
uint wsrep_sync_wait;
|
||||||
ulong wsrep_retry_autocommit;
|
ulong wsrep_retry_autocommit;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2615,11 +2615,13 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bail out if DB snapshot has not been installed. We however,
|
Bail out if DB snapshot has not been installed. We however,
|
||||||
* allow SET and SHOW queries
|
allow SET and SHOW queries.
|
||||||
*/
|
*/
|
||||||
if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready &&
|
if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready &&
|
||||||
lex->sql_command != SQLCOM_SET_OPTION &&
|
lex->sql_command != SQLCOM_SET_OPTION &&
|
||||||
|
!(thd->variables.wsrep_dirty_reads &&
|
||||||
|
lex->sql_command == SQLCOM_SELECT) &&
|
||||||
!wsrep_is_show_query(lex->sql_command))
|
!wsrep_is_show_query(lex->sql_command))
|
||||||
{
|
{
|
||||||
#if DIRTY_HACK
|
#if DIRTY_HACK
|
||||||
|
@ -4743,6 +4743,12 @@ static Sys_var_mybool Sys_wsrep_slave_UK_checks(
|
|||||||
static Sys_var_mybool Sys_wsrep_restart_slave(
|
static Sys_var_mybool Sys_wsrep_restart_slave(
|
||||||
"wsrep_restart_slave", "Should MySQL slave be restarted automatically, when node joins back to cluster",
|
"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));
|
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 */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
static bool fix_host_cache_size(sys_var *, THD *, enum_var_type)
|
static bool fix_host_cache_size(sys_var *, THD *, enum_var_type)
|
||||||
|
Reference in New Issue
Block a user