diff --git a/mysql-test/suite/galera/r/galera_mdev_31517.result b/mysql-test/suite/galera/r/galera_mdev_31517.result new file mode 100644 index 0000000000000..efb3f9856223a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_mdev_31517.result @@ -0,0 +1,24 @@ +connection node_2; +connection node_1; +connection node_2; +CALL mtr.add_suppression("unknown variable 'non_existing_variable=ON'"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("sst_received failed: State wait was interrupted"); +CALL mtr.add_suppression("State transfer interrupted, shutting down gracefully"); +connection node_1; +CREATE TABLE t(i INT NOT NULL PRIMARY KEY) ENGINE INNODB; +INSERT INTO t VALUES(1); +connection node_2; +connection node_1; +connection node_2; +connection node_1; +connection node_2; +connection node_1; +connection node_2; +Starting server ... +Starting server ... +SET GLOBAL wsrep_mode = DEFAULT; +connection node_1; +DROP TABLE t; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/galera_mdev_31517.test b/mysql-test/suite/galera/t/galera_mdev_31517.test new file mode 100644 index 0000000000000..2793d383bf086 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_mdev_31517.test @@ -0,0 +1,129 @@ +# +# Test for MDEV-31517: Wrong variable name in the configuration leads +# Galera to think SST/IST failed, at next restart will request a full +# SST. +# +# To reproduce: +# +# 1. Start Galera cluster +# 2. Stop a Node +# 3. Start the node +# 4. Stop a Node +# 5. Add non_existing_variable=ON in the config +# 6. Start the node, this will fail +# 7 Remove non_existing_variable=ON from the config file +# 8 Restart the server +# 9. Observe a full SST happening +# +# This test checks that an IST takes place at Step 9 instead of a full SST. + +# Step 1: Start Galera cluster +--source include/galera_cluster.inc +--source include/have_mariabackup.inc + +# Suppress expected errors and warnings: +--connection node_2 +CALL mtr.add_suppression("unknown variable 'non_existing_variable=ON'"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("sst_received failed: State wait was interrupted"); +CALL mtr.add_suppression("State transfer interrupted, shutting down gracefully"); + +# Count the number of "SST completed" messages in the log file before +# and after testing. To do this we need to save original log file +# before testing: +# +--let TEST_LOG=$MYSQLTEST_VARDIR/log/mysqld.2.err +--perl + use strict; + my $test_log=$ENV{'TEST_LOG'} or die "TEST_LOG not set"; + my $test_log_copy=$test_log . '.copy'; + if (-e $test_log_copy) { + unlink $test_log_copy; + } +EOF +--copy_file $TEST_LOG $TEST_LOG.copy + +--connection node_1 +CREATE TABLE t(i INT NOT NULL PRIMARY KEY) ENGINE INNODB; +INSERT INTO t VALUES(1); + +# Step 2: Stop node 2 +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Step 3: Start node 2 +--connection node_2 +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Step 4: Stop node 2 +--connection node_2 +let $MYSQLD_DATADIR= `SELECT @@datadir`; +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Step 5: Add non_existing_variable=ON in the config +--exec cp $MYSQLTEST_VARDIR/my.cnf $MYSQLTEST_VARDIR/my.cnf-orig +--exec echo '[mysqld.2]' >> $MYSQLTEST_VARDIR/my.cnf +--exec echo 'non_existing_variable=ON' >> $MYSQLTEST_VARDIR/my.cnf + +# Step 6: start the stopped node, this will fail +--connection node_2 +--exec cp -p $MYSQLD_DATADIR/grastate.dat $MYSQLD_DATADIR/grastate.dat_before +--echo Starting server ... +--error 1 +--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf | grep 'non_existing_variable' +--exec cp -p $MYSQLD_DATADIR/grastate.dat $MYSQLD_DATADIR/grastate.dat_after + +# Step 7: remove the wrong variable in the config file +--exec cp $MYSQLTEST_VARDIR/my.cnf-orig $MYSQLTEST_VARDIR/my.cnf + +# Step 8: Start the node +--echo Starting server ... +let $restart_noprint=2; +--source include/start_mysqld.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +# cleanup +SET GLOBAL wsrep_mode = DEFAULT; + +--connection node_1 +DROP TABLE t; + +# Count the number of "SST completed" messages in the log file during +# test phase - to print the error message if the number of such +# messages in log file increased at the end of the test: +# +--perl + use strict; + my $test_log=$ENV{'TEST_LOG'} or die "TEST_LOG not set"; + my $test_log_copy=$test_log . '.copy'; + open(FILE, $test_log_copy) or die("Unable to open $test_log_copy: $!\n"); + my $initial=grep(/SST completed/gi,); + close(FILE); + open(FILE, $test_log) or die("Unable to open $test_log: $!\n"); + my $final=grep(/SST completed/gi,); + close(FILE); + if ($final != $initial) { + my $diff=$final-$initial; + print("Full WSREP SST performed $diff times.\n"); + } +EOF +--remove_file $TEST_LOG.copy + +--source include/galera_end.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 138cc52db27d7..6e27563ee3050 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5241,8 +5241,14 @@ static int init_server_components() #endif if ((ho_error= handle_options(&remaining_argc, &remaining_argv, removed_opts, - mysqld_get_one_option))) + mysqld_get_one_option))) { +#ifdef WITH_WSREP + Wsrep_server_state::instance().disable_node_reset(); +#endif + unireg_abort(ho_error); + } + /* Add back the program name handle_options removes */ remaining_argc++; remaining_argv--; diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc index 268ad0e432dbe..bfe570b8df890 100644 --- a/sql/wsrep_client_service.cc +++ b/sql/wsrep_client_service.cc @@ -392,3 +392,9 @@ int Wsrep_client_service::bf_rollback() DBUG_RETURN(ret); } + +void Wsrep_client_service::notify_state_change() +{ + DBUG_ENTER("Wsrep_client_service::notify_state_change"); + DBUG_VOID_RETURN; +} diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h index f53d9be083d72..bf89fc21f7778 100644 --- a/sql/wsrep_client_service.h +++ b/sql/wsrep_client_service.h @@ -68,6 +68,7 @@ class Wsrep_client_service : public wsrep::client_service void debug_sync(const char*) override; void debug_crash(const char*) override; int bf_rollback() override; + void notify_state_change() override; private: friend class Wsrep_server_service; THD* m_thd; diff --git a/wsrep-lib b/wsrep-lib index e55f01ce1eed0..fdae687f1dc81 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit e55f01ce1eed02e0781bc53bb23456c936667ccf +Subproject commit fdae687f1dc819e022e195bc68a4b7ebfac40137