From 5a61fd58197deee41b14a02a18550ef628b09442 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 29 Aug 2024 12:30:05 +0200 Subject: [PATCH 01/12] MDEV-34831: MDEV-34704 introduces a typo, --qick Fix MDEV-34704 typos. --- client/mysql.cc | 3 ++- mysql-test/main/client.result | 2 +- mysql-test/main/client.test | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 37f8482cfc5..aadfa72fcf7 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1681,7 +1681,8 @@ static struct my_option my_long_options[] = "if the output is suspended. Doesn't use history file.", &quick, &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"quick-max-column-width", 0, - "Maximal field length limit in case of --qick", &quick_max_column_width, + "Maximum number of characters displayed in a column header" + " when using --quick", &quick_max_column_width, &quick_max_column_width, 0, GET_ULONG, REQUIRED_ARG, LONG_MAX, 0, ULONG_MAX, 0, 1, 0}, {"raw", 'r', "Write fields without conversion. Used with --batch.", diff --git a/mysql-test/main/client.result b/mysql-test/main/client.result index bc3b9f64e81..86620d58bc6 100644 --- a/mysql-test/main/client.result +++ b/mysql-test/main/client.result @@ -58,5 +58,5 @@ insert into t1 values ("01234", "0123456789", "01234567890123456789", "1"); +-----------+------------+----------------------+------+ drop table t1; # -# End of 10.7 tests +# End of 10.5 tests # diff --git a/mysql-test/main/client.test b/mysql-test/main/client.test index 20df85f0807..d7249c15e75 100644 --- a/mysql-test/main/client.test +++ b/mysql-test/main/client.test @@ -42,5 +42,5 @@ insert into t1 values ("01234", "0123456789", "01234567890123456789", "1"); drop table t1; --echo # ---echo # End of 10.7 tests +--echo # End of 10.5 tests --echo # From b1d74b7e7214178ab0e81b5fb4c27165ecd9f83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 29 Apr 2024 10:13:03 +0300 Subject: [PATCH 02/12] MDEV-33997 : Assertion `((WSREP_PROVIDER_EXISTS_ && this->variables.wsrep_on) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()' failed in int THD::binlog_write_row(TABLE*, bool, const uchar*) Problem was that we did not found that table was partitioned and then we should find what is actual underlaying storage engine. We should not use RSU for !InnoDB tables. Signed-off-by: Julius Goryavsky --- mysql-test/suite/wsrep/r/MDEV-33997.result | 38 ++++++++++++++ mysql-test/suite/wsrep/t/MDEV-33997.cnf | 9 ++++ .../suite/wsrep/t/MDEV-33997.combinations | 4 ++ mysql-test/suite/wsrep/t/MDEV-33997.test | 49 +++++++++++++++++++ sql/log_event_server.cc | 14 +++--- sql/sql_parse.cc | 7 +++ 6 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/wsrep/r/MDEV-33997.result create mode 100644 mysql-test/suite/wsrep/t/MDEV-33997.cnf create mode 100644 mysql-test/suite/wsrep/t/MDEV-33997.combinations create mode 100644 mysql-test/suite/wsrep/t/MDEV-33997.test diff --git a/mysql-test/suite/wsrep/r/MDEV-33997.result b/mysql-test/suite/wsrep/r/MDEV-33997.result new file mode 100644 index 00000000000..f0e43462054 --- /dev/null +++ b/mysql-test/suite/wsrep/r/MDEV-33997.result @@ -0,0 +1,38 @@ +SET SESSION wsrep_osu_method=RSU; +SET autocommit=0; +CREATE TABLE t (c INT) ENGINE=INNODB PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t VALUES (1); +INSERT INTO t SELECT 1 ; +COMMIT; +SELECT * FROM t; +c +1 +1 +DROP TABLE t; +SET autocommit=1; +SET SESSION wsrep_osu_method=RSU; +CREATE TABLE t (c INT) ENGINE=INNODB PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t SELECT 1 ; +SELECT * FROM t; +c +1 +DROP TABLE t; +SET autocommit=1; +SET SESSION wsrep_osu_method=RSU; +CREATE TABLE t (c INT) ENGINE=MYISAM PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t SELECT 1 ; +ERROR 42000: This version of MariaDB doesn't yet support 'RSU on this table engine' +SELECT * FROM t; +c +DROP TABLE t; +SET SESSION wsrep_osu_method=RSU; +SET autocommit=0; +CREATE TABLE t (c INT) ENGINE=MYISAM PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t VALUES (1); +INSERT INTO t SELECT 1 ; +ERROR 42000: This version of MariaDB doesn't yet support 'RSU on this table engine' +COMMIT; +SELECT * FROM t; +c +1 +DROP TABLE t; diff --git a/mysql-test/suite/wsrep/t/MDEV-33997.cnf b/mysql-test/suite/wsrep/t/MDEV-33997.cnf new file mode 100644 index 00000000000..489c4385dbd --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-33997.cnf @@ -0,0 +1,9 @@ +!include ../my.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 diff --git a/mysql-test/suite/wsrep/t/MDEV-33997.combinations b/mysql-test/suite/wsrep/t/MDEV-33997.combinations new file mode 100644 index 00000000000..1ce3b45aa1a --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-33997.combinations @@ -0,0 +1,4 @@ +[binlogon] +log-bin + +[binlogoff] diff --git a/mysql-test/suite/wsrep/t/MDEV-33997.test b/mysql-test/suite/wsrep/t/MDEV-33997.test new file mode 100644 index 00000000000..3d015244d7d --- /dev/null +++ b/mysql-test/suite/wsrep/t/MDEV-33997.test @@ -0,0 +1,49 @@ +--source include/have_wsrep.inc +--source include/have_innodb.inc +--source include/have_wsrep_provider.inc +--source include/have_partition.inc +# +# MDEV-33997: Assertion `((WSREP_PROVIDER_EXISTS_ && this->variables.wsrep_on) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()' failed in int THD::binlog_write_row(TABLE*, bool, const uchar*) +# +SET SESSION wsrep_osu_method=RSU; +SET autocommit=0; + +CREATE TABLE t (c INT) ENGINE=INNODB PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t VALUES (1); +INSERT INTO t SELECT 1 ; +COMMIT; +SELECT * FROM t; +DROP TABLE t; + +# +# MDEV-27296 : Assertion `((thd && (WSREP_PROVIDER_EXISTS_ && thd->variables.wsrep_on)) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()' failed +# Second test case +# +SET autocommit=1; +SET SESSION wsrep_osu_method=RSU; +CREATE TABLE t (c INT) ENGINE=INNODB PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t SELECT 1 ; +SELECT * FROM t; +DROP TABLE t; + +# +# We should not allow RSU for MyISAM +# +SET autocommit=1; +SET SESSION wsrep_osu_method=RSU; +CREATE TABLE t (c INT) ENGINE=MYISAM PARTITION BY KEY(c) PARTITIONS 2; +--error ER_NOT_SUPPORTED_YET +INSERT INTO t SELECT 1 ; +SELECT * FROM t; +DROP TABLE t; + +SET SESSION wsrep_osu_method=RSU; +SET autocommit=0; + +CREATE TABLE t (c INT) ENGINE=MYISAM PARTITION BY KEY(c) PARTITIONS 2; +INSERT INTO t VALUES (1); +--error ER_NOT_SUPPORTED_YET +INSERT INTO t SELECT 1 ; +COMMIT; +SELECT * FROM t; +DROP TABLE t; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index d8056fd4378..69a27ed6350 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5519,13 +5519,15 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) #ifdef WITH_WSREP if (WSREP(thd)) { - WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d " + WSREP_WARN("BF applier thread=%lu failed to open_and_lock_tables for " + "%s, fatal: %d " "wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)", - thd->get_stmt_da()->sql_errno(), - thd->is_fatal_error, - thd->wsrep_cs().mode(), - thd->wsrep_trx().state(), - (long long) wsrep_thd_trx_seqno(thd)); + thd_get_thread_id(thd), + thd->get_stmt_da()->message(), + thd->is_fatal_error, + thd->wsrep_cs().mode(), + thd->wsrep_trx().state(), + wsrep_thd_trx_seqno(thd)); } #endif /* WITH_WSREP */ if (thd->is_error() && diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2d6c7621f7b..01fa466780e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4759,6 +4759,13 @@ mysql_execute_command(THD *thd) thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; } + /* Only TOI allowed to !InnoDB tables */ + if (!is_innodb && wsrep_OSU_method_get(thd) != WSREP_OSU_TOI) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RSU on this table engine"); + break; + } + // For !InnoDB we start TOI if it is not yet started and hope for the best if (!is_innodb && !wsrep_toi) { From 9091afdc55ab2e6276256da59ce79e318abfb1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 15 Jun 2023 14:51:56 +0300 Subject: [PATCH 03/12] MDEV-31173 : Server crashes when setting wsrep_cluster_address after adding invalid value to wsrep_allowlist table Problem was that wsrep_schema tables were not marked as category information. Fix allows access to wsrep_schema tables even when node is detached. This is 10.4-10.9 version of fix. Signed-off-by: Julius Goryavsky --- .../r/galera_wsrep_schema_detached.result | 27 +++++++++++++ .../t/galera_wsrep_schema_detached.test | 39 +++++++++++++++++++ sql/table.cc | 23 +++++------ sql/wsrep_schema.cc | 12 +++++- sql/wsrep_schema.h | 12 +++--- 5 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_wsrep_schema_detached.result create mode 100644 mysql-test/suite/galera/t/galera_wsrep_schema_detached.test diff --git a/mysql-test/suite/galera/r/galera_wsrep_schema_detached.result b/mysql-test/suite/galera/r/galera_wsrep_schema_detached.result new file mode 100644 index 00000000000..493bf9d3cac --- /dev/null +++ b/mysql-test/suite/galera/r/galera_wsrep_schema_detached.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +call mtr.add_suppression("WSREP: async IST sender failed to serve.*"); +SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options; +connection node_2; +SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address; +SET GLOBAL WSREP_ON=0; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_cluster; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM mysql.wsrep_cluster_members; +EXPECT_2 +2 +connection node_1; +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true'; +connection node_2; +Killing server ... +connection node_1; +connection node_2; +connection node_1; +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=false'; diff --git a/mysql-test/suite/galera/t/galera_wsrep_schema_detached.test b/mysql-test/suite/galera/t/galera_wsrep_schema_detached.test new file mode 100644 index 00000000000..f67091a5fb9 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_wsrep_schema_detached.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--connection node_1 +call mtr.add_suppression("WSREP: async IST sender failed to serve.*"); +SET @wsrep_provider_options_orig = @@GLOBAL.wsrep_provider_options; + +--connection node_2 +SET @wsrep_cluster_address_orig = @@GLOBAL.wsrep_cluster_address; +SET GLOBAL WSREP_ON=0; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_1 FROM mysql.wsrep_cluster; +SELECT COUNT(*) AS EXPECT_2 FROM mysql.wsrep_cluster_members; + +--connection node_1 +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=true'; + +--connection node_2 +--source include/kill_galera.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 + +--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 + +SET GLOBAL wsrep_provider_options ='pc.ignore_sb=false'; + +# Cleanup +--source include/auto_increment_offset_restore.inc diff --git a/sql/table.cc b/sql/table.cc index 74b478cb816..f0020deb519 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -276,17 +276,6 @@ const char *fn_frm_ext(const char *name) TABLE_CATEGORY get_table_category(const Lex_ident_db &db, const Lex_ident_table &name) { -#ifdef WITH_WSREP - if (db.str && db.streq(MYSQL_SCHEMA_NAME)) - { - if (name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_STREAMING_TABLE)}) || - name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_CLUSTER_TABLE)}) || - name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_MEMBERS_TABLE)})) - { - return TABLE_CATEGORY_INFORMATION; - } - } -#endif /* WITH_WSREP */ if (is_infoschema_db(&db)) return TABLE_CATEGORY_INFORMATION; @@ -308,6 +297,18 @@ TABLE_CATEGORY get_table_category(const Lex_ident_db &db, return TABLE_CATEGORY_LOG; } +#ifdef WITH_WSREP + if (db.streq(WSREP_LEX_SCHEMA)) + { + if(name.streq(WSREP_LEX_STREAMING)) + return TABLE_CATEGORY_INFORMATION; + if (name.streq(WSREP_LEX_CLUSTER)) + return TABLE_CATEGORY_INFORMATION; + if (name.streq(WSREP_LEX_MEMBERS)) + return TABLE_CATEGORY_INFORMATION; + } +#endif /* WITH_WSREP */ + return TABLE_CATEGORY_USER; } diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index abc387cc15f..4cb839053c3 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2021 Codership Oy +/* Copyright (C) 2015-2023 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 @@ -35,6 +35,16 @@ #include #include +#define WSREP_SCHEMA "mysql" +#define WSREP_STREAMING_TABLE "wsrep_streaming_log" +#define WSREP_CLUSTER_TABLE "wsrep_cluster" +#define WSREP_MEMBERS_TABLE "wsrep_cluster_members" + +LEX_CSTRING WSREP_LEX_SCHEMA= {STRING_WITH_LEN(WSREP_SCHEMA)}; +LEX_CSTRING WSREP_LEX_STREAMING= {STRING_WITH_LEN(WSREP_STREAMING_TABLE)}; +LEX_CSTRING WSREP_LEX_CLUSTER= {STRING_WITH_LEN(WSREP_CLUSTER_TABLE)}; +LEX_CSTRING WSREP_LEX_MEMBERS= {STRING_WITH_LEN(WSREP_MEMBERS_TABLE)}; + const char* wsrep_sr_table_name_full= WSREP_SCHEMA "/" WSREP_STREAMING_TABLE; static const std::string wsrep_schema_str= WSREP_SCHEMA; diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h index 979b175481c..f0f79046768 100644 --- a/sql/wsrep_schema.h +++ b/sql/wsrep_schema.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2019 Codership Oy +/* Copyright (C) 2015-2023 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 @@ -33,11 +33,6 @@ struct TABLE_LIST; struct st_mysql_lex_string; typedef struct st_mysql_lex_string LEX_STRING; -#define WSREP_SCHEMA "mysql" -#define WSREP_STREAMING_TABLE "wsrep_streaming_log" -#define WSREP_CLUSTER_TABLE "wsrep_cluster" -#define WSREP_MEMBERS_TABLE "wsrep_cluster_members" - /** Name of the table in `wsrep_schema_str` used for storing streaming replication data. In an InnoDB full format, e.g. "database/tablename". */ extern const char* wsrep_sr_table_name_full; @@ -146,4 +141,9 @@ class Wsrep_schema extern Wsrep_schema* wsrep_schema; +extern LEX_CSTRING WSREP_LEX_SCHEMA; +extern LEX_CSTRING WSREP_LEX_STREAMING; +extern LEX_CSTRING WSREP_LEX_CLUSTER; +extern LEX_CSTRING WSREP_LEX_MEMBERS; + #endif /* !WSREP_SCHEMA_H */ From 74d716876537e244ae20a71874c9e670e0cfc930 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 30 Aug 2024 10:28:28 -0700 Subject: [PATCH 04/12] MDEV-25084 Assertion failure when moving equality from having to where This bug was fixed by the patch for bug MDEV-26402. Only a test case that failed before this patch was applied is added in this commit. --- mysql-test/main/having_cond_pushdown.result | 10 ++++++++++ mysql-test/main/having_cond_pushdown.test | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result index 3531c855781..c5877da4abd 100644 --- a/mysql-test/main/having_cond_pushdown.result +++ b/mysql-test/main/having_cond_pushdown.result @@ -5187,4 +5187,14 @@ HAVING (SELECT MAX(b) FROM t1) = a AND a > b; a b 2 1 DROP TABLE t1; +# +# MDEV-25084: Moving equality with constant right side +# from HAVING to WHERE +# (fixed by the patch for MDEV-26402) +# +CREATE TABLE t1 (a CHAR(3)) CHARSET=sjis; +INSERT INTO t1 VALUES ('foo'),('bar'); +SELECT LOAD_FILE('') AS f, a FROM t1 GROUP BY f, a HAVING f = a; +f a +DROP TABLE t1; End of 10.5 tests diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test index fd414e62a8c..51a346b0ad4 100644 --- a/mysql-test/main/having_cond_pushdown.test +++ b/mysql-test/main/having_cond_pushdown.test @@ -1584,4 +1584,16 @@ eval $q; DROP TABLE t1; + +--echo # +--echo # MDEV-25084: Moving equality with constant right side +--echo # from HAVING to WHERE +--echo # (fixed by the patch for MDEV-26402) +--echo # + +CREATE TABLE t1 (a CHAR(3)) CHARSET=sjis; +INSERT INTO t1 VALUES ('foo'),('bar'); +SELECT LOAD_FILE('') AS f, a FROM t1 GROUP BY f, a HAVING f = a; +DROP TABLE t1; + --echo End of 10.5 tests From b65bbb2fae419eef54cb79584e618b3ef5409aa2 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 30 Aug 2024 15:49:51 +0200 Subject: [PATCH 05/12] MDEV-34647: small refactoring after main fix --- sql/sql_parse.cc | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 01fa466780e..377d3051794 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4747,36 +4747,36 @@ mysql_execute_command(THD *thd) #ifdef WITH_WSREP if (wsrep && !first_table->view) { - bool is_innodb= first_table->table->file->partition_ht()->db_type == DB_TYPE_INNODB; - - // For consistency check inserted table needs to be InnoDB - if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) + const legacy_db_type db_type= first_table->table->file->partition_ht()->db_type; + // For InnoDB we don't need to worry about anything here: + if (db_type != DB_TYPE_INNODB) { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "Galera cluster does support consistency check only" - " for InnoDB tables."); - thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; - } - - /* Only TOI allowed to !InnoDB tables */ - if (!is_innodb && wsrep_OSU_method_get(thd) != WSREP_OSU_TOI) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RSU on this table engine"); - break; - } - - // For !InnoDB we start TOI if it is not yet started and hope for the best - if (!is_innodb && !wsrep_toi) - { - const legacy_db_type db_type= first_table->table->file->partition_ht()->db_type; - - /* Currently we support TOI for MyISAM only. */ - if (db_type == DB_TYPE_MYISAM && wsrep_replicate_myisam) - WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); + // For consistency check inserted table needs to be InnoDB + if (thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_UNSUPPORTED, + "Galera cluster does support consistency check only" + " for InnoDB tables."); + thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; + } + /* Only TOI allowed to !InnoDB tables */ + if (wsrep_OSU_method_get(thd) != WSREP_OSU_TOI) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RSU on this table engine"); + break; + } + // For !InnoDB we start TOI if it is not yet started and hope for the best + if (!wsrep_toi) + { + /* Currently we support TOI for MyISAM only. */ + if (db_type == DB_TYPE_MYISAM && wsrep_replicate_myisam) + WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); + } } } #endif /* WITH_WSREP */ + /* Only the INSERT table should be merged. Other will be handled by select. From 54a10a429334a9579558a5d284c510d6f8b5bc97 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Tue, 21 May 2024 12:40:19 +0300 Subject: [PATCH 06/12] MDEV-32363 Shut down Galera networking and logging on fatal signal When handling fatal signal, shut down Galera networking before printing out stack trace and writing core file. This is to achieve fail-silent semantics on crashes which may keep the process running for a long time, but not fully responding e.g. due to core dumping or symbol resolving. Also suppress all Galera/wsrep logging to avoid logging from background threads to garble crash information from signal handler. Notice that for fully fail-silent crash, Galera 26.4.19 is needed. Signed-off-by: Julius Goryavsky --- sql/signal_handler.cc | 8 ++++++++ sql/wsrep_server_service.cc | 9 ++++++++- sql/wsrep_server_service.h | 4 ++++ sql/wsrep_server_state.cc | 23 +++++++++++++++++++++++ sql/wsrep_server_state.h | 2 ++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 3d497e39289..002a4c244d1 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -25,6 +25,10 @@ #include "my_stacktrace.h" #include +#ifdef WITH_WSREP +#include "wsrep_server_state.h" +#endif /* WITH_WSREP */ + #ifdef __WIN__ #include #include @@ -221,6 +225,10 @@ extern "C" sig_handler handle_fatal_signal(int sig) "the equation.\n\n"); } +#ifdef WITH_WSREP + Wsrep_server_state::handle_fatal_signal(); +#endif /* WITH_WSREP */ + #ifdef HAVE_STACKTRACE thd= current_thd; diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index af2c3efd214..6184ba2df59 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -161,9 +161,16 @@ void Wsrep_server_service::bootstrap() wsrep_set_SE_checkpoint(wsrep::gtid::undefined(), wsrep_gtid_server.undefined()); } +static std::atomic suppress_logging{false}; +void wsrep_suppress_error_logging() { suppress_logging= true; } + void Wsrep_server_service::log_message(enum wsrep::log::level level, - const char* message) + const char *message) { + if (suppress_logging.load(std::memory_order_relaxed)) + { + return; + } switch (level) { case wsrep::log::debug: diff --git a/sql/wsrep_server_service.h b/sql/wsrep_server_service.h index 3a7da229cd4..9a1e148b55f 100644 --- a/sql/wsrep_server_service.h +++ b/sql/wsrep_server_service.h @@ -99,4 +99,8 @@ class Wsrep_storage_service; Wsrep_storage_service* wsrep_create_storage_service(THD *orig_thd, const char *ctx); +/** + Suppress all error logging from wsrep/Galera library. + */ +void wsrep_suppress_error_logging(); #endif /* WSREP_SERVER_SERVICE */ diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc index 6bc4eaf4d86..a936d9dd79d 100644 --- a/sql/wsrep_server_state.cc +++ b/sql/wsrep_server_state.cc @@ -18,6 +18,8 @@ #include "wsrep_server_state.h" #include "wsrep_binlog.h" /* init/deinit group commit */ +#include "my_stacktrace.h" /* my_safe_printf_stderr() */ + mysql_mutex_t LOCK_wsrep_server_state; mysql_cond_t COND_wsrep_server_state; @@ -82,3 +84,24 @@ void Wsrep_server_state::destroy() mysql_cond_destroy(&COND_wsrep_server_state); } } + +void Wsrep_server_state::handle_fatal_signal() +{ + if (m_instance) + { + /* Galera background threads are still running and the logging may be + relatively verbose in case of networking error. Silence all wsrep + logging before shutting down networking to avoid garbling signal + handler output. */ + my_safe_printf_stderr("WSREP: Suppressing further logging\n"); + wsrep_suppress_error_logging(); + + /* Shut down all communication with other nodes to fail silently. */ + my_safe_printf_stderr("WSREP: Shutting down network communications\n"); + if (m_instance->provider().set_node_isolation( + wsrep::provider::node_isolation::isolated)) { + my_safe_printf_stderr("WSREP: Galera library does not support node isolation\n"); + } + my_safe_printf_stderr("\n"); + } +} diff --git a/sql/wsrep_server_state.h b/sql/wsrep_server_state.h index 1ef937300f6..43a93fd5aef 100644 --- a/sql/wsrep_server_state.h +++ b/sql/wsrep_server_state.h @@ -56,6 +56,8 @@ public: return (get_provider().capabilities() & capability); } + static void handle_fatal_signal(); + private: Wsrep_server_state(const std::string& name, const std::string& incoming_address, From 69c6cb5dc4907c9133bb6f8077f35ad5eafb7549 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Sun, 19 May 2024 00:23:00 +0300 Subject: [PATCH 07/12] Fix recovering state GTID in case log file contains non-text bytes - use grep with -a option. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/include/galera_wsrep_recover.inc | 4 ++-- mysql-test/suite/galera/t/galera_pc_recovery.test | 4 ++-- mysql-test/suite/wsrep/t/wsrep-recover-step.inc | 2 +- scripts/galera_recovery.sh | 4 ++-- scripts/mysqld_safe.sh | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/galera/include/galera_wsrep_recover.inc b/mysql-test/suite/galera/include/galera_wsrep_recover.inc index aa2f0e2e777..efe803dcc9f 100644 --- a/mysql-test/suite/galera/include/galera_wsrep_recover.inc +++ b/mysql-test/suite/galera/include/galera_wsrep_recover.inc @@ -10,8 +10,8 @@ if (!$wsrep_recover_additional) --perl use strict; - my $wsrep_start_position_str = "grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'"; - my $wsrep_start_position = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + my $wsrep_start_position_str = "grep -a 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'"; + my $wsrep_start_position = `grep -a 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; chomp($wsrep_start_position); die if $wsrep_start_position eq ''; diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test index 16abe6fc9ba..0fd9c8ab3d9 100644 --- a/mysql-test/suite/galera/t/galera_pc_recovery.test +++ b/mysql-test/suite/galera/t/galera_pc_recovery.test @@ -38,10 +38,10 @@ SELECT COUNT(*) = 1 FROM t1; --perl use strict; - my $wsrep_start_position1 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.1.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + my $wsrep_start_position1 = `grep -a 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.1.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; chomp($wsrep_start_position1); - my $wsrep_start_position2 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.2.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + my $wsrep_start_position2 = `grep -a 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.2.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; chomp($wsrep_start_position2); die if $wsrep_start_position1 eq '' || $wsrep_start_position2 eq ''; diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-step.inc b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc index 22669438fe0..b131ac07641 100644 --- a/mysql-test/suite/wsrep/t/wsrep-recover-step.inc +++ b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc @@ -18,7 +18,7 @@ --perl use strict; - my $wsrep_start_position = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + my $wsrep_start_position = `grep -a 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; chomp($wsrep_start_position); die if $wsrep_start_position eq ''; open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die; diff --git a/scripts/galera_recovery.sh b/scripts/galera_recovery.sh index 9ff5e4e5f50..50aeb3a0b91 100644 --- a/scripts/galera_recovery.sh +++ b/scripts/galera_recovery.sh @@ -81,10 +81,10 @@ wsrep_recover_position() { # Parse server's error log for recovered position. The server prints # "..skipping position recovery.." if started without wsrep. - recovered_pos="$(grep 'WSREP: Recovered position:' $log_file)" + recovered_pos="$(grep -a 'WSREP: Recovered position:' $log_file)" if [ -z "$recovered_pos" ]; then - skipped="$(grep WSREP $log_file | grep 'skipping position recovery')" + skipped="$(grep -a WSREP $log_file | grep 'skipping position recovery')" if [ -z "$skipped" ]; then log "WSREP: Failed to recover position: '`cat $log_file`'" exit 1 diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index be115066f80..074840e992d 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -260,9 +260,9 @@ wsrep_recover_position() { exit 1 fi - local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" + local rp="$(grep -a 'WSREP: Recovered position:' $wr_logfile)" if [ -z "$rp" ]; then - local skipped="$(grep WSREP $wr_logfile | grep 'skipping position recovery')" + local skipped="$(grep -a WSREP $wr_logfile | grep 'skipping position recovery')" if [ -z "$skipped" ]; then log_error "WSREP: Failed to recover position: '`cat $wr_logfile`'" ret=1 From 7119149f8394d063f2f512a7fefc1d733f048867 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Sun, 19 May 2024 21:26:46 +0300 Subject: [PATCH 08/12] If donor loop receives unknown signal from the SST script it is an error condition (SST failure), so it should set error code before exiting. Signed-off-by: Julius Goryavsky --- sql/wsrep_sst.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 08a3d159e94..13500a83f43 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1840,6 +1840,8 @@ wait_signal: else { WSREP_WARN("Received unknown signal: '%s'", out); + /* since it is the end of the loop, we must set error code */ + err=-EINVAL; proc.wait(); } } From 731a5aba0b6eb465e82a3f243c5daaf735f7313f Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Sun, 19 May 2024 21:08:46 +0300 Subject: [PATCH 09/12] Use only MySQL code for TOI error vote For TOI events specifically we have a situation where in case of the same error different nodes may generate different messages. This may be for two reasons: - different locale setting between the current client session and server default (we can reasonably require server locales to be identical on all nodes, but user can change message locale for the session) - non-deterministic course of STATEMENT execution e.g. for ALTER TABLE On the other hand we may reasonably expect TOI event failures since they are executed after replication, so we must ensure that voting is consistent. For that purpose error codes should be sufficiently unique and deterministic for TOI event failures as DDLs normally deal with a single object, so we can merely use MySQL error codes to vote on. Notice that this problem does not happen with regular transactional writesets, since the originator node will always vote success and replica nodes are assumed to have the same global locale setting. As such different error messages indicate different errors even if the error code is the same (e.g. ER_DUP_KEY can happen on different rows tables). Use only MySQL error code (without the error message) for error voting in case of TOI event failure. Signed-off-by: Julius Goryavsky --- .../suite/galera_3nodes/r/galera_toi_vote.result | 3 ++- .../suite/galera_3nodes/t/galera_toi_vote.test | 3 +++ sql/wsrep_applier.cc | 16 +++++++++++++--- sql/wsrep_applier.h | 16 +++++++++++++++- sql/wsrep_high_priority_service.cc | 11 ++++++----- sql/wsrep_mysqld.cc | 5 ++++- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/galera_3nodes/r/galera_toi_vote.result b/mysql-test/suite/galera_3nodes/r/galera_toi_vote.result index d8d3abe40e9..345fa92c13d 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_toi_vote.result +++ b/mysql-test/suite/galera_3nodes/r/galera_toi_vote.result @@ -7,8 +7,9 @@ connection node_3; SET SESSION wsrep_on=OFF; DROP SCHEMA test; connection node_1; +SET SESSION lc_messages='fr_FR'; CREATE SCHEMA test; -ERROR HY000: Can't create database 'test'; database exists +ERROR HY000: Ne peut créer la base 'test'; elle existe déjà connection node_1; SET SESSION wsrep_sync_wait=0; connection node_2; diff --git a/mysql-test/suite/galera_3nodes/t/galera_toi_vote.test b/mysql-test/suite/galera_3nodes/t/galera_toi_vote.test index 6bc87cf8874..bd53c510cd4 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_toi_vote.test +++ b/mysql-test/suite/galera_3nodes/t/galera_toi_vote.test @@ -24,6 +24,9 @@ DROP SCHEMA test; # This should fail on nodes 1 and 2 and succeed on node 3 --connection node_1 +# Make error message on source node different by changing locale +# It should still agree with node 2 +SET SESSION lc_messages='fr_FR'; --error ER_DB_CREATE_EXISTS CREATE SCHEMA test; diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index 513e17b3045..0ec8e6e7f47 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -82,7 +82,9 @@ wsrep_get_apply_format(THD* thd) return thd->wsrep_rgi->rli->relay_log.description_event_for_exec; } -void wsrep_store_error(const THD* const thd, wsrep::mutable_buffer& dst) +void wsrep_store_error(const THD* const thd, + wsrep::mutable_buffer& dst, + bool const include_msg) { Diagnostics_area::Sql_condition_iterator it= thd->get_stmt_da()->sql_conditions(); @@ -100,8 +102,16 @@ void wsrep_store_error(const THD* const thd, wsrep::mutable_buffer& dst) uint const err_code= cond->get_sql_errno(); const char* const err_str= cond->get_message_text(); - slider+= my_snprintf(slider, buf_end - slider, " %s, Error_code: %d;", - err_str, err_code); + if (include_msg) + { + slider+= snprintf(slider, buf_end - slider, " %s, Error_code: %d;", + err_str, err_code); + } + else + { + slider+= snprintf(slider, buf_end - slider, " Error_code: %d;", + err_code); + } } if (slider != dst.data()) diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h index fefca306a70..e633b1b9bf2 100644 --- a/sql/wsrep_applier.h +++ b/sql/wsrep_applier.h @@ -35,7 +35,21 @@ int wsrep_apply_events(THD* thd, #define WSREP_ERR_FAILED 6 // Operation failed for some internal reason #define WSREP_ERR_ABORTED 7 // Operation was aborted externally -void wsrep_store_error(const THD* thd, wsrep::mutable_buffer& buf); +/* Loops over THD diagnostic area and concatenates all error messages + * and error codes to a single continuous buffer to create a unique + * but consistent failure signature which provider can use for voting + * between the nodes in the cluster. + * + * @param thd THD context + * @param dst buffer to store the signature + * @param include_msg whether to use MySQL error message in addition to + * MySQL error code. Note that in the case of a TOI + * operation the message may be not consistent between + * the nodes e.g. due to a different client locale setting + * and should be omitted */ +void wsrep_store_error(const THD* thd, + wsrep::mutable_buffer& buf, + bool include_msg); class Format_description_log_event; void wsrep_set_apply_format(THD*, Format_description_log_event*); diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc index 7eb3f07849a..2c0e2e643fa 100644 --- a/sql/wsrep_high_priority_service.cc +++ b/sql/wsrep_high_priority_service.cc @@ -123,14 +123,15 @@ static void wsrep_setup_uk_and_fk_checks(THD* thd) static int apply_events(THD* thd, Relay_log_info* rli, const wsrep::const_buffer& data, - wsrep::mutable_buffer& err) + wsrep::mutable_buffer& err, + bool const include_msg) { int const ret= wsrep_apply_events(thd, rli, data.data(), data.size()); if (ret || wsrep_thd_has_ignored_error(thd)) { if (ret) { - wsrep_store_error(thd, err); + wsrep_store_error(thd, err, include_msg); } wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); } @@ -427,7 +428,7 @@ int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta, #endif thd->set_time(); - int ret= apply_events(thd, m_rli, data, err); + int ret= apply_events(thd, m_rli, data, err, false); wsrep_thd_set_ignored_error(thd, false); trans_commit(thd); @@ -595,7 +596,7 @@ int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, #endif /* ENABLED_DEBUG_SYNC */ wsrep_setup_uk_and_fk_checks(thd); - int ret= apply_events(thd, m_rli, data, err); + int ret= apply_events(thd, m_rli, data, err, true); thd->close_temporary_tables(); if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) @@ -764,7 +765,7 @@ int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta, ws_meta, thd->wsrep_sr().fragments()); } - ret= ret || apply_events(thd, m_rli, data, err); + ret= ret || apply_events(thd, m_rli, data, err, true); thd->close_temporary_tables(); if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) { diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index e584c2cc144..6bb879a0367 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2489,7 +2489,10 @@ static void wsrep_TOI_end(THD *thd) { if (thd->is_error() && !wsrep_must_ignore_error(thd)) { - wsrep_store_error(thd, err); + /* use only error code, for the message can be inconsistent + * between the nodes due to differing lc_message settings + * in client session and server applier thread */ + wsrep_store_error(thd, err, false); } int const ret= client_state.leave_toi_local(err); From 83196a7b2398ed3caa52a04e09b656828ad64804 Mon Sep 17 00:00:00 2001 From: Alexey Yurchenko Date: Sun, 19 May 2024 22:09:18 +0300 Subject: [PATCH 10/12] Add a basic MTR test for DDL error voting to ensure that all DDLs generate consistent error messages, Signed-off-by: Julius Goryavsky --- .../suite/galera/r/galera_vote_ddl.result | 70 +++++++++++++++++++ mysql-test/suite/galera/t/galera_vote_ddl.inc | 54 ++++++++++++++ .../suite/galera/t/galera_vote_ddl.test | 34 +++++++++ 3 files changed, 158 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_vote_ddl.result create mode 100644 mysql-test/suite/galera/t/galera_vote_ddl.inc create mode 100644 mysql-test/suite/galera/t/galera_vote_ddl.test diff --git a/mysql-test/suite/galera/r/galera_vote_ddl.result b/mysql-test/suite/galera/r/galera_vote_ddl.result new file mode 100644 index 00000000000..bc5d99256e5 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_vote_ddl.result @@ -0,0 +1,70 @@ +connection node_2; +connection node_1; +connection node_1; +SET @@global.wsrep_ignore_apply_errors = 7; +connection node_2; +SET @@global.wsrep_ignore_apply_errors = 7; +connection node_1; +CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY); +connection node_1; +DROP TABLE nonexistent; +ERROR 42S02: Unknown table 'test.nonexistent' +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +TRUNCATE TABLE nonexistent; +ERROR 42S02: Table 'test.nonexistent' doesn't exist +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +CREATE TABLE nonexistent.t1 (s INT); +ERROR 42000: Unknown database 'nonexistent' +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +CREATE TABLE t1 (s INT); +ERROR 42S01: Table 't1' already exists +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +ALTER TABLE nonexistent ADD COLUMN (c INT); +ERROR 42S02: Table 'test.nonexistent' doesn't exist +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +DROP TABLE t1; +connection node_1; +SET @@global.wsrep_ignore_apply_errors = 0; +connection node_2; +SET @@global.wsrep_ignore_apply_errors = 0; +connection node_1; +CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY); +connection node_1; +DROP TABLE nonexistent; +ERROR 42S02: Unknown table 'test.nonexistent' +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +TRUNCATE TABLE nonexistent; +ERROR 42S02: Table 'test.nonexistent' doesn't exist +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +CREATE TABLE nonexistent.t1 (s INT); +ERROR 42000: Unknown database 'nonexistent' +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +CREATE TABLE t1 (s INT); +ERROR 42S01: Table 't1' already exists +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +connection node_1; +ALTER TABLE nonexistent ADD COLUMN (c INT); +ERROR 42S02: Table 'test.nonexistent' doesn't exist +INSERT INTO t1 VALUES (DEFAULT); +connection node_2; +DROP TABLE t1; +connection node_1; +SET @@global.wsrep_ignore_apply_errors = 7; +connection node_2; +SET @@global.wsrep_ignore_apply_errors = 7; diff --git a/mysql-test/suite/galera/t/galera_vote_ddl.inc b/mysql-test/suite/galera/t/galera_vote_ddl.inc new file mode 100644 index 00000000000..80a543fb886 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_vote_ddl.inc @@ -0,0 +1,54 @@ +--connection node_1 +CREATE TABLE t1 (pk INT AUTO_INCREMENT PRIMARY KEY); + +--connection node_1 +--error 1051 +DROP TABLE nonexistent; + +# Verify cluster is intact +INSERT INTO t1 VALUES (DEFAULT); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--error 1146 +TRUNCATE TABLE nonexistent; + +# Verify cluster is intact +INSERT INTO t1 VALUES (DEFAULT); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 2 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--error 1049 +CREATE TABLE nonexistent.t1 (s INT); + +# Verify cluster is intact +INSERT INTO t1 VALUES (DEFAULT); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--error 1050 +CREATE TABLE t1 (s INT); + +# Verify cluster is intact +INSERT INTO t1 VALUES (DEFAULT); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 4 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +--error 1146 +ALTER TABLE nonexistent ADD COLUMN (c INT); + +# Verify cluster is intact +INSERT INTO t1 VALUES (DEFAULT); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_vote_ddl.test b/mysql-test/suite/galera/t/galera_vote_ddl.test new file mode 100644 index 00000000000..9db6e612e7e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_vote_ddl.test @@ -0,0 +1,34 @@ +# +# Test voting on identical DDL errors (error messages should match) +# + +--source include/galera_cluster.inc +--source include/have_binlog_format_row.inc + +# +# 1. Ignore all DDL errors (avoids voting) +# +--connection node_1 +--let $wsrep_ignore_apply_errors_saved1 = `SELECT @@global.wsrep_ignore_apply_errors` +SET @@global.wsrep_ignore_apply_errors = 7; +--connection node_2 +--let $wsrep_ignore_apply_errors_saved2 = `SELECT @@global.wsrep_ignore_apply_errors` +SET @@global.wsrep_ignore_apply_errors = 7; + +--source galera_vote_ddl.inc + +# +# 2. Don't ignore any errors (forces voting) +# +--connection node_1 +SET @@global.wsrep_ignore_apply_errors = 0; +--connection node_2 +SET @@global.wsrep_ignore_apply_errors = 0; + +--source galera_vote_ddl.inc + +--connection node_1 +--eval SET @@global.wsrep_ignore_apply_errors = $wsrep_ignore_apply_errors_saved1 + +--connection node_2 +--eval SET @@global.wsrep_ignore_apply_errors = $wsrep_ignore_apply_errors_saved2 From dd64f29d6bea6f36be9634edd5c2d27f2205ca33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 12 Apr 2024 11:24:42 +0300 Subject: [PATCH 11/12] MDEV-33897 : Galera test failure on galera_3nodes.galera_gtid_consistency Based on logs SST was started before donor reached Primaty state. Add wait_conditions to make sure that nodes reach Primary state before starting next node. Signed-off-by: Julius Goryavsky --- .../r/galera_gtid_consistency.result | 33 +++++++------- .../t/galera_gtid_consistency.cnf | 35 ++++++--------- .../t/galera_gtid_consistency.test | 44 ++++++++++++++++--- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result b/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result index ffc5ec0627a..91ff0342b8d 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result +++ b/mysql-test/suite/galera_3nodes/r/galera_gtid_consistency.result @@ -1,6 +1,9 @@ connection node_2; connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; set wsrep_sync_wait=0; connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; @@ -44,9 +47,9 @@ connection node_1b; connection node_1; connection node_3; connection node_1; -CALL insert_row('node1', 500); +CALL insert_row('node1', 100); connection node_3; -CALL insert_row('node3', 500); +CALL insert_row('node3', 100); CREATE TABLE t2(i int primary key) engine=innodb; connection node_2; # Restart node_2 @@ -60,7 +63,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2503 +gtid_binlog_pos 1111-1-1703 connection node_2; # GTID in node2 show variables like 'wsrep_gtid_domain_id'; @@ -68,7 +71,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2503 +gtid_binlog_pos 1111-1-1703 connection node_3; # GTID in node3 show variables like 'wsrep_gtid_domain_id'; @@ -76,7 +79,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2503 +gtid_binlog_pos 1111-1-1703 # Shutdown node_3 connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; @@ -98,7 +101,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2554 +gtid_binlog_pos 1111-1-1754 connection node_2; # GTID in node2 show variables like 'wsrep_gtid_domain_id'; @@ -106,7 +109,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2554 +gtid_binlog_pos 1111-1-1754 connection node_3; # GTID in node3 show variables like 'wsrep_gtid_domain_id'; @@ -114,7 +117,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2554 +gtid_binlog_pos 1111-1-1754 # One by one shutdown all nodes connection node_3; # shutdown node_3 @@ -132,7 +135,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2554 +gtid_binlog_pos 1111-1-1754 ANALYZE TABLE t2; Table Op Msg_type Msg_text test.t2 analyze status Engine-independent statistics collected @@ -163,7 +166,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2756 +gtid_binlog_pos 1111-1-1956 connection node_2; node2 GTID show variables like 'wsrep_gtid_domain_id'; @@ -171,7 +174,7 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2756 +gtid_binlog_pos 1111-1-1956 connection node_3; node3 GTID show variables like 'wsrep_gtid_domain_id'; @@ -179,22 +182,22 @@ Variable_name Value wsrep_gtid_domain_id 1111 show variables like '%gtid_binlog_pos%'; Variable_name Value -gtid_binlog_pos 1111-1-2756 +gtid_binlog_pos 1111-1-1956 connection node_1; table size in node1 SELECT COUNT(*) FROM t1; COUNT(*) -2750 +1950 connection node_2; table size in node2 SELECT COUNT(*) FROM t1; COUNT(*) -2750 +1950 connection node_3; table size in node3 SELECT COUNT(*) FROM t1; COUNT(*) -2750 +1950 connection node_2; call mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node"); call mtr.add_suppression("Sending JOIN failed: "); diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf index c27490faf36..c0acbe58ad3 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.cnf @@ -1,38 +1,31 @@ !include ../galera_3nodes.cnf +[mysqld] +loose-galera-gtid-consistency=1 +wsrep_sst_auth="root:" +wsrep_sst_method=mariabackup +log_slave_updates=ON +log_bin=mariadb-bin-log +binlog-format=row +wsrep-gtid-mode=ON +wsrep-debug=1 +gtid-strict-mode=1 + [mysqld.1] wsrep-node-name="node1" -wsrep_gtid_domain_id=1111 gtid_domain_id=2 server_id=10999 -wsrep_sst_auth="root:" -wsrep_sst_method=mariabackup -log_slave_updates=ON -log_bin=mariadb-bin-log -binlog-format=row -wsrep-gtid-mode=ON +wsrep_gtid_domain_id=1111 [mysqld.2] wsrep-node-name="node2" -wsrep_gtid_domain_id=1112 gtid_domain_id=3 -wsrep_sst_auth="root:" -wsrep_sst_method=mariabackup -log_slave_updates=ON -log_bin=mariadb-bin-log -binlog-format=row -wsrep-gtid-mode=ON +wsrep_gtid_domain_id=1112 [mysqld.3] wsrep-node-name="node3" -wsrep_gtid_domain_id=1113 gtid_domain_id=4 -wsrep_sst_auth="root:" -wsrep_sst_method=mariabackup -log_slave_updates=ON -log_bin=mariadb-bin-log -binlog-format=row -wsrep-gtid-mode=ON +wsrep_gtid_domain_id=1113 [sst] transferfmt=@ENV.MTR_GALERA_TFMT diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test index f00972b0461..6a160720398 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_consistency.test @@ -13,6 +13,13 @@ # from the bootstrap node (node_1), and use it # --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +# 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 + --connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 set wsrep_sync_wait=0; --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 @@ -98,10 +105,10 @@ show variables like '%gtid_binlog_pos%'; # while node 2 is absent # --connection node_1 -CALL insert_row('node1', 500); +CALL insert_row('node1', 100); --connection node_3 -CALL insert_row('node3', 500); +CALL insert_row('node3', 100); CREATE TABLE t2(i int primary key) engine=innodb; @@ -225,12 +232,19 @@ show variables like '%gtid_binlog_pos%'; # bootstap cluster in order node1 - node2 - node3 # send some inserts and DDL after each node started # ---sleep 5 + --echo # Bootstrap from node_1 --connection node_1 --let $restart_parameters = --wsrep_new_cluster --source include/start_mysqld.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment' +--source include/wait_condition.inc + show variables like 'wsrep_gtid_domain_id'; show variables like '%gtid_binlog_pos%'; @@ -243,6 +257,13 @@ ANALYZE TABLE t2; --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --source include/start_mysqld.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment' +--source include/wait_condition.inc + # # connection node_1b may not be functional anymore, after node was # shutdown, open node_1c for controlling node 1 state @@ -265,6 +286,14 @@ ALTER TABLE t2 ADD COLUMN (k int); --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect --source include/start_mysqld.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment' +--source include/wait_condition.inc + + --connection node_1c --echo # wait until all nodes are back in cluster --let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; @@ -335,13 +364,18 @@ DROP TABLE t2; DROP TABLE t3; --connection node_3 ---let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't3' --source include/wait_condition.inc --connection node_2 ---let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't3' --source include/wait_condition.inc +# Restore original auto_increment_offset values. +--let $galera_cluster_size=3 +--source ../galera/include/auto_increment_offset_restore.inc + --disconnect node_3 --disconnect node_2b --disconnect node_1b --disconnect node_1c + From 7e748d075b7dc8aef36b1155cc43253d6a8a8ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 30 Aug 2024 08:32:10 +0300 Subject: [PATCH 12/12] MDEV-34841 : Enable working Galera tests * Fixes galera.galera_bf_kill_debug test case. * Enable galera_ssl_upgrade, galera_ssl_reload, galera_pc_bootstrap * Add MDEV to disabled tests that miss it Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/t/galera_ssl_upgrade.cnf | 4 ++++ mysql-test/suite/galera/t/galera_ssl_upgrade.test | 2 ++ mysql-test/suite/galera_3nodes/disabled.def | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.cnf b/mysql-test/suite/galera/t/galera_ssl_upgrade.cnf index 2954ae0f4cb..7c495102564 100644 --- a/mysql-test/suite/galera/t/galera_ssl_upgrade.cnf +++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.cnf @@ -1,5 +1,9 @@ !include ../galera_2nodes.cnf +[mysqld] +loose-galera-ssl-upgrade=1 +wsrep-debug=1 + [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;socket.ssl=yes;socket.ssl_cert=@ENV.MYSQL_TEST_DIR/std_data/galera-cert.pem;socket.ssl_key=@ENV.MYSQL_TEST_DIR/std_data/galera-key.pem' diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.test b/mysql-test/suite/galera/t/galera_ssl_upgrade.test index c09615527fd..78897ffd738 100644 --- a/mysql-test/suite/galera/t/galera_ssl_upgrade.test +++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.test @@ -7,6 +7,8 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_ssl_communication.inc +--source include/have_openssl.inc +--source include/force_restart.inc # Save original auto_increment_offset values. --let $node_1=node_1 diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index b7f0d8da8c1..c52df019c65 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -11,5 +11,6 @@ ############################################################################## galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed -galera_pc_bootstrap : temporarily disabled at the request of Codership -galera_ipv6_mariabackup_section : temporarily disabled at the request of Codership +galera_ipv6_rsync : MDEV-34842 Can't connect to server on '::1' (115) +galera_ipv6_rsync_section : MDEV-34842 Can't connect to server on '::1' (115) +galera_ipv6_mariabackup_section : MDEV-34842 Can't connect to server on '::1' (115)