From 880baedcf6f2c1c342dc59e8a0e813c0ea728264 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 2 Apr 2021 18:13:46 +0300 Subject: [PATCH 1/5] MDEV-17913 Encrypted transactional Aria tables remain corrupt after crash recovery, automatic repairment does not work This was because of a wrong test in encryption code that wrote random numbers over the LSN for pages for transactional Aria tables during repair. The effect was that after an ALTER TABLE ENABLE KEYS of a encrypted recovery of the tables would not work. The test cases will be pushed into 10.5 as it requires of several changes to check table that safer not to backport. --- storage/maria/ma_crypt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index 95b84d38221..564edb4bbe8 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -268,7 +268,7 @@ static my_bool ma_crypt_data_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) return 1; } - if (!share->now_transactional) + if (!share->base.born_transactional) { /* store a random number instead of LSN (for counter block) */ store_rand_lsn(args->page); @@ -392,7 +392,7 @@ static my_bool ma_crypt_index_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) return 1; } - if (!share->now_transactional) + if (!share->base.born_transactional) { /* store a random number instead of LSN (for counter block) */ store_rand_lsn(args->page); From 915983e1cc3a0a356a0adfef38fc7ad87264bd9f Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Wed, 24 Mar 2021 10:55:27 +0100 Subject: [PATCH 2/5] MDEV-25226 Assertion when wsrep_on set OFF with SR transaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch makes the following changes around variable wsrep_on: 1) Variable wsrep_on can no longer be updated from a session that has an active transaction running. The original behavior allowed cases like this: BEGIN; INSERT INTO t1 VALUES (1); SET SESSION wsrep_on = OFF; INSERT INTO t1 VALUES (2); COMMIT; With regular transactions this would result in no replication events (not even value 1). With streaming replication it would be unnecessarily complex to achieve the same behavior. In the above example, it would be possible for value 1 to be already replicated if it happened to fill a separate fragment, while value 2 wouldn't. 2) Global variable wsrep_on no longer affects current sessions, only subsequent ones. This is to avoid a similar case to the above, just using just by using global wsrep_on instead session wsrep_on: --connection conn_1 BEGIN; INSERT INTO t1 VALUES(1); --connection conn_2 SET GLOBAL wsrep_on = OFF; --connection conn_1 INSERT INTO t1 VALUES(2); COMMIT; The above example results in the transaction to be replicated, as global wsrep_on will only affect the session wsrep_on of new connections. Reviewed-by: Jan Lindström --- .../galera/r/galera_var_wsrep_on_off.result | 46 +++++++++++++++ .../galera/t/galera_var_wsrep_on_off.test | 57 +++++++++++++++++++ .../suite/galera_sr/r/MDEV-25226.result | 24 ++++++++ mysql-test/suite/galera_sr/t/MDEV-25226.test | 33 +++++++++++ sql/mysqld.cc | 13 +---- sql/wsrep_mysqld.cc | 12 ++++ sql/wsrep_mysqld.h | 7 ++- sql/wsrep_trans_observer.h | 2 +- sql/wsrep_var.cc | 14 ++++- sql/wsrep_var.h | 1 + 10 files changed, 190 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/galera_sr/r/MDEV-25226.result create mode 100644 mysql-test/suite/galera_sr/t/MDEV-25226.test diff --git a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result index 5323bc9bf60..b3096afd387 100644 --- a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result +++ b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result @@ -22,3 +22,49 @@ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3; COUNT(*) = 1 1 DROP TABLE t1; +START TRANSACTION; +SET SESSION wsrep_on=OFF; +ERROR 25000: You are not allowed to execute this command in a transaction +SET GLOBAL wsrep_on=OFF; +ERROR 25000: You are not allowed to execute this command in a transaction +COMMIT; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +START TRANSACTION; +INSERT INTO t1 VALUES (1); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;; +connection node_1a; +SET GLOBAL wsrep_on = OFF; +connection node_1; +SHOW SESSION VARIABLES LIKE 'wsrep_on'; +Variable_name Value +wsrep_on ON +SHOW GLOBAL VARIABLES LIKE 'wsrep_on'; +Variable_name Value +wsrep_on OFF +INSERT INTO t1 VALUES (2); +COMMIT; +connection node_2; +SET SESSION wsrep_sync_wait = 15; +SELECT * FROM t1; +f1 +1 +2 +connection node_1a; +SET GLOBAL wsrep_on = ON; +DROP TABLE t1; +connection node_1; +SET GLOBAL wsrep_on = OFF; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;; +connection node_1b; +SHOW SESSION VARIABLES LIKE 'wsrep_on'; +Variable_name Value +wsrep_on OFF +SHOW GLOBAL VARIABLES LIKE 'wsrep_on'; +Variable_name Value +wsrep_on OFF +CREATE TABLE t2 (f1 INTEGER); +DROP TABLE t2; +SET GLOBAL wsrep_on = ON; +SHOW SESSION VARIABLES LIKE 'wsrep_on'; +Variable_name Value +wsrep_on ON diff --git a/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test b/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test index 783b78792e6..1a48abc25eb 100644 --- a/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test +++ b/mysql-test/suite/galera/t/galera_var_wsrep_on_off.test @@ -30,3 +30,60 @@ SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 3; DROP TABLE t1; + +# +# Test that variable wsrep_on cannot be changed while in +# active transaction. +# + +START TRANSACTION; +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET SESSION wsrep_on=OFF; +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL wsrep_on=OFF; +COMMIT; + + +# +# Test that @@global.wsrep_on does not affect the value of +# @@session.wsrep_on of current sessions +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +--connection node_1a +SET GLOBAL wsrep_on = OFF; + +--connection node_1 +SHOW SESSION VARIABLES LIKE 'wsrep_on'; +SHOW GLOBAL VARIABLES LIKE 'wsrep_on'; +INSERT INTO t1 VALUES (2); +COMMIT; + +--connection node_2 +SET SESSION wsrep_sync_wait = 15; +SELECT * FROM t1; + +--connection node_1a +SET GLOBAL wsrep_on = ON; +DROP TABLE t1; + + +# +# New connections inherit @@session.wsrep_on from @@global.wsrep_on +# +--connection node_1 +SET GLOBAL wsrep_on = OFF; + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +--connection node_1b +SHOW SESSION VARIABLES LIKE 'wsrep_on'; +SHOW GLOBAL VARIABLES LIKE 'wsrep_on'; +CREATE TABLE t2 (f1 INTEGER); +DROP TABLE t2; + +SET GLOBAL wsrep_on = ON; +SHOW SESSION VARIABLES LIKE 'wsrep_on'; diff --git a/mysql-test/suite/galera_sr/r/MDEV-25226.result b/mysql-test/suite/galera_sr/r/MDEV-25226.result new file mode 100644 index 00000000000..4699023562d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MDEV-25226.result @@ -0,0 +1,24 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES(1); +SET SESSION wsrep_on=OFF; +ERROR 25000: You are not allowed to execute this command in a transaction +SET GLOBAL wsrep_on=OFF; +ERROR 25000: You are not allowed to execute this command in a transaction +INSERT INTO t1 VALUES(2); +COMMIT; +connection node_1; +SELECT * FROM t1; +f1 +1 +2 +connection node_2; +SELECT * FROM t1; +f1 +1 +2 +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/MDEV-25226.test b/mysql-test/suite/galera_sr/t/MDEV-25226.test new file mode 100644 index 00000000000..3d19a0b9675 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MDEV-25226.test @@ -0,0 +1,33 @@ +# +# MDEV-25226 - Test the case the where wsrep_on is set OFF +# on a transaction that has already replicated a fragment. +# +# This would cause: Assertion `transaction_.active() == false || +# (transaction_.state() == wsrep::transaction::s_executing || +# transaction_.state() == wsrep::transaction::s_prepared || +# transaction_.state() == wsrep::transaction::s_aborted || +# transaction_.state() == wsrep::transaction::s_must_abort)' +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); + +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES(1); +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET SESSION wsrep_on=OFF; +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES(2); +COMMIT; + +--connection node_1 +SELECT * FROM t1; + +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d0081034c0c..c536cdef504 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1131,14 +1131,6 @@ PSI_file_key key_file_binlog_state; PSI_statement_info stmt_info_new_packet; #endif -#ifdef WITH_WSREP -/** Whether the Galera write-set replication is enabled. A cached copy of -global_system_variables.wsrep_on && wsrep_provider && - strcmp(wsrep_provider, WSREP_NONE) -*/ -bool WSREP_ON_; -#endif /* WITH_WSREP */ - #ifndef EMBEDDED_LIBRARY void net_before_header_psi(struct st_net *net, void *thd, size_t /* unused: count */) { @@ -5710,10 +5702,7 @@ int mysqld_main(int argc, char **argv) } #ifdef WITH_WSREP - WSREP_ON_= (global_system_variables.wsrep_on && - wsrep_provider && - strcmp(wsrep_provider, WSREP_NONE)); - + wsrep_set_wsrep_on(); if (WSREP_ON && wsrep_check_opts()) unireg_abort(1); #endif diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c3c4e4a0bf4..0338d7ad054 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -131,6 +131,18 @@ uint wsrep_ignore_apply_errors= 0; * End configuration options */ +/* + * Cached variables + */ + +// Whether the Galera write-set replication provider is set +// wsrep_provider && strcmp(wsrep_provider, WSREP_NONE) +bool WSREP_PROVIDER_EXISTS_; + +// Whether the Galera write-set replication is enabled +// global_system_variables.wsrep_on && WSREP_PROVIDER_EXISTS_ +bool WSREP_ON_; + /* * Other wsrep global variables. */ diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 02996012156..0b245ea11cb 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -20,6 +20,7 @@ #ifdef WITH_WSREP extern bool WSREP_ON_; +extern bool WSREP_PROVIDER_EXISTS_; #include #include "mysql/service_wsrep.h" @@ -221,7 +222,8 @@ extern wsrep_seqno_t wsrep_locked_seqno; /* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to * avoid compiler warnings (GCC 6 and later) */ -#define WSREP_NNULL(thd) (WSREP_ON && thd->variables.wsrep_on) +#define WSREP_NNULL(thd) \ + (WSREP_PROVIDER_EXISTS_ && thd->variables.wsrep_on) #define WSREP(thd) \ (thd && WSREP_NNULL(thd)) @@ -277,8 +279,7 @@ void WSREP_LOG(void (*fun)(const char* fmt, ...), const char* fmt, ...); WSREP_INFO("context: %s:%d", __FILE__, __LINE__); \ } -#define WSREP_PROVIDER_EXISTS \ - (wsrep_provider && strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN)) +#define WSREP_PROVIDER_EXISTS (WSREP_PROVIDER_EXISTS_) static inline bool wsrep_cluster_address_exists() { diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index dbe710a0256..366cbef50d3 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -407,7 +407,7 @@ static inline void wsrep_after_apply(THD* thd) static inline void wsrep_open(THD* thd) { DBUG_ENTER("wsrep_open"); - if (WSREP(thd)) + if (WSREP_PROVIDER_EXISTS) { thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); thd->wsrep_cs().debug_log_level(wsrep_debug); diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 815a65ff240..01e9d022cfb 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -88,10 +88,11 @@ static bool refresh_provider_options() } } -static void wsrep_set_wsrep_on() +void wsrep_set_wsrep_on() { - WSREP_ON_= global_system_variables.wsrep_on && wsrep_provider && - strcmp(wsrep_provider, WSREP_NONE); + WSREP_PROVIDER_EXISTS_= wsrep_provider && + strncasecmp(wsrep_provider, WSREP_NONE, FN_REFLEN); + WSREP_ON_= global_system_variables.wsrep_on && WSREP_PROVIDER_EXISTS_; } /* This is intentionally declared as a weak global symbol, so that @@ -146,6 +147,13 @@ bool wsrep_on_check(sys_var *self, THD* thd, set_var* var) " innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0)); return true; } + + if (thd->in_active_multi_stmt_transaction()) + { + my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0)); + return true; + } + return false; } diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 481df02f2d5..b1b2932cdfe 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -35,6 +35,7 @@ class set_var; class THD; int wsrep_init_vars(); +void wsrep_set_wsrep_on(); #define CHECK_ARGS (sys_var *self, THD* thd, set_var *var) #define UPDATE_ARGS (sys_var *self, THD* thd, enum_var_type type) From f8488370d6e4dc38643545260b17755bb8be8a9d Mon Sep 17 00:00:00 2001 From: mkaruza Date: Wed, 31 Mar 2021 14:59:50 +0200 Subject: [PATCH 3/5] MDEV-24956: ALTER TABLE not replicated with Galera in MariaDB 10.5.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `WSREP_CLIENT` is used as condition for starting ALTER/OPTIMIZE/REPAIR TOI. Using this condition async replicated affected DDL's will not be replicated. Fixed by removing this condition. Reviewed-by: Jan Lindström --- .../galera_3nodes/r/galera_2_cluster.result | 89 +++++++++++ .../galera_3nodes/t/galera_2_cluster.cnf | 25 +++ .../galera_3nodes/t/galera_2_cluster.test | 148 ++++++++++++++++++ sql/sql_admin.cc | 11 +- sql/sql_alter.cc | 2 +- 5 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera_3nodes/r/galera_2_cluster.result create mode 100644 mysql-test/suite/galera_3nodes/t/galera_2_cluster.cnf create mode 100644 mysql-test/suite/galera_3nodes/t/galera_2_cluster.test diff --git a/mysql-test/suite/galera_3nodes/r/galera_2_cluster.result b/mysql-test/suite/galera_3nodes/r/galera_2_cluster.result new file mode 100644 index 00000000000..87898891f9b --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_2_cluster.result @@ -0,0 +1,89 @@ +connection node_2; +connection node_1; +connect node_5, 127.0.0.1, root, , test, $NODE_MYPORT_5; +connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4; +connection node_4; +CHANGE MASTER TO master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_1, master_use_gtid=current_pos;; +START SLAVE; +include/wait_for_slave_to_start.inc +connection node_1; +CREATE TABLE t1(c1 INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INTEGER); +INSERT INTO t1(c2) VALUES(1); +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connection node_1; +include/save_master_gtid.inc +connection node_4; +include/sync_with_master_gtid.inc +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connect node_6, 127.0.0.1, root, , test, $NODE_MYPORT_6; +connection node_6; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connection node_2; +ALTER TABLE t1 ADD COLUMN t3 INTEGER; +Node 2 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; +COUNT(*) = 3 +1 +connection node_3; +Node 3 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; +COUNT(*) = 3 +1 +connection node_1; +include/save_master_gtid.inc +connection node_4; +include/sync_with_master_gtid.inc +Node 4 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; +COUNT(*) = 3 +1 +connection node_6; +Node 6 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; +COUNT(*) = 3 +1 +connection node_2; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +connection node_1; +connection node_4; +connection node_6; +connection node_1; +DROP TABLE t1; +connection node_4; +STOP SLAVE; +RESET SLAVE; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +SET GLOBAL GTID_SLAVE_POS=""; +connection node_1; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +connection node_2; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +connection node_3; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +connection node_5; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +connection node_6; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; diff --git a/mysql-test/suite/galera_3nodes/t/galera_2_cluster.cnf b/mysql-test/suite/galera_3nodes/t/galera_2_cluster.cnf new file mode 100644 index 00000000000..3889a4f4fdd --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_2_cluster.cnf @@ -0,0 +1,25 @@ +!include ../galera_2x3nodes.cnf + +[mysqld.1] +wsrep_gtid_domain_id=1 +server-id=11 + +[mysqld.2] +wsrep_gtid_domain_id=1 +server-id=12 + +[mysqld.3] +wsrep_gtid_domain_id=1 +server-id=13 + +[mysqld.4] +wsrep_gtid_domain_id=2 +server-id=21 + +[mysqld.5] +wsrep_gtid_domain_id=2 +server-id=22 + +[mysqld.6] +wsrep_gtid_domain_id=2 +server-id=23 \ No newline at end of file diff --git a/mysql-test/suite/galera_3nodes/t/galera_2_cluster.test b/mysql-test/suite/galera_3nodes/t/galera_2_cluster.test new file mode 100644 index 00000000000..8a9a74a7252 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_2_cluster.test @@ -0,0 +1,148 @@ +# +# This test creates 2x3 nodes galera cluster. +# +# A(1) <-> B(2) <-> C(3) {Galera cluster 1} +# | {Circular Async replication} +# D(4) <-> E(5) <-> F(6) {Galera cluster 2} +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connect node_5, 127.0.0.1, root, , test, $NODE_MYPORT_5 + +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connection node_4 + +--replace_result $NODE_MYPORT_1 NODE_MYPORT_1 +--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_1, master_use_gtid=current_pos; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +# +# CREATE TABLE & INSERT +# + +--connection node_1 + +CREATE TABLE t1(c1 INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INTEGER); +INSERT INTO t1(c2) VALUES(1); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 + +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +--source include/save_master_gtid.inc + +--connection node_4 +--source include/sync_with_master_gtid.inc + +SELECT COUNT(*) = 1 FROM t1; + +--connect node_6, 127.0.0.1, root, , test, $NODE_MYPORT_6 +--connection node_6 + +SELECT COUNT(*) = 1 FROM t1; + +# +# ALTER TABLE +# + +--connection node_2 + +ALTER TABLE t1 ADD COLUMN t3 INTEGER; +--echo Node 2 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; + +--connection node_3 + +--echo Node 3 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; + +--connection node_1 +--source include/save_master_gtid.inc + +--connection node_4 +--source include/sync_with_master_gtid.inc + +--echo Node 4 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; + +--connection node_6 + +--echo Node 6 column number AFTER ALTER +SELECT COUNT(*) = 3 FROM information_schema.columns WHERE table_name ='t1'; + +# +# OPTIMIZE TABLE +# + +--connection node_2 + +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +OPTIMIZE TABLE t1; + +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE >= $wsrep_last_committed_before + 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed' +--source include/wait_condition.inc + +--connection node_4 + +--let $wait_condition = SELECT VARIABLE_VALUE >= $wsrep_last_committed_before + 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed' +--source include/wait_condition.inc + +--connection node_6 + +--let $wait_condition = SELECT VARIABLE_VALUE >= $wsrep_last_committed_before + 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed' +--source include/wait_condition.inc + +# +# Cleanup +# + +--connection node_1 + +DROP TABLE t1; + +--connection node_4 + +STOP SLAVE; +RESET SLAVE; +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; +SET GLOBAL GTID_SLAVE_POS=""; + +--connection node_1 + +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; + +--connection node_2 + +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; + +--connection node_3 + +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; + +--connection node_5 + +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; + +--connection node_6 + +SET GLOBAL wsrep_on = OFF; +RESET MASTER; +SET GLOBAL wsrep_on = ON; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index e59dffc10aa..a96eb58809b 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -447,8 +447,6 @@ dbug_err: */ static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables) { - if (!WSREP(thd) || !WSREP_CLIENT(thd)) return false; - LEX *lex= thd->lex; /* only handle OPTIMIZE and REPAIR here */ switch (lex->sql_command) @@ -549,10 +547,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, for (table= tables; table; table= table->next_local) table->table= NULL; #ifdef WITH_WSREP - if (wsrep_toi_replication(thd, tables)) + if (WSREP(thd)) { - WSREP_INFO("wsrep TOI replication of has failed, skipping OPTIMIZE"); - goto err; + if(wsrep_toi_replication(thd, tables)) + { + WSREP_INFO("wsrep TOI replication of has failed."); + goto err; + } } #endif /* WITH_WSREP */ diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 2bbc8169df2..f1a67e7d968 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -471,7 +471,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE)) DBUG_RETURN(TRUE); /* purecov: inspected */ #ifdef WITH_WSREP - if (WSREP(thd) && WSREP_CLIENT(thd) && + if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() || !thd->find_temporary_table(first_table))) { From 5b71e0424c0c647c39798fd1791e8b68d730d784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 6 Apr 2021 15:33:13 +0300 Subject: [PATCH 4/5] MDEV-21402 : sql_safe_updates breaks Galera 4 Added handling for sql_safe_updated i.e. we disable it while we do wsrep_schema operations. --- .../r/galera_wsrep_schema_init.result | 94 +++++++++++++++++++ .../t/galera_wsrep_schema_init.cnf | 5 + .../t/galera_wsrep_schema_init.test | 58 ++++++++++++ sql/wsrep_schema.cc | 36 ++++++- 4 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result create mode 100644 mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.cnf create mode 100644 mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.test diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result new file mode 100644 index 00000000000..2a29afd62be --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema_init.result @@ -0,0 +1,94 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_1; +connection node_2; +connection node_3; +SHOW CREATE TABLE mysql.wsrep_cluster; +Table Create Table +wsrep_cluster CREATE TABLE `wsrep_cluster` ( + `cluster_uuid` char(36) NOT NULL, + `view_id` bigint(20) NOT NULL, + `view_seqno` bigint(20) NOT NULL, + `protocol_version` int(11) NOT NULL, + `capabilities` int(11) NOT NULL, + PRIMARY KEY (`cluster_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE mysql.wsrep_cluster_members; +Table Create Table +wsrep_cluster_members CREATE TABLE `wsrep_cluster_members` ( + `node_uuid` char(36) NOT NULL, + `cluster_uuid` char(36) NOT NULL, + `node_name` char(32) NOT NULL, + `node_incoming_address` varchar(256) NOT NULL, + PRIMARY KEY (`node_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT @@sql_safe_updates; +@@sql_safe_updates +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster; +COUNT(*) = 1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +COUNT(*) = 3 +1 +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); +COUNT(*) = 1 +1 +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +node_incoming_address LIKE '127.0.0.1:%' +1 +1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +1 +1 +connection node_2; +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +COUNT(*) = 3 +1 +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); +COUNT(*) = 1 +1 +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +node_incoming_address LIKE '127.0.0.1:%' +1 +1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +1 +1 +connection node_3; +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +COUNT(*) = 3 +1 +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); +COUNT(*) = 1 +1 +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +node_incoming_address LIKE '127.0.0.1:%' +1 +1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +1 +1 diff --git a/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.cnf b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.cnf new file mode 100644 index 00000000000..317094cea72 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.cnf @@ -0,0 +1,5 @@ +!include ../galera_3nodes.cnf + +[mysqld] +sql-safe-updates=1 +wsrep-debug=1 diff --git a/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.test b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.test new file mode 100644 index 00000000000..7d8089a8ceb --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema_init.test @@ -0,0 +1,58 @@ +# +# This test performs basic checks on the contents of the wsrep_schema +# +# wsrep_members_history checks are temporarily disabled until it +# can be made configurable. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +# Make the test fail if table structure has changed + +SHOW CREATE TABLE mysql.wsrep_cluster; +SHOW CREATE TABLE mysql.wsrep_cluster_members; +#disabled SHOW CREATE TABLE mysql.wsrep_member_history; +SELECT @@sql_safe_updates; + +# Checks for the wsrep_cluster table + +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster; + +# Checks for the wsrep_cluster_members table + +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); + +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; + +--connection node_2 + +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); + +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; + +--connection node_3 +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); + +SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_members; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; + +--source ../galera/include/auto_increment_offset_restore.inc + diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index e811d4e8317..5ee6468e9c1 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -159,6 +159,24 @@ private: THD *m_cur_thd; }; +class sql_safe_updates +{ +public: + sql_safe_updates(THD* thd) + : m_thd(thd) + , m_option_bits(thd->variables.option_bits) + { + thd->variables.option_bits&= ~OPTION_SAFE_UPDATES; + } + ~sql_safe_updates() + { + m_thd->variables.option_bits= m_option_bits; + } +private: + THD* m_thd; + ulonglong m_option_bits; +}; + static int execute_SQL(THD* thd, const char* sql, uint length) { DBUG_ENTER("Wsrep_schema::execute_SQL()"); int err= 0; @@ -603,13 +621,15 @@ static void wsrep_init_thd_for_schema(THD *thd) thd->prior_thr_create_utime= thd->start_utime= thd->thr_create_utime; - /* */ - thd->variables.wsrep_on = 0; + /* No Galera replication */ + thd->variables.wsrep_on= 0; /* No binlogging */ - thd->variables.sql_log_bin = 0; - thd->variables.option_bits &= ~OPTION_BIN_LOG; + thd->variables.sql_log_bin= 0; + thd->variables.option_bits&= ~OPTION_BIN_LOG; + /* No safe updates */ + thd->variables.option_bits&= ~OPTION_SAFE_UPDATES; /* No general log */ - thd->variables.option_bits |= OPTION_LOG_OFF; + thd->variables.option_bits|= OPTION_LOG_OFF; /* Read committed isolation to avoid gap locking */ thd->variables.tx_isolation= ISO_READ_COMMITTED; wsrep_assign_from_threadvars(thd); @@ -664,6 +684,7 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) Wsrep_schema_impl::wsrep_off wsrep_off(thd); Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); /* Clean up cluster table and members table. @@ -918,6 +939,7 @@ int Wsrep_schema::append_fragment(THD* thd, thd->lex->reset_n_backup_query_tables_list(&query_tables_list_backup); Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); Wsrep_schema_impl::init_stmt(thd); TABLE* frag_table= 0; @@ -967,6 +989,7 @@ int Wsrep_schema::update_fragment_meta(THD* thd, thd->lex->reset_n_backup_query_tables_list(&query_tables_list_backup); Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); int error; uchar *key=NULL; key_part_map key_map= 0; @@ -1089,6 +1112,7 @@ int Wsrep_schema::remove_fragments(THD* thd, WSREP_DEBUG("Removing %zu fragments", fragments.size()); Wsrep_schema_impl::wsrep_off wsrep_off(thd); Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); Query_tables_list query_tables_list_backup; Open_tables_backup open_tables_backup; @@ -1156,6 +1180,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, Wsrep_schema_impl::wsrep_off wsrep_off(&thd); Wsrep_schema_impl::binlog_off binlog_off(&thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(&thd); Wsrep_schema_impl::thd_context_switch thd_context_switch(orig_thd, &thd); int ret= 1; @@ -1270,6 +1295,7 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) Wsrep_storage_service storage_service(&storage_thd); Wsrep_schema_impl::binlog_off binlog_off(&storage_thd); Wsrep_schema_impl::wsrep_off wsrep_off(&storage_thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(&storage_thd); Wsrep_schema_impl::thd_context_switch thd_context_switch(orig_thd, &storage_thd); Wsrep_server_state& server_state(Wsrep_server_state::instance()); From f69c1c9dcb815d7597ec2035470a81ac3b6c9380 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 6 Apr 2021 16:57:38 +1000 Subject: [PATCH 5/5] MDEV-19508: SI_KERNEL is not on all implementations SI_USER is, however in FreeBSD there are a couple of non-kernel user signal infomations above SI_KERNEL. Put a fallback just in case there is nothing available. --- include/my_pthread.h | 1 - sql/mysqld.cc | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 81dd63ee331..bc47bb8bad0 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -197,7 +197,6 @@ static inline int my_sigwait(sigset_t *set, int *sig, int *code) *code= siginfo.si_code; return *sig < 0 ? errno : 0; #else -#define SI_KERNEL 128 *code= 0; return sigwait(set, sig); #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c536cdef504..7e3ce878cdc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3253,7 +3253,13 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) } break; case SIGHUP: +#if defined(SI_KERNEL) if (!abort_loop && origin != SI_KERNEL) +#elif defined(SI_USER) + if (!abort_loop && origin <= SI_USER) +#else + if (!abort_loop) +#endif { int not_used; mysql_print_status(); // Print some debug info