diff --git a/mysql-test/suite/wsrep/r/wsrep_cluster_address_update.result b/mysql-test/suite/wsrep/r/wsrep_cluster_address_update.result new file mode 100644 index 0000000000000..375333d8f7fd1 --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep_cluster_address_update.result @@ -0,0 +1,28 @@ +# +# Set sync point and change cluster address, it will block +# +connect con1, localhost, root; +SET DEBUG_SYNC = "wsrep_cluster_address_update SIGNAL update_reached WAIT_FOR continue"; +SET GLOBAL wsrep_cluster_address='gcomm://';; +# +# Wait until sync point is reached +# +connect con_ctrl, localhost, root; +SET DEBUG_SYNC = "now WAIT_FOR update_reached"; +# +# set !wsrep_cluster_address[0], that failed earlier +# +connect con2, localhost, root; +SET GLOBAL wsrep_cluster_address='';; +connection con_ctrl; +# +# Signal cluster address update to continue +# +SET DEBUG_SYNC = "now SIGNAL continue"; +disconnect con1; +disconnect con2; +connect con1, localhost, root; +# restart +disconnect con_ctrl; +call mtr.add_suppression(".*mariadbd got signal.*"); +call mtr.add_suppression("Attempting backtrace. Include this in the bug report."); diff --git a/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.cnf b/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.cnf new file mode 100644 index 0000000000000..f4d5689404cda --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.cnf @@ -0,0 +1,13 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld.1] +wsrep-on=ON +binlog-format=ROW +innodb-flush-log-at-trx-commit=1 +wsrep-cluster-address=gcomm:// +wsrep-provider=@ENV.WSREP_PROVIDER +innodb-autoinc-lock-mode=2 +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port diff --git a/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.test b/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.test new file mode 100644 index 0000000000000..3674949cb9ebe --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep_cluster_address_update.test @@ -0,0 +1,41 @@ +--source include/have_wsrep.inc +--source include/have_innodb.inc +--source include/have_wsrep_provider.inc +--source include/have_debug_sync.inc + +--echo # +--echo # Set sync point and change cluster address, it will block +--echo # +--connect con1, localhost, root +SET DEBUG_SYNC = "wsrep_cluster_address_update SIGNAL update_reached WAIT_FOR continue"; +--send SET GLOBAL wsrep_cluster_address='gcomm://'; + +--echo # +--echo # Wait until sync point is reached +--echo # +--connect con_ctrl, localhost, root +SET DEBUG_SYNC = "now WAIT_FOR update_reached"; + +--echo # +--echo # set !wsrep_cluster_address[0], that failed earlier +--echo # +--connect con2, localhost, root +--send SET GLOBAL wsrep_cluster_address=''; + +--connection con_ctrl +--echo # +--echo # Signal cluster address update to continue +--echo # +--error 0,2013 +SET DEBUG_SYNC = "now SIGNAL continue"; +sleep 2; + +--disconnect con1 +--disconnect con2 + +--connect con1, localhost, root +--source include/restart_mysqld.inc + +--disconnect con_ctrl +call mtr.add_suppression(".*mariadbd got signal.*"); +call mtr.add_suppression("Attempting backtrace. Include this in the bug report."); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 010cab56614ce..28afe7dc49e70 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -986,7 +986,7 @@ void wsrep_init_startup (bool sst_first) */ if (!wsrep_start_replication(wsrep_cluster_address)) unireg_abort(1); - wsrep_create_rollbacker(); + wsrep_create_rollbacker(wsrep_cluster_address); wsrep_create_appliers(1); Wsrep_server_state& server_state= Wsrep_server_state::instance(); diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 8e83aa955382b..bd932a2b3bd69 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2023 Codership Oy +/* Copyright (C) 2013-2025 Codership Oy 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 @@ -278,9 +278,9 @@ static void wsrep_rollback_process(THD *rollbacker, DBUG_VOID_RETURN; } -void wsrep_create_rollbacker() +void wsrep_create_rollbacker(const char* cluster_address) { - DBUG_ASSERT(wsrep_cluster_address[0]); + DBUG_ASSERT(cluster_address[0]); Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_rollback_process, WSREP_ROLLBACKER_THREAD, pthread_self())); diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 2fe3e123ceaa5..79f63a35233bf 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2023 Codership Oy +/* Copyright (C) 2013-2025 Codership Oy 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 @@ -85,7 +85,7 @@ class Wsrep_thd_queue int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, void *, system_status_var *, enum enum_var_type scope); bool wsrep_create_appliers(long threads, bool mutex_protected=false); -void wsrep_create_rollbacker(); +void wsrep_create_rollbacker(const char*); bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd); /* diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3d381afa7048c..b5fdee8269763 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2023 Codership Oy +/* Copyright 2008-2025 Codership Oy 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 @@ -657,15 +657,24 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) char *tmp= my_strdup(PSI_INSTRUMENT_ME, wsrep_cluster_address, MYF(MY_WME)); WSREP_DEBUG("wsrep_cluster_address_update: %s", wsrep_cluster_address); mysql_mutex_unlock(&LOCK_global_system_variables); - + /* Here, wsrep_cluster_address can be changed */ + DEBUG_SYNC(thd, "wsrep_cluster_address_update"); mysql_mutex_lock(&LOCK_wsrep_cluster_config); wsrep_stop_replication(thd); + /* + Note that we can't lock LOCK_global_system_variables yet + because in below LOCK_wsrep_slave_threads is aquired + and correct mutexing order is LOCK_wsrep_slave_threads + and then LOCK_global_system_variables. + tmp passed below because wsrep_cluster_address could have + been changed meanwhile. + */ if (*tmp && wsrep_start_replication(tmp)) { - wsrep_create_rollbacker(); - WSREP_DEBUG("Cluster address update creating %ld applier threads running %lu", - wsrep_slave_threads, wsrep_running_applier_threads); + wsrep_create_rollbacker(tmp); + WSREP_INFO("Cluster address update to %s creating %ld applier threads running %lu", + tmp, wsrep_slave_threads, wsrep_running_applier_threads); wsrep_create_appliers(wsrep_slave_threads); } mysql_mutex_unlock(&LOCK_wsrep_cluster_config);