From 8101af68fac5121cc2c44583c77c12f4f7318599 Mon Sep 17 00:00:00 2001 From: Sergei Krivonos Date: Sun, 14 Nov 2021 06:11:12 +0200 Subject: [PATCH 1/7] MDEV-27036: allow Json_writer_[array|object] from Json_writer --- sql/my_json_writer.h | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index 7d209501a87..0bd1e550439 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -367,14 +367,24 @@ protected: */ bool closed; -public: - explicit Json_writer_struct(THD *thd) + explicit Json_writer_struct(Json_writer *writer) + : my_writer(writer) { - my_writer= thd->opt_trace.get_current_json(); context.init(my_writer); closed= false; } - bool trace_started() + explicit Json_writer_struct(THD *thd) + : Json_writer_struct(thd->opt_trace.get_current_json()) + { + } + +public: + + virtual ~Json_writer_struct() + { + } + + bool trace_started() const { return my_writer != 0; } @@ -397,8 +407,8 @@ private: my_writer->add_member(name); } public: - explicit Json_writer_object(THD* thd, const char *str= nullptr) - : Json_writer_struct(thd) + explicit Json_writer_object(Json_writer* writer, const char *str= nullptr) + : Json_writer_struct(writer) { if (unlikely(my_writer)) { @@ -408,6 +418,11 @@ public: } } + explicit Json_writer_object(THD* thd, const char *str= nullptr) + : Json_writer_object(thd->opt_trace.get_current_json(), str) + { + } + ~Json_writer_object() { if (my_writer && !closed) @@ -567,17 +582,22 @@ public: class Json_writer_array : public Json_writer_struct { public: - Json_writer_array(THD *thd): Json_writer_struct(thd) + explicit Json_writer_array(Json_writer *writer, const char *str= nullptr) + : Json_writer_struct(writer) { if (unlikely(my_writer)) + { + if (str) + my_writer->add_member(str); my_writer->start_array(); + } } - Json_writer_array(THD *thd, const char *str) : Json_writer_struct(thd) + explicit Json_writer_array(THD *thd, const char *str= nullptr) + : Json_writer_array(thd->opt_trace.get_current_json(), str) { - if (unlikely(my_writer)) - my_writer->add_member(str).start_array(); } + ~Json_writer_array() { if (unlikely(my_writer && !closed)) @@ -586,6 +606,7 @@ public: closed= TRUE; } } + void end() { DBUG_ASSERT(!closed); From d4d71153dbeb896589d1d56c9746b4e0b54f110e Mon Sep 17 00:00:00 2001 From: Sergei Krivonos Date: Mon, 15 Nov 2021 00:42:26 +0200 Subject: [PATCH 2/7] Json_writer_object add integers --- sql/my_json_writer.h | 28 ++++++++++++++-------------- sql/opt_range.cc | 2 +- sql/sql_select.cc | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index 0bd1e550439..4b69ba70675 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -18,6 +18,9 @@ #include "my_base.h" #if !defined(NDEBUG) || defined(JSON_WRITER_UNIT_TEST) +#include +#include +#include #include #endif @@ -30,6 +33,8 @@ #define VALIDITY_ASSERT(x) DBUG_ASSERT(x) #endif +#include + class Opt_trace_stmt; class Opt_trace_context; class Json_writer; @@ -440,17 +445,22 @@ public: } return *this; } + Json_writer_object& add(const char *name, ulonglong value) { DBUG_ASSERT(!closed); if (my_writer) { add_member(name); - context.add_ll(static_cast(value)); + my_writer->add_ull(value); } return *this; } - Json_writer_object& add(const char *name, longlong value) + + template::value>::type + > + Json_writer_object& add(const char *name, IntT value) { DBUG_ASSERT(!closed); if (my_writer) @@ -460,6 +470,7 @@ public: } return *this; } + Json_writer_object& add(const char *name, double value) { DBUG_ASSERT(!closed); @@ -470,18 +481,7 @@ public: } return *this; } - #ifndef _WIN64 - Json_writer_object& add(const char *name, size_t value) - { - DBUG_ASSERT(!closed); - if (my_writer) - { - add_member(name); - context.add_ll(static_cast(value)); - } - return *this; - } - #endif + Json_writer_object& add(const char *name, const char *value) { DBUG_ASSERT(!closed); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 47bf8f1682f..5f13c9b3441 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6908,7 +6908,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info, DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost)); } else - trace_costs->add("disk_sweep_cost", static_cast(0)); + trace_costs->add("disk_sweep_cost", 0); DBUG_PRINT("info", ("New out_rows: %g", info->out_rows)); DBUG_PRINT("info", ("New cost: %g, %scovering", info->total_cost, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e12eeb6c815..3272f8b7f65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -396,7 +396,7 @@ static void trace_table_dependencies(THD *thd, { if (map & (1ULL << j)) { - trace_one_table.add("map_bit", static_cast(j)); + trace_one_table.add("map_bit", j); break; } } From f21a36d5e165d67934969ffec1858da80c43c8ad Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 23 Nov 2021 02:35:46 +0100 Subject: [PATCH 3/7] MDEV-26064: mariabackup SST fails when starting with --innodb-force-recovery If the server is started with the --innodb-force-recovery argument on the command line, then during SST this argument can be passed to mariabackup only at the --prepare stage, and accordingly it must be removed from the --mysqld-args list (and it is not should be passed to mariabackup otherwise). This commit fixes a flaw in the SST scripts and add a test that checks the ability to run the joiner node in a configuration that uses --innodb-force-recovery=1. --- ...sst_mariabackup_force_recovery,debug.rdiff | 192 +++++++ ...lera_sst_mariabackup_force_recovery.result | 520 ++++++++++++++++++ ..._sst_mariabackup_force_recovery-master.opt | 1 + .../galera_sst_mariabackup_force_recovery.cnf | 16 + ...galera_sst_mariabackup_force_recovery.test | 20 + scripts/wsrep_sst_common.sh | 10 + scripts/wsrep_sst_mariabackup.sh | 6 +- 7 files changed, 764 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery,debug.rdiff create mode 100644 mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery.result create mode 100644 mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery-master.opt create mode 100644 mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.cnf create mode 100644 mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.test diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery,debug.rdiff new file mode 100644 index 00000000000..bad8355b514 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery,debug.rdiff @@ -0,0 +1,192 @@ +--- r/galera_sst_mariabackup.result 2021-04-10 14:25:04.142716409 +0300 ++++ r/galera_sst_mariabackup,debug.reject 2021-04-10 14:53:30.033162191 +0300 +@@ -516,5 +516,189 @@ + 1 + DROP TABLE t1; + COMMIT; ++Performing State Transfer on a server that has been killed and restarted ++while a DDL was in progress on it ++connection node_1; ++CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 VALUES (1,'node1_committed_before'); ++INSERT INTO t1 VALUES (2,'node1_committed_before'); ++INSERT INTO t1 VALUES (3,'node1_committed_before'); ++INSERT INTO t1 VALUES (4,'node1_committed_before'); ++INSERT INTO t1 VALUES (5,'node1_committed_before'); ++connection node_2; ++START TRANSACTION; ++INSERT INTO t1 VALUES (6,'node2_committed_before'); ++INSERT INTO t1 VALUES (7,'node2_committed_before'); ++INSERT INTO t1 VALUES (8,'node2_committed_before'); ++INSERT INTO t1 VALUES (9,'node2_committed_before'); ++INSERT INTO t1 VALUES (10,'node2_committed_before'); ++COMMIT; ++SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; ++connection node_1; ++ALTER TABLE t1 ADD COLUMN f2 INTEGER; ++connection node_2; ++SET wsrep_sync_wait = 0; ++Killing server ... ++connection node_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (id,f1) VALUES (11,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (12,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (13,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (14,'node1_committed_during'); ++INSERT INTO t1 (id,f1) VALUES (15,'node1_committed_during'); ++COMMIT; ++START TRANSACTION; ++INSERT INTO t1 (id,f1) VALUES (16,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (17,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (18,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (19,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (20,'node1_to_be_committed_after'); ++connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (id,f1) VALUES (21,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (22,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (23,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (24,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (25,'node1_to_be_rollbacked_after'); ++connection node_2; ++Performing --wsrep-recover ... ++connection node_2; ++Starting server ... ++Using --wsrep-start-position when starting mysqld ... ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (id,f1) VALUES (26,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (27,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (28,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (29,'node2_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (30,'node2_committed_after'); ++COMMIT; ++connection node_1; ++INSERT INTO t1 (id,f1) VALUES (31,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (32,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (33,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (34,'node1_to_be_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (35,'node1_to_be_committed_after'); ++COMMIT; ++SET AUTOCOMMIT=OFF; ++START TRANSACTION; ++INSERT INTO t1 (id,f1) VALUES (36,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (37,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (38,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (39,'node1_committed_after'); ++INSERT INTO t1 (id,f1) VALUES (40,'node1_committed_after'); ++COMMIT; ++connection node_1a_galera_st_kill_slave_ddl; ++INSERT INTO t1 (id,f1) VALUES (41,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (42,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (43,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (44,'node1_to_be_rollbacked_after'); ++INSERT INTO t1 (id,f1) VALUES (45,'node1_to_be_rollbacked_after'); ++ROLLBACK; ++SET AUTOCOMMIT=ON; ++SET SESSION wsrep_sync_wait=15; ++SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++EXPECT_3 ++3 ++SELECT COUNT(*) AS EXPECT_35 FROM t1; ++EXPECT_35 ++35 ++SELECT * FROM t1; ++id f1 f2 ++1 node1_committed_before NULL ++2 node1_committed_before NULL ++3 node1_committed_before NULL ++4 node1_committed_before NULL ++5 node1_committed_before NULL ++6 node2_committed_before NULL ++7 node2_committed_before NULL ++8 node2_committed_before NULL ++9 node2_committed_before NULL ++10 node2_committed_before NULL ++11 node1_committed_during NULL ++12 node1_committed_during NULL ++13 node1_committed_during NULL ++14 node1_committed_during NULL ++15 node1_committed_during NULL ++16 node1_to_be_committed_after NULL ++17 node1_to_be_committed_after NULL ++18 node1_to_be_committed_after NULL ++19 node1_to_be_committed_after NULL ++20 node1_to_be_committed_after NULL ++26 node2_committed_after NULL ++27 node2_committed_after NULL ++28 node2_committed_after NULL ++29 node2_committed_after NULL ++30 node2_committed_after NULL ++31 node1_to_be_committed_after NULL ++32 node1_to_be_committed_after NULL ++33 node1_to_be_committed_after NULL ++34 node1_to_be_committed_after NULL ++35 node1_to_be_committed_after NULL ++36 node1_committed_after NULL ++37 node1_committed_after NULL ++38 node1_committed_after NULL ++39 node1_committed_after NULL ++40 node1_committed_after NULL ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++COMMIT; ++connection node_1; ++SET AUTOCOMMIT=ON; ++SET SESSION wsrep_sync_wait=15; ++SELECT COUNT(*) AS EXPECT_3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; ++EXPECT_3 ++3 ++SELECT COUNT(*) AS EXPECT_35 FROM t1; ++EXPECT_35 ++35 ++SELECT * FROM t1; ++id f1 f2 ++1 node1_committed_before NULL ++2 node1_committed_before NULL ++3 node1_committed_before NULL ++4 node1_committed_before NULL ++5 node1_committed_before NULL ++6 node2_committed_before NULL ++7 node2_committed_before NULL ++8 node2_committed_before NULL ++9 node2_committed_before NULL ++10 node2_committed_before NULL ++11 node1_committed_during NULL ++12 node1_committed_during NULL ++13 node1_committed_during NULL ++14 node1_committed_during NULL ++15 node1_committed_during NULL ++16 node1_to_be_committed_after NULL ++17 node1_to_be_committed_after NULL ++18 node1_to_be_committed_after NULL ++19 node1_to_be_committed_after NULL ++20 node1_to_be_committed_after NULL ++26 node2_committed_after NULL ++27 node2_committed_after NULL ++28 node2_committed_after NULL ++29 node2_committed_after NULL ++30 node2_committed_after NULL ++31 node1_to_be_committed_after NULL ++32 node1_to_be_committed_after NULL ++33 node1_to_be_committed_after NULL ++34 node1_to_be_committed_after NULL ++35 node1_to_be_committed_after NULL ++36 node1_committed_after NULL ++37 node1_committed_after NULL ++38 node1_committed_after NULL ++39 node1_committed_after NULL ++40 node1_committed_after NULL ++SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; ++COUNT(*) = 0 ++1 ++DROP TABLE t1; ++COMMIT; ++SET GLOBAL debug_dbug = $debug_orig; + disconnect node_2; + disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery.result new file mode 100644 index 00000000000..caf602c017c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_force_recovery.result @@ -0,0 +1,520 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +Performing State Transfer on a server that has been shut down cleanly and restarted +connection node_1; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); +connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); +COMMIT; +connection node_1a_galera_st_shutdown_slave; +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); +ROLLBACK; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_15 FROM t1; +EXPECT_15 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +Performing State Transfer on a server that starts from a clean var directory +This is accomplished by shutting down node #2 and removing its var directory before restarting it +connection node_1; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); +COMMIT; +Shutting down server ... +connection node_1; +Cleaning var directory ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); +connect node_1a_galera_st_clean_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); +connection node_2; +Starting server ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); +COMMIT; +connection node_1a_galera_st_clean_slave; +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (44,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); +ROLLBACK; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * from t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (id int not null primary key,f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1,'node1_committed_before'); +INSERT INTO t1 VALUES (2,'node1_committed_before'); +INSERT INTO t1 VALUES (3,'node1_committed_before'); +INSERT INTO t1 VALUES (4,'node1_committed_before'); +INSERT INTO t1 VALUES (5,'node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (6,'node2_committed_before'); +INSERT INTO t1 VALUES (7,'node2_committed_before'); +INSERT INTO t1 VALUES (8,'node2_committed_before'); +INSERT INTO t1 VALUES (9,'node2_committed_before'); +INSERT INTO t1 VALUES (10,'node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (11,'node1_committed_during'); +INSERT INTO t1 VALUES (12,'node1_committed_during'); +INSERT INTO t1 VALUES (13,'node1_committed_during'); +INSERT INTO t1 VALUES (14,'node1_committed_during'); +INSERT INTO t1 VALUES (15,'node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES (16,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (17,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (18,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (19,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (20,'node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (21,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (22,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (23,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (24,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (25,'node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (26,'node2_committed_after'); +INSERT INTO t1 VALUES (27,'node2_committed_after'); +INSERT INTO t1 VALUES (28,'node2_committed_after'); +INSERT INTO t1 VALUES (29,'node2_committed_after'); +INSERT INTO t1 VALUES (30,'node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES (31,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (32,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (33,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (34,'node1_to_be_committed_after'); +INSERT INTO t1 VALUES (35,'node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (36,'node1_committed_after'); +INSERT INTO t1 VALUES (37,'node1_committed_after'); +INSERT INTO t1 VALUES (38,'node1_committed_after'); +INSERT INTO t1 VALUES (39,'node1_committed_after'); +INSERT INTO t1 VALUES (40,'node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES (41,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (42,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (43,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (45,'node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES (46,'node1_to_be_rollbacked_after'); +ROLLBACK; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * FROM t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_sync_wait=15; +SELECT COUNT(*) AS EXPECT_35 FROM t1; +EXPECT_35 +35 +SELECT * FROM t1; +id f1 +1 node1_committed_before +2 node1_committed_before +3 node1_committed_before +4 node1_committed_before +5 node1_committed_before +6 node2_committed_before +7 node2_committed_before +8 node2_committed_before +9 node2_committed_before +10 node2_committed_before +11 node1_committed_during +12 node1_committed_during +13 node1_committed_during +14 node1_committed_during +15 node1_committed_during +16 node1_to_be_committed_after +17 node1_to_be_committed_after +18 node1_to_be_committed_after +19 node1_to_be_committed_after +20 node1_to_be_committed_after +26 node2_committed_after +27 node2_committed_after +28 node2_committed_after +29 node2_committed_after +30 node2_committed_after +31 node1_to_be_committed_after +32 node1_to_be_committed_after +33 node1_to_be_committed_after +34 node1_to_be_committed_after +35 node1_to_be_committed_after +36 node1_committed_after +37 node1_committed_after +38 node1_committed_after +39 node1_committed_after +40 node1_committed_after +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery-master.opt b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery-master.opt new file mode 100644 index 00000000000..b54b4fad444 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery-master.opt @@ -0,0 +1 @@ +--innodb-force-recovery=1 diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.cnf new file mode 100644 index 00000000000..857a4101406 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.cnf @@ -0,0 +1,16 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth="root:" +wsrep_debug=1 + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[sst] +transferfmt=@ENV.MTR_GALERA_TFMT +streamfmt=mbstream diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.test b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.test new file mode 100644 index 00000000000..bcb9ade3a25 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_force_recovery.test @@ -0,0 +1,20 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--source suite/galera/include/galera_st_shutdown_slave.inc +--source suite/galera/include/galera_st_clean_slave.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc + +# Restore original auto_increment_offset values. +--source include/auto_increment_offset_restore.inc + +--source include/galera_end.inc diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index a1293fcb749..b2c9539a02f 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -44,6 +44,7 @@ WSREP_SST_OPT_HOST_ESCAPED="" INNODB_DATA_HOME_DIR="${INNODB_DATA_HOME_DIR:-}" INNODB_LOG_GROUP_HOME="${INNODB_LOG_GROUP_HOME:-}" INNODB_UNDO_DIR="${INNODB_UNDO_DIR:-}" +INNODB_FORCE_RECOVERY="" INNOEXTRA="" while [ $# -gt 0 ]; do @@ -382,6 +383,14 @@ case "$1" in fi skip_mysqld_arg=1 ;; + '--innodb-force-recovery') + if [ -n "$value" ]; then + if [ "$value" -ne 0 ]; then + INNODB_FORCE_RECOVERY="$value" + fi + fi + skip_mysqld_arg=1 + ;; '--log-bin') if [ -z "$WSREP_SST_OPT_BINLOG" ]; then MYSQLD_OPT_LOG_BIN="$value" @@ -499,6 +508,7 @@ if [ -n "$WSREP_SST_OPT_BINLOG" ]; then fi fi +readonly INNODB_FORCE_RECOVERY readonly WSREP_SST_OPT_MYSQLD get_binlog() diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 3fe3bf5c206..fa6f48db776 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -951,7 +951,11 @@ setup_commands() if [ -n "$WSREP_SST_OPT_MYSQLD" ]; then mysqld_args="--mysqld-args $WSREP_SST_OPT_MYSQLD" fi - INNOAPPLY="$BACKUP_BIN --prepare $disver $iapts $INNOEXTRA --target-dir='$DATA' --datadir='$DATA' $mysqld_args $INNOAPPLY" + if [ -z "$INNODB_FORCE_RECOVERY" ]; then + INNOAPPLY="$BACKUP_BIN --prepare $disver $iapts $INNOEXTRA --target-dir='$DATA' --datadir='$DATA' $mysqld_args $INNOAPPLY" + else + INNOAPPLY="$BACKUP_BIN --prepare $disver $iapts $INNOEXTRA --innodb-force-recovery=$INNODB_FORCE_RECOVERY --target-dir='$DATA' --datadir='$DATA' $mysqld_args $INNOAPPLY" + fi INNOMOVE="$BACKUP_BIN $WSREP_SST_OPT_CONF --move-back $disver $impts --force-non-empty-directories --target-dir='$DATA' --datadir='${TDATA:-$DATA}' $INNOMOVE" INNOBACKUP="$BACKUP_BIN $WSREP_SST_OPT_CONF --backup $disver $iopts $tmpopts $INNOEXTRA --galera-info --stream=$sfmt --target-dir='$itmpdir' --datadir='$DATA' $mysqld_args $INNOBACKUP" } From 1ea7d5965012efba7b3abdc388a49c81157aacd1 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 16 Nov 2021 07:32:14 +0100 Subject: [PATCH 4/7] MDEV-26915: SST scripts do not take log_bin_index setting into account Currently, SST scripts assume that the filename specified in the --log-bin-index argument either does not contain an extension or uses the standard ".index" extension. Similar assumptions are used for the log_bin_index parameter read from the configuration file. This commit adds support for arbitrary extensions for the index file paths. --- .../suite/galera/r/galera_log_bin_ext.result | 80 + .../suite/galera/t/galera_log_bin_ext.cnf | 11 + .../suite/galera/t/galera_log_bin_ext.test | 1 + scripts/wsrep_sst_common.sh | 14 +- scripts/wsrep_sst_mariabackup.sh | 6 +- scripts/wsrep_sst_rsync.sh | 4 +- scripts/wsrep_sst_xtrabackup-v2.sh | 1405 +++++++++++++++++ 7 files changed, 1514 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_log_bin_ext.result create mode 100644 mysql-test/suite/galera/t/galera_log_bin_ext.cnf create mode 100644 mysql-test/suite/galera/t/galera_log_bin_ext.test create mode 100644 scripts/wsrep_sst_xtrabackup-v2.sh diff --git a/mysql-test/suite/galera/r/galera_log_bin_ext.result b/mysql-test/suite/galera/r/galera_log_bin_ext.result new file mode 100644 index 00000000000..58e13fb71a0 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_log_bin_ext.result @@ -0,0 +1,80 @@ +connection node_2; +connection node_1; +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; +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (id INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (1); +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t1) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t2 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t2) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t2 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t2) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER +connection node_2; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t1 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t1) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t2 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t2) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # BEGIN GTID #-#-# +hostname1-bin.000001 # Annotate_rows # # INSERT INTO t2 VALUES (1) +hostname1-bin.000001 # Table_map # # table_id: # (test.t2) +hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F +hostname1-bin.000001 # Xid # # COMMIT /* XID */ +hostname1-bin.000001 # Gtid # # GTID #-#-# +hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER +DROP TABLE t1; +DROP TABLE t2; +#cleanup +connection node_1; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; diff --git a/mysql-test/suite/galera/t/galera_log_bin_ext.cnf b/mysql-test/suite/galera/t/galera_log_bin_ext.cnf new file mode 100644 index 00000000000..012209610ea --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_bin_ext.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +log-bin = hostname1-bin +log-bin-index = hostname1.bdx +log-slave-updates + +[mysqld.2] +log-bin = hostname2-bin +log-bin-index = hostname2.bdx +log-slave-updates diff --git a/mysql-test/suite/galera/t/galera_log_bin_ext.test b/mysql-test/suite/galera/t/galera_log_bin_ext.test new file mode 100644 index 00000000000..923bd623a8a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_log_bin_ext.test @@ -0,0 +1 @@ +--source galera_log_bin.inc diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index b2c9539a02f..dbd639595df 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -230,7 +230,7 @@ case "$1" in shift ;; '--binlog-index'|'--log-bin-index') - readonly WSREP_SST_OPT_BINLOG_INDEX="$2" + WSREP_SST_OPT_BINLOG_INDEX="$2" shift ;; '--log-basename') @@ -453,7 +453,7 @@ if [ -n "${MYSQLD_OPT_LOG_BIN:-}" -a \ fi if [ -n "${MYSQLD_OPT_LOG_BIN_INDEX:-}" -a \ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then - readonly WSREP_SST_OPT_BINLOG_INDEX="$MYSQLD_OPT_LOG_BIN_INDEX" + WSREP_SST_OPT_BINLOG_INDEX="$MYSQLD_OPT_LOG_BIN_INDEX" fi if [ -n "${MYSQLD_OPT_DATADIR:-}" -a \ -z "$WSREP_SST_OPT_DATA" ]; then @@ -563,6 +563,16 @@ get_binlog() # is already defined above): readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_BINLOG.index" fi + else + # Remove all directories from the index file path: + local filename="${WSREP_SST_OPT_BINLOG_INDEX##*/}" + # Check if the index file name contains the extension: + if [ "${filename%.*}" = "$filename" ]; then + # Let's add the default extension (".index"): + readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_BINLOG_INDEX.index" + else + readonly WSREP_SST_OPT_BINLOG_INDEX + fi fi fi } diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index fa6f48db776..b429a9effd5 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -1249,8 +1249,8 @@ then cd "$binlog_dir" wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" rm -fv "$WSREP_SST_OPT_BINLOG".[0-9]* 1>&2 \+ || true - binlog_index="${WSREP_SST_OPT_BINLOG_INDEX%.index}.index" - [ -f "$binlog_index" ] && rm -fv "$binlog_index" 1>&2 \+ || true + [ -f "$WSREP_SST_OPT_BINLOG_INDEX" ] && \ + rm -fv "$WSREP_SST_OPT_BINLOG_INDEX" 1>&2 \+ || true cd "$OLD_PWD" fi @@ -1325,7 +1325,7 @@ then cd "$BINLOG_DIRNAME" for bfile in $(ls -1 "$BINLOG_FILENAME".[0-9]*); do - echo "$BINLOG_DIRNAME/$bfile" >> "${WSREP_SST_OPT_BINLOG_INDEX%.index}.index" + echo "$BINLOG_DIRNAME/$bfile" >> "$WSREP_SST_OPT_BINLOG_INDEX" done cd "$OLD_PWD" diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index ad9688011e1..29c9cd43470 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -392,7 +392,7 @@ EOF # Prepare binlog files cd "$BINLOG_DIRNAME" - binlog_files_full=$(tail -n $BINLOG_N_FILES "${WSREP_SST_OPT_BINLOG_INDEX%.index}.index") + binlog_files_full=$(tail -n $BINLOG_N_FILES "$WSREP_SST_OPT_BINLOG_INDEX") binlog_files="" for ii in $binlog_files_full @@ -732,7 +732,7 @@ EOF if [ -f "$BINLOG_TAR_FILE" ]; then cd "$BINLOG_DIRNAME" - binlog_index="${WSREP_SST_OPT_BINLOG_INDEX%.index}.index" + binlog_index="$WSREP_SST_OPT_BINLOG_INDEX" # Clean up old binlog files first rm -f "$BINLOG_FILENAME".[0-9]* diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh new file mode 100644 index 00000000000..73f15e79a4c --- /dev/null +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -0,0 +1,1405 @@ +#!/bin/bash -ue +# Copyright (C) 2017-2021 MariaDB +# Copyright (C) 2013 Percona Inc +# +# 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 +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to the +# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston +# MA 02110-1335 USA. + +# Documentation: +# http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html +# Make sure to read that before proceeding! + +. $(dirname "$0")/wsrep_sst_common +wsrep_check_datadir + +OS="$(uname)" +ealgo="" +eformat="" +ekey="" +ekeyfile="" +encrypt=0 +ecode=0 +ssyslog="" +ssystag="" +BACKUP_PID="" +tcert="" +tpath=0 +tpem="" +tkey="" +tmode="DISABLED" +sockopt="" +progress="" +ttime=0 +totime=0 +lsn="" +ecmd="" +rlimit="" +# Initially +stagemsg="$WSREP_SST_OPT_ROLE" +cpat="" +speciald=1 +ib_home_dir="" +ib_log_dir="" +ib_undo_dir="" + +sfmt="" +strmcmd="" +tfmt="" +tcmd="" +rebuild=0 +rebuildcmd="" +payload=0 +pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p'" +pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE" +STATDIR="" +uextra=0 +disver="" + +tmpopts="" +itmpdir="" +xtmpdir="" + +scomp="" +sdecomp="" + +ssl_dhparams="" + +compress='none' +compress_chunk="" +compress_threads="" + +backup_threads="" + +encrypt_threads="" +encrypt_chunk="" + +readonly SECRET_TAG="secret" + +sst_ver=-1 + +if [ -n "$(command -v pv)" ] && pv --help | grep -qw -- '-F'; then + pvopts="$pvopts $pvformat" +fi +pcmd="pv $pvopts" +declare -a RC + +BACKUP_BIN="$(command -v innobackupex)" +if [ ! -x "$BACKUP_BIN" ]; then + wsrep_log_error 'innobackupex binary not found in path' + exit 42 +fi + +DATA="$WSREP_SST_OPT_DATA" +INFO_FILE="xtrabackup_galera_info" +IST_FILE="xtrabackup_ist" +MAGIC_FILE="$DATA/$INFO_FILE" + +INNOAPPLYLOG="$DATA/innobackupex.prepare.log" +INNOMOVELOG="$DATA/innobackupex.move.log" +INNOBACKUPLOG="$DATA/innobackupex.backup.log" + +# Setting the path for ss and ip +export PATH="/usr/sbin:/sbin:$PATH" + +timeit() +{ + local stage="$1" + shift + local cmd="$@" + local x1 x2 took extcode + + if [ $ttime -eq 1 ]; then + x1=$(date +%s) + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + x2=$(date +%s) + took=$(( x2-x1 )) + wsrep_log_info "NOTE: $stage took $took seconds" + totime=$(( totime+took )) + else + wsrep_log_info "Evaluating $cmd" + eval "$cmd" + extcode=$? + fi + return $extcode +} + +get_keys() +{ + # $encrypt -eq 1 is for internal purposes only + if [ $encrypt -ge 2 -o $encrypt -eq -1 ]; then + return + fi + + if [ $encrypt -eq 0 ]; then + if [ -n "$ealgo" -o -n "$ekey" -o -n "$ekeyfile" ]; then + wsrep_log_error "Options for encryption are specified, " \ + "but encryption itself is disabled. SST may fail." + fi + return + fi + + if [ $sfmt = 'tar' ]; then + wsrep_log_info "NOTE: key-based encryption (encrypt=1) " \ + "cannot be enabled with tar format" + encrypt=-1 + return + fi + + wsrep_log_info "Key based encryption enabled in my.cnf - supported only from Xtrabackup 2.1.4" + + if [ -z "$ealgo" ]; then + wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" + exit 3 + fi + + if [ -z "$ekey" -a ! -r "$ekeyfile" ]; then + wsrep_log_error "FATAL: Either key must be specified " \ + "or keyfile must be readable" + exit 3 + fi + + if [ "$eformat" = 'openssl' ]; then + get_openssl + if [ -z "$OPENSSL_BINARY" ]; then + wsrep_log_error "If encryption using the openssl is enabled, " \ + "then you need to install openssl" + exit 2 + fi + ecmd="'$OPENSSL_BINARY' enc -$ealgo" + if "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-pbkdf2'; then + ecmd="$ecmd -pbkdf2" + elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-iter'; then + ecmd="$ecmd -iter 1" + elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-md'; then + ecmd="$ecmd -md sha256" + fi + if [ -z "$ekey" ]; then + ecmd="$ecmd -kfile '$ekeyfile'" + else + ecmd="$ecmd -k '$ekey'" + fi + elif [ "$eformat" = 'xbcrypt' ]; then + if [ -z "$(command -v xbcrypt)" ]; then + wsrep_log_error "If encryption using the xbcrypt is enabled, " \ + "then you need to install xbcrypt" + exit 2 + fi + wsrep_log_info "NOTE: xbcrypt-based encryption, " \ + "supported only from Xtrabackup 2.1.4" + if [ -z "$ekey" ]; then + ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key-file='$ekeyfile'" + else + wsrep_log_warning \ + "Using the 'encrypt-key' option causes the encryption key " \ + "to be set via the command-line and is considered insecure. " \ + "It is recommended to use the 'encrypt-key-file' option instead." + ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key='$ekey'" + fi + if [ -n "$encrypt_threads" ]; then + ecmd="$ecmd --encrypt-threads=$encrypt_threads" + fi + if [ -n "$encrypt_chunk" ]; then + ecmd="$ecmd --encrypt-chunk-size=$encrypt_chunk" + fi + else + wsrep_log_error "Unknown encryption format='$eformat'" + exit 2 + fi + + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + ecmd="$ecmd -d" + fi + + stagemsg="$stagemsg-XB-Encrypted" +} + +get_transfer() +{ + if [ $tfmt = 'nc' ]; then + wsrep_log_info "Using netcat as streamer" + wsrep_check_programs nc + tcmd="nc" + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + if nc -h 2>&1 | grep -q 'ncat'; then + wsrep_log_info "Using Ncat as streamer" + tcmd="$tcmd -l" + elif nc -h 2>&1 | grep -qw -- '-d'; then + wsrep_log_info "Using Debian netcat as streamer" + tcmd="$tcmd -dl" + if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then + # When host is not explicitly specified (when only the port + # is specified) netcat can only bind to an IPv4 address if + # the "-6" option is not explicitly specified: + tcmd="$tcmd -6" + fi + else + wsrep_log_info "Using traditional netcat as streamer" + tcmd="$tcmd -l -p" + fi + tcmd="$tcmd $SST_PORT" + else + # Check to see if netcat supports the '-N' flag. + # -N Shutdown the network socket after EOF on stdin + # If it supports the '-N' flag, then we need to use the '-N' + # flag, otherwise the transfer will stay open after the file + # transfer and cause the command to timeout. + # Older versions of netcat did not need this flag and will + # return an error if the flag is used. + if nc -h 2>&1 | grep -qw -- '-N'; then + tcmd="$tcmd -N" + wsrep_log_info "Using nc -N" + fi + # netcat doesn't understand [] around IPv6 address + if nc -h 2>&1 | grep -q ncat; then + wsrep_log_info "Using Ncat as streamer" + elif nc -h 2>&1 | grep -qw -- '-d'; then + wsrep_log_info "Using Debian netcat as streamer" + else + wsrep_log_info "Using traditional netcat as streamer" + tcmd="$tcmd -q0" + fi + tcmd="$tcmd $WSREP_SST_OPT_HOST_UNESCAPED $SST_PORT" + fi + else + tfmt='socat' + + wsrep_log_info "Using socat as streamer" + wsrep_check_programs socat + + if [ -n "$sockopt" ]; then + sockopt=$(trim_string "$sockopt" ',') + if [ -n "$sockopt" ]; then + sockopt=",$sockopt" + fi + fi + + # Add an option for ipv6 if needed: + if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then + # If sockopt contains 'pf=ip6' somewhere in the middle, + # this will not interfere with socat, but exclude the trivial + # cases when sockopt contains 'pf=ip6' as prefix or suffix: + if [ "$sockopt" = "${sockopt#,pf=ip6}" -a \ + "$sockopt" = "${sockopt%,pf=ip6}" ] + then + sockopt=",pf=ip6$sockopt" + fi + fi + + if [ $encrypt -lt 2 ]; then + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + tcmd="socat -u TCP-LISTEN:$SST_PORT,reuseaddr$sockopt stdio" + else + tcmd="socat -u stdio TCP:$REMOTEIP:$SST_PORT$sockopt" + fi + return + fi + + if ! socat -V | grep -q -F 'WITH_OPENSSL 1'; then + wsrep_log_error "******** FATAL ERROR ************************************************ " + wsrep_log_error "* Encryption requested, but socat is not OpenSSL enabled (encrypt=$encrypt) *" + wsrep_log_error "********************************************************************* " + exit 2 + fi + + local action='Decrypting' + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + tcmd="socat -u openssl-listen:$SST_PORT,reuseaddr" + else + tcmd="socat -u stdio openssl-connect:$REMOTEIP:$SST_PORT" + action='Encrypting' + fi + + if [ "${sockopt#*,dhparam=}" != "$sockopt" ]; then + if [ -z "$ssl_dhparams" ]; then + # Determine the socat version + SOCAT_VERSION=$(socat -V 2>&1 | grep -m1 -oe '[0-9]\.[0-9][\.0-9]*') + if [ -z "$SOCAT_VERSION" ]; then + wsrep_log_error "******** FATAL ERROR ******************" + wsrep_log_error "* Cannot determine the socat version. *" + wsrep_log_error "***************************************" + exit 2 + fi + if ! check_for_version "$SOCAT_VERSION" '1.7.3'; then + # socat versions < 1.7.3 will have 512-bit dhparams (too small) + # so create 2048-bit dhparams and send that as a parameter: + check_for_dhparams + fi + fi + if [ -n "$ssl_dhparams" ]; then + tcmd="$tcmd,dhparam='$ssl_dhparams'" + fi + fi + + CN_option=",commonname=''" + + if [ $encrypt -eq 2 ]; then + wsrep_log_info "Using openssl based encryption with socat: with crt and pem" + if [ -z "$tpem" -o -z "$tcert" ]; then + wsrep_log_error \ + "Both PEM file and CRT file (or path) are required" + exit 22 + fi + if [ ! -r "$tpem" -o ! -r "$tcert" ]; then + wsrep_log_error \ + "Both PEM file and CRT file (or path) must be readable" + exit 22 + fi + verify_ca_matches_cert "$tcert" "$tpem" $tpath + if [ $tpath -eq 0 ]; then + tcmd="$tcmd,cert='$tpem',cafile='$tcert'" + else + tcmd="$tcmd,cert='$tpem',capath='$tcert'" + fi + stagemsg="$stagemsg-OpenSSL-Encrypted-2" + wsrep_log_info "$action with cert=$tpem, ca=$tcert" + elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then + wsrep_log_info "Using openssl based encryption with socat: with key and crt" + if [ -z "$tpem" -o -z "$tkey" ]; then + wsrep_log_error "Both certificate file (or path) " \ + "and key file are required" + exit 22 + fi + if [ ! -r "$tpem" -o ! -r "$tkey" ]; then + wsrep_log_error "Both certificate file (or path) " \ + "and key file must be readable" + exit 22 + fi + verify_cert_matches_key "$tpem" "$tkey" + stagemsg="$stagemsg-OpenSSL-Encrypted-3" + if [ -z "$tcert" ]; then + if [ $encrypt -eq 4 ]; then + wsrep_log_error \ + "Peer certificate file (or path) required if encrypt=4" + exit 22 + fi + # no verification + CN_option="" + tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0" + wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0" + else + # CA verification + if [ ! -r "$tcert" ]; then + wsrep_log_error "Certificate file or path must be readable" + exit 22 + fi + verify_ca_matches_cert "$tcert" "$tpem" $tpath + if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then + CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'" + elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ] + then + CN_option=",commonname=''" + elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then + CN_option=',commonname=localhost' + else + CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'" + fi + if [ $tpath -eq 0 ]; then + tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'" + else + tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'" + fi + wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert" + fi + else + wsrep_log_info "Unknown encryption mode: encrypt=$encrypt" + exit 22 + fi + + tcmd="$tcmd$CN_option$sockopt" + + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + tcmd="$tcmd stdio" + fi + fi +} + +get_footprint() +{ + pushd "$WSREP_SST_OPT_DATA" 1>/dev/null + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c -s | awk 'END { print $1 }') + if [ "$compress" != 'none' ]; then + # QuickLZ has around 50% compression ratio + # When compression/compaction used, the progress is only an approximate. + payload=$(( payload*1/2 )) + fi + popd 1>/dev/null + pcmd="$pcmd -s $payload" + adjust_progress +} + +adjust_progress() +{ + if [ -z "$(command -v pv)" ]; then + wsrep_log_error "pv not found in path: $PATH" + wsrep_log_error "Disabling all progress/rate-limiting" + pcmd="" + rlimit="" + progress="" + return + fi + + if [ -n "$progress" -a "$progress" != '1' ]; then + if [ -e "$progress" ]; then + pcmd="$pcmd 2>>'$progress'" + else + pcmd="$pcmd 2>'$progress'" + fi + elif [ -z "$progress" -a -n "$rlimit" ]; then + # When rlimit is non-zero + pcmd="pv -q" + fi + + if [ -n "$rlimit" -a "$WSREP_SST_OPT_ROLE" = 'donor' ]; then + wsrep_log_info "Rate-limiting SST to $rlimit" + pcmd="$pcmd -L \$rlimit" + fi +} + +encgroups='--mysqld|sst|xtrabackup' + +check_server_ssl_config() +{ + # backward-compatible behavior: + tcert=$(parse_cnf 'sst' 'tca') + tpem=$(parse_cnf 'sst' 'tcert') + tkey=$(parse_cnf 'sst' 'tkey') + # reading new ssl configuration options: + local tcert2=$(parse_cnf "$encgroups" 'ssl-ca') + local tpem2=$(parse_cnf "$encgroups" 'ssl-cert') + local tkey2=$(parse_cnf "$encgroups" 'ssl-key') + # if there are no old options, then we take new ones: + if [ -z "$tcert" -a -z "$tpem" -a -z "$tkey" ]; then + tcert="$tcert2" + tpem="$tpem2" + tkey="$tkey2" + # checking for presence of the new-style SSL configuration: + elif [ -n "$tcert2" -o -n "$tpem2" -o -n "$tkey2" ]; then + if [ "$tcert" != "$tcert2" -o \ + "$tpem" != "$tpem2" -o \ + "$tkey" != "$tkey2" ] + then + wsrep_log_info "new ssl configuration options (ssl-ca, ssl-cert " \ + "and ssl-key) are ignored by SST due to presence " \ + "of the tca, tcert and/or tkey in the [sst] section" + fi + fi + if [ -n "$tcert" ]; then + tcert=$(trim_string "$tcert") + if [ "${tcert%/}" != "$tcert" ]; then + tpath=1 + fi + fi +} + +read_cnf() +{ + sfmt=$(parse_cnf sst streamfmt 'xbstream') + tfmt=$(parse_cnf sst transferfmt 'socat') + + encrypt=$(parse_cnf "$encgroups" 'encrypt' 0) + tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | tr [:lower:] [:upper:]) + + if [ $encrypt -eq 0 -o $encrypt -ge 2 ] + then + if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then + check_server_ssl_config + fi + if [ "$tmode" != 'DISABLED' ]; then + if [ 0 -eq $encrypt -a -n "$tpem" -a -n "$tkey" ] + then + encrypt=3 # enable cert/key SSL encyption + + # avoid CA verification if not set explicitly: + # nodes may happen to have different CA if self-generated + # zeroing up tcert does the trick + [ "${tmode#VERIFY}" != "$tmode" ] || tcert="" + fi + fi + elif [ $encrypt -eq 1 ]; then + ealgo=$(parse_cnf "$encgroups" 'encrypt-algo') + eformat=$(parse_cnf "$encgroups" 'encrypt-format' 'xbcrypt') + ekey=$(parse_cnf "$encgroups" 'encrypt-key') + # The keyfile should be read only when the key + # is not specified or empty: + if [ -z "$ekey" ]; then + ekeyfile=$(parse_cnf "$encgroups" 'encrypt-key-file') + fi + fi + + wsrep_log_info "SSL configuration: CA='$tcert', CERT='$tpem'," \ + "KEY='$tkey', MODE='$tmode', encrypt='$encrypt'" + + sockopt=$(parse_cnf sst sockopt "") + progress=$(parse_cnf sst progress "") + rebuild=$(parse_cnf sst rebuild 0) + ttime=$(parse_cnf sst time 0) + cpat='.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$' + [ "$OS" = 'FreeBSD' ] && cpat=$(echo "$cpat" | sed 's/\\|/|/g') + cpat=$(parse_cnf sst cpat "$cpat") + scomp=$(parse_cnf sst compressor "") + sdecomp=$(parse_cnf sst decompressor "") + + rlimit=$(parse_cnf sst rlimit "") + uextra=$(parse_cnf sst use-extra 0) + speciald=$(parse_cnf sst sst-special-dirs 1) + iopts=$(parse_cnf sst inno-backup-opts "") + iapts=$(parse_cnf sst inno-apply-opts "") + impts=$(parse_cnf sst inno-move-opts "") + stimeout=$(parse_cnf sst sst-initial-timeout 300) + ssyslog=$(parse_cnf sst sst-syslog 0) + ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") + ssystag="$ssystag-" + sstlogarchive=$(parse_cnf sst sst-log-archive 1) + sstlogarchivedir=$(parse_cnf sst sst-log-archive-dir '/tmp/sst_log_archive') + + if [ $speciald -eq 0 ]; then + wsrep_log_error "sst-special-dirs equal to 0 is not supported, falling back to 1" + speciald=1 + fi + + if [ $ssyslog -ne -1 ]; then + ssyslog=$(in_config 'mysqld_safe' 'syslog') + fi + + if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then + compress=$(parse_cnf "$encgroups" 'compress' 'none') + if [ "$compress" != 'none' ]; then + compress_chunk=$(parse_cnf "$encgroups" 'compress-chunk-size') + compress_threads=$(parse_cnf "$encgroups" 'compress-threads') + fi + fi + + backup_threads=$(parse_cnf "$encgroups" 'backup-threads') + + if [ "$eformat" = 'xbcrypt' ]; then + encrypt_threads=$(parse_cnf "$encgroups" 'encrypt-threads') + encrypt_chunk=$(parse_cnf "$encgroups" 'encrypt-chunk-size') + fi +} + +get_stream() +{ + if [ "$sfmt" = 'mbstream' -o "$sfmt" = 'xbstream' ]; then + STREAM_BIN=$(command -v "$sfmt") + if [ -z "$STREAM_BIN" ]; then + if [ "$sfmt" = 'xbstream' ]; then + STREAM_BIN="$(command -v mbstream)" + else + STREAM_BIN="$(command -v xbstream)" + fi + fi + if [ -z "$STREAM_BIN" ]; then + wsrep_log_error "Streaming with $sfmt, but $sfmt not found in path" + exit 42 + fi + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + strmcmd="'$STREAM_BIN' -x" + else + strmcmd="'$STREAM_BIN' -c '$INFO_FILE'" + fi + else + sfmt='tar' + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + strmcmd='tar xfi -' + else + strmcmd="tar cf - '$INFO_FILE'" + fi + fi + wsrep_log_info "Streaming with $sfmt" +} + +sig_joiner_cleanup() +{ + wsrep_log_error "Removing $MAGIC_FILE file due to signal" + [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" +} + +cleanup_at_exit() +{ + # Since this is invoked just after exit NNN + local estatus=$? + if [ $estatus -ne 0 ]; then + wsrep_log_error "Cleanup after exit with status:$estatus" + fi + + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + wsrep_log_info "Removing the sst_in_progress file" + wsrep_cleanup_progress_file + else + if [ -n "$BACKUP_PID" ]; then + if check_pid "$BACKUP_PID" 1; then + wsrep_log_error "xtrabackup process is still running. Killing..." + cleanup_pid $CHECK_PID "$BACKUP_PID" + fi + fi + [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" + fi + + if [ -n "$progress" -a -p "$progress" ]; then + wsrep_log_info "Cleaning up fifo file $progress" + rm -f "$progress" || true + fi + + wsrep_log_info "Cleaning up temporary directories" + + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then + if [ -n "$STATDIR" ]; then + [ -d "$STATDIR" ] && rm -rf "$STATDIR" + fi + else + [ -n "$xtmpdir" -a -d "$xtmpdir" ] && rm -rf "$xtmpdir" || true + [ -n "$itmpdir" -a -d "$itmpdir" ] && rm -rf "$itmpdir" || true + fi + + # Final cleanup + pgid=$(ps -o pgid= $$ | grep -o '[0-9]*') + + # This means no setsid done in mysqld. + # We don't want to kill mysqld here otherwise. + if [ $$ -eq $pgid ]; then + # This means a signal was delivered to the process. + # So, more cleanup. + if [ $estatus -ge 128 ]; then + kill -KILL -- -$$ || true + fi + fi + + exit $estatus +} + +setup_ports() +{ + SST_PORT="$WSREP_SST_OPT_PORT" + if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then + REMOTEIP="$WSREP_SST_OPT_HOST" + lsn="$WSREP_SST_OPT_LSN" + sst_ver="$WSREP_SST_OPT_SST_VER" + fi +} + +# +# Waits ~30 seconds for socat or nc to open the port and +# then reports ready, regardless of timeout. +# +wait_for_listen() +{ + local PORT="$1" + local ADDR="$2" + local MODULE="$3" + for i in {1..150}; do + if check_port "" "$PORT" 'socat|nc'; then + break + fi + sleep 0.2 + done + echo "ready $ADDR/$MODULE//$sst_ver" +} + +check_extra() +{ + local use_socket=1 + if [ $uextra -eq 1 ]; then + local thread_handling=$(parse_cnf '--mysqld' 'thread-handling') + if [ "$thread_handling" = 'pool-of-threads' ]; then + local eport=$(parse_cnf '--mysqld' 'extra-port') + if [ -n "$eport" ]; then + # Xtrabackup works only locally. + # Hence, setting host to 127.0.0.1 unconditionally: + wsrep_log_info "SST through extra_port $eport" + INNOEXTRA="$INNOEXTRA --host=127.0.0.1 --port=$eport" + use_socket=0 + else + wsrep_log_error "Extra port $eport null, failing" + exit 1 + fi + else + wsrep_log_info "Thread pool not set, ignore the option use_extra" + fi + fi + if [ $use_socket -eq 1 -a -n "$WSREP_SST_OPT_SOCKET" ]; then + INNOEXTRA="$INNOEXTRA --socket='$WSREP_SST_OPT_SOCKET'" + fi +} + +recv_joiner() +{ + local dir="$1" + local msg="$2" + local tmt=$3 + local checkf=$4 + local wait=$5 + + if [ ! -d "$dir" ]; then + # This indicates that IST is in progress + return + fi + + local ltcmd="$tcmd" + if [ $tmt -gt 0 ]; then + if [ -n "$(command -v timeout)" ]; then + if timeout --help | grep -qw -- '-k'; then + ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" + else + ltcmd="timeout -s9 $tmt $tcmd" + fi + fi + fi + + pushd "$dir" 1>/dev/null + set +e + + if [ $wait -ne 0 ]; then + wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" & + fi + + timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" + + set -e + popd 1>/dev/null + + if [ ${RC[0]} -eq 124 ]; then + wsrep_log_error "Possible timeout in receiving first data from " \ + "donor in gtid stage: exit codes: ${RC[@]}" + exit 32 + fi + + for ecode in "${RC[@]}"; do + if [ $ecode -ne 0 ]; then + wsrep_log_error "Error while getting data from donor node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done + + if [ $checkf -eq 1 ]; then + if [ ! -r "$MAGIC_FILE" ]; then + # this message should cause joiner to abort + wsrep_log_error "receiving process ended without creating " \ + "'$MAGIC_FILE'" + wsrep_log_info "Contents of datadir" + wsrep_log_info $(ls -l "$dir/"*) + exit 32 + fi + + # check donor supplied secret + SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) + if [ "$SECRET" != "$MY_SECRET" ]; then + wsrep_log_error "Donor does not know my secret!" + wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" + exit 32 + fi + + # remove secret from the magic file + grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" + mv "$MAGIC_FILE.new" "$MAGIC_FILE" + fi +} + +send_donor() +{ + local dir="$1" + local msg="$2" + + pushd "$dir" 1>/dev/null + set +e + timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + popd 1>/dev/null + + for ecode in "${RC[@]}"; do + if [ $ecode -ne 0 ]; then + wsrep_log_error "Error while sending data to joiner node: " \ + "exit codes: ${RC[@]}" + exit 32 + fi + done +} + +monitor_process() +{ + local sst_stream_pid=$1 + + while true ; do + if ! ps -p "$WSREP_SST_OPT_PARENT" >/dev/null 2>&1; then + wsrep_log_error "Parent mysqld process (PID: $WSREP_SST_OPT_PARENT) terminated unexpectedly." + kill -- -"$WSREP_SST_OPT_PARENT" + exit 32 + fi + if ! ps -p "$sst_stream_pid" >/dev/null 2>&1; then + break + fi + sleep 0.1 + done +} + +# check the version, we require XB-2.4 to ensure that we can pass the +# datadir via the command-line option +XB_REQUIRED_VERSION="2.3.5" + +XB_VERSION=`$BACKUP_BIN --version 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1` +if [[ -z "$XB_VERSION" ]]; then + wsrep_log_error "FATAL: Cannot determine the $BACKUP_BIN version. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" + exit 2 +fi + +if ! check_for_version "$XB_VERSION" "$XB_REQUIRED_VERSION"; then + wsrep_log_error "FATAL: The $BACKUP_BIN version is $XB_VERSION. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" + exit 2 +fi + +[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" + +if [ "$WSREP_SST_OPT_ROLE" != 'joiner' -a "$WSREP_SST_OPT_ROLE" != 'donor' ]; then + wsrep_log_error "Invalid role '$WSREP_SST_OPT_ROLE'" + exit 22 +fi + +read_cnf +setup_ports + +if "$BACKUP_BIN" --help 2>/dev/null | grep -qw -- '--version-check'; then + disver='--no-version-check' +fi + +# if no command line argument and INNODB_DATA_HOME_DIR environment variable +# is not set, try to get it from my.cnf: +if [ -z "$INNODB_DATA_HOME_DIR" ]; then + INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir') +fi + +OLD_PWD="$(pwd)" + +cd "$WSREP_SST_OPT_DATA" +if [ -n "$INNODB_DATA_HOME_DIR" ]; then + # handle both relative and absolute paths + [ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR" + cd "$INNODB_DATA_HOME_DIR" +fi +INNODB_DATA_HOME_DIR=$(pwd -P) + +cd "$OLD_PWD" + +if [ $ssyslog -eq 1 ]; then + if [ -n "$(command -v logger)" ]; then + wsrep_log_info "Logging all stderr of SST/xtrabackup to syslog" + + exec 2> >(logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE) + + wsrep_log_error() + { + logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" + } + + wsrep_log_info() + { + logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" + } + else + wsrep_log_error "logger not in path: $PATH. Ignoring" + fi + INNOAPPLY="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" + INNOMOVE="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" + INNOBACKUP="2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" +else + if [ $sstlogarchive -eq 1 ] + then + ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S.%N") + + if [ -n "$sstlogarchivedir" ]; then + if [ ! -d "$sstlogarchivedir" ]; then + mkdir -p "$sstlogarchivedir" + fi + fi + + if [ -e "$INNOAPPLYLOG" ] + then + if [ -n "$sstlogarchivedir" ] + then + newfile=$(basename "$INNOAPPLYLOG") + newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" + else + newfile="$INNOAPPLYLOG.$ARCHIVETIMESTAMP" + fi + wsrep_log_info "Moving '$INNOAPPLYLOG' to '$newfile'" + mv "$INNOAPPLYLOG" "$newfile" + gzip "$newfile" + fi + + if [ -e "$INNOMOVELOG" ] + then + if [ -n "$sstlogarchivedir" ] + then + newfile=$(basename "$INNOMOVELOG") + newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" + else + newfile="$INNOMOVELOG.$ARCHIVETIMESTAMP" + fi + wsrep_log_info "Moving '$INNOMOVELOG' to '$newfile'" + mv "$INNOMOVELOG" "$newfile" + gzip "$newfile" + fi + + if [ -e "$INNOBACKUPLOG" ] + then + if [ -n "$sstlogarchivedir" ] + then + newfile=$(basename "$INNOBACKUPLOG") + newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" + else + newfile="$INNOBACKUPLOG.$ARCHIVETIMESTAMP" + fi + wsrep_log_info "Moving '$INNOBACKUPLOG' to '$newfile'" + mv "$INNOBACKUPLOG" "$newfile" + gzip "$newfile" + fi + fi + INNOAPPLY="> '$INNOAPPLYLOG' 2>&1" + INNOMOVE="> '$INNOMOVELOG' 2>&1" + INNOBACKUP="2> '$INNOBACKUPLOG'" +fi + +setup_commands() +{ + if [ -z "$INNODB_FORCE_RECOVERY" ]; then + INNOAPPLY="$BACKUP_BIN $disver $iapts $INNOEXTRA --apply-log $rebuildcmd '$DATA' $INNOAPPLY" + else + INNOAPPLY="$BACKUP_BIN $disver $iapts $INNOEXTRA --innodb-force-recovery=$INNODB_FORCE_RECOVERY --apply-log $rebuildcmd '$DATA' $INNOAPPLY" + fi + INNOMOVE="$BACKUP_BIN $WSREP_SST_OPT_CONF --move-back $disver $impts --force-non-empty-directories '$DATA' $INNOMOVE" + sfmt_work="$sfmt" + if [ "$sfmt" = 'mbstream' ]; then + sfmt_work='xbstream' + fi + INNOBACKUP="$BACKUP_BIN $WSREP_SST_OPT_CONF $disver $iopts $tmpopts $INNOEXTRA --galera-info --stream=$sfmt_work '$itmpdir' $INNOBACKUP" +} + +get_stream +get_transfer + +if [ "$WSREP_SST_OPT_ROLE" = 'donor' ] +then + trap cleanup_at_exit EXIT + + if [ $WSREP_SST_OPT_BYPASS -eq 0 ] + then + if [ -z "$sst_ver" ]; then + wsrep_log_error "Upgrade joiner to 5.6.21 or higher for backup locks support" + wsrep_log_error "The joiner is not supported for this version of donor" + exit 93 + fi + + tmpdir=$(parse_cnf "$encgroups" 'tmpdir') + if [ -z "$tmpdir" ]; then + xtmpdir="$(mktemp -d)" + elif [ "$OS" = 'Linux' ]; then + xtmpdir=$(mktemp '-d' "--tmpdir=$tmpdir") + else + xtmpdir=$(TMPDIR="$tmpdir"; mktemp '-d') + fi + + wsrep_log_info "Using '$xtmpdir' as xtrabackup temporary directory" + tmpopts="--tmpdir='$xtmpdir'" + + itmpdir="$(mktemp -d)" + wsrep_log_info "Using '$itmpdir' as xtrabackup working directory" + + usrst=0 + if [ -n "$WSREP_SST_OPT_USER" ]; then + INNOEXTRA="$INNOEXTRA --user='$WSREP_SST_OPT_USER'" + usrst=1 + fi + + if [ -n "$WSREP_SST_OPT_PSWD" ]; then + INNOEXTRA="$INNOEXTRA --password='$WSREP_SST_OPT_PSWD'" + elif [ $usrst -eq 1 ]; then + # Empty password, used for testing, debugging etc. + INNOEXTRA="$INNOEXTRA --password=" + fi + + check_extra + + wsrep_log_info "Streaming GTID file before SST" + + # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id + # (separated by a space). + echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" + + if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then + # Let joiner know that we know its secret + echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" + fi + + ttcmd="$tcmd" + + if [ -n "$scomp" ]; then + tcmd="$scomp | $tcmd" + fi + + get_keys + if [ $encrypt -eq 1 ]; then + tcmd="$ecmd | $tcmd" + fi + + send_donor "$DATA" "$stagemsg-gtid" + + # Restore the transport commmand to its original state + tcmd="$ttcmd" + + if [ -n "$progress" ]; then + get_footprint + tcmd="$pcmd | $tcmd" + elif [ -n "$rlimit" ]; then + adjust_progress + tcmd="$pcmd | $tcmd" + fi + + wsrep_log_info "Sleeping before data transfer for SST" + sleep 10 + + wsrep_log_info "Streaming the backup to joiner at $REMOTEIP:$SST_PORT" + + # Add compression to the head of the stream (if specified) + if [ -n "$scomp" ]; then + tcmd="$scomp | $tcmd" + fi + + # Add encryption to the head of the stream (if specified) + if [ $encrypt -eq 1 ]; then + tcmd="$ecmd | $tcmd" + fi + + iopts="--databases-exclude='lost+found' $iopts" + + if [ ${FORCE_FTWRL:-0} -eq 1 ]; then + wsrep_log_info "Forcing FTWRL due to environment variable FORCE_FTWRL equal to $FORCE_FTWRL" + iopts="--no-backup-locks $iopts" + fi + + # if compression is enabled for backup files, then add the + # appropriate options to the innobackupex command line: + if [ "$compress" != 'none' ]; then + iopts="--compress${compress:+=$compress} $iopts" + if [ -n "$compress_threads" ]; then + iopts="--compress-threads=$compress_threads $iopts" + fi + if [ -n "$compress_chunk" ]; then + iopts="--compress-chunk-size=$compress_chunk $iopts" + fi + fi + + if [ -n "$backup_threads" ]; then + iopts="--parallel=$backup_threads $iopts" + fi + + setup_commands + set +e + timeit "$stagemsg-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" + set -e + + if [ ${RC[0]} -ne 0 ]; then + wsrep_log_error "innobackupex finished with error: ${RC[0]}. " \ + "Check syslog or '$INNOBACKUPLOG' for details" + exit 22 + elif [ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]; then + wsrep_log_error "$tcmd finished with error: ${RC[1]}" + exit 22 + fi + + # innobackupex implicitly writes PID to fixed location in $xtmpdir + BACKUP_PID="$xtmpdir/xtrabackup_pid" + + else # BYPASS FOR IST + + wsrep_log_info "Bypassing the SST for IST" + echo "continue" # now server can resume updating data + + # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id + # (separated by a space). + echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" + echo "1" > "$DATA/$IST_FILE" + + if [ -n "$scomp" ]; then + tcmd="$scomp | $tcmd" + fi + + get_keys + if [ $encrypt -eq 1 ]; then + tcmd="$ecmd | $tcmd" + fi + + strmcmd="$strmcmd '$IST_FILE'" + + send_donor "$DATA" "$stagemsg-IST" + + fi + + echo "done $WSREP_SST_OPT_GTID" + wsrep_log_info "Total time on donor: $totime seconds" + +elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] +then + [ -e "$SST_PROGRESS_FILE" ] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" + [ -n "$SST_PROGRESS_FILE" ] && touch "$SST_PROGRESS_FILE" + + ib_home_dir="$INNODB_DATA_HOME_DIR" + + # if no command line argument and INNODB_LOG_GROUP_HOME is not set, + # try to get it from my.cnf: + if [ -z "$INNODB_LOG_GROUP_HOME" ]; then + INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir') + fi + + ib_log_dir="$INNODB_LOG_GROUP_HOME" + + # if no command line argument then try to get it from my.cnf: + if [ -z "$INNODB_UNDO_DIR" ]; then + INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory') + fi + + ib_undo_dir="$INNODB_UNDO_DIR" + + if [ -n "$backup_threads" ]; then + impts="--parallel=$backup_threads $impts" + fi + + stagemsg='Joiner-Recv' + + sencrypted=1 + nthreads=1 + + MODULE="xtrabackup_sst" + + [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" + + # May need xtrabackup_checkpoints later on + [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" + [ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" + [ -f "$DATA/ib_logfile0" ] && rm -f "$DATA/ib_logfile0" + + ADDR="$WSREP_SST_OPT_ADDR" + + if [ "${tmode#VERIFY}" != "$tmode" ] + then # backward-incompatible behavior + CN="" + if [ -n "$tpem" ] + then + # find out my Common Name + get_openssl + if [ -z "$OPENSSL_BINARY" ]; then + wsrep_log_error 'openssl not found but it is required for authentication' + exit 42 + fi + CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \ + tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ + sed s/\ %//) + fi + MY_SECRET="$(wsrep_gen_secret)" + # Add authentication data to address + ADDR="$CN:$MY_SECRET@$ADDR" + else + MY_SECRET="" # for check down in recv_joiner() + fi + + trap sig_joiner_cleanup HUP PIPE INT TERM + trap cleanup_at_exit EXIT + + if [ -n "$progress" ]; then + adjust_progress + tcmd="$tcmd | $pcmd" + fi + + get_keys + if [ $encrypt -eq 1 -a $sencrypted -eq 1 ]; then + strmcmd="$ecmd | $strmcmd" + fi + + if [ -n "$sdecomp" ]; then + strmcmd="$sdecomp | $strmcmd" + fi + + check_sockets_utils + + STATDIR="$(mktemp -d)" + MAGIC_FILE="$STATDIR/$INFO_FILE" + + recv_joiner "$STATDIR" "$stagemsg-gtid" $stimeout 1 1 + + if ! ps -p "$WSREP_SST_OPT_PARENT" >/dev/null 2>&1 + then + wsrep_log_error "Parent mysqld process (PID: $WSREP_SST_OPT_PARENT) terminated unexpectedly." + exit 32 + fi + + if [ ! -r "$STATDIR/$IST_FILE" ] + then + + if [ -d "$DATA/.sst" ]; then + wsrep_log_info "WARNING: Stale temporary SST directory: '$DATA/.sst' from previous state transfer. Removing" + rm -rf "$DATA/.sst" + fi + mkdir -p "$DATA/.sst" + (recv_joiner "$DATA/.sst" "$stagemsg-SST" 0 0 0) & + jpid=$! + wsrep_log_info "Proceeding with SST" + + wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" + if [ "$OS" = 'FreeBSD' ]; then + find -E ${ib_home_dir:+"$ib_home_dir"} \ + ${ib_undo_dir:+"$ib_undo_dir"} \ + ${ib_log_dir:+"$ib_log_dir"} \ + "$DATA" -mindepth 1 -prune -regex "$cpat" -o -exec rm -rfv {} 1>&2 \+ + else + find ${ib_home_dir:+"$ib_home_dir"} \ + ${ib_undo_dir:+"$ib_undo_dir"} \ + ${ib_log_dir:+"$ib_log_dir"} \ + "$DATA" -mindepth 1 -prune -regex "$cpat" -o -exec rm -rfv {} 1>&2 \+ + fi + + get_binlog + + if [ -n "$WSREP_SST_OPT_BINLOG" ]; then + binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG") + cd "$binlog_dir" + wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" + rm -fv "$WSREP_SST_OPT_BINLOG".[0-9]* 1>&2 \+ || true + [ -f "$WSREP_SST_OPT_BINLOG_INDEX" ] && \ + rm -fv "$WSREP_SST_OPT_BINLOG_INDEX" 1>&2 \+ || true + cd "$OLD_PWD" + fi + + TDATA="$DATA" + DATA="$DATA/.sst" + + MAGIC_FILE="$DATA/$INFO_FILE" + wsrep_log_info "Waiting for SST streaming to complete!" + monitor_process $jpid + + if [ ! -s "$DATA/xtrabackup_checkpoints" ]; then + wsrep_log_error "xtrabackup_checkpoints missing, failed xtrabackup/SST on donor" + exit 2 + fi + + # Rebuild indexes for compact backups + if grep -q -F 'compact = 1' "$DATA/xtrabackup_checkpoints"; then + wsrep_log_info "Index compaction detected" + get_proc + nthreads=$(parse_cnf "$encgroups" 'rebuild-threads' $nproc) + wsrep_log_info "Rebuilding during prepare with $nthreads threads" + rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" + fi + + qpfiles=$(find "$DATA" -maxdepth 1 -type f -name '*.qp' -print -quit) + if [ -n "$qpfiles" ]; then + wsrep_log_info "Compressed qpress files found" + + if [ -z "$(command -v qpress)" ]; then + wsrep_log_error "qpress utility not found in the path" + exit 22 + fi + + get_proc + + dcmd="xargs -n 2 qpress -dT$nproc" + + if [ -n "$progress" ] && pv --help | grep -qw -- '--line-mode'; then + count=$(find "$DATA" -type f -name '*.qp' | wc -l) + count=$(( count*2 )) + pvopts="-f -s $count -l -N Decompression" + if pv --help | grep -qw -- '-F'; then + pvopts="$pvopts -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" + fi + pcmd="pv $pvopts" + adjust_progress + dcmd="$pcmd | $dcmd" + fi + + # Decompress the qpress files + wsrep_log_info "Decompression with $nproc threads" + timeit "Joiner-Decompression" "find '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" + extcode=$? + + if [ $extcode -eq 0 ]; then + wsrep_log_info "Removing qpress files after decompression" + find "$DATA" -type f -name '*.qp' -delete + if [ $? -ne 0 ]; then + wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" + fi + else + wsrep_log_error "Decompression failed. Exit code: $extcode" + exit 22 + fi + fi + + if [ -n "$WSREP_SST_OPT_BINLOG" ]; then + + BINLOG_DIRNAME=$(dirname "$WSREP_SST_OPT_BINLOG") + BINLOG_FILENAME=$(basename "$WSREP_SST_OPT_BINLOG") + + # To avoid comparing data directory and BINLOG_DIRNAME + mv "$DATA/$BINLOG_FILENAME".* "$BINLOG_DIRNAME/" 2>/dev/null || true + + cd "$BINLOG_DIRNAME" + for bfile in $(ls -1 "$BINLOG_FILENAME".[0-9]*); do + echo "$BINLOG_DIRNAME/$bfile" >> "$WSREP_SST_OPT_BINLOG_INDEX" + done + cd "$OLD_PWD" + + fi + + wsrep_log_info "Preparing the backup at $DATA" + setup_commands + timeit "Xtrabackup prepare stage" "$INNOAPPLY" + + if [ $? -ne 0 ]; then + wsrep_log_error "xtrabackup apply finished with errors. Check '$INNOAPPLYLOG' for details" + exit 22 + fi + + # [ -f "$INNOAPPLYLOG" ] && rm "$INNOAPPLYLOG" + + MAGIC_FILE="$TDATA/$INFO_FILE" + + wsrep_log_info "Moving the backup to $TDATA" + timeit "Xtrabackup move stage" "$INNOMOVE" + if [ $? -eq 0 ]; then + wsrep_log_info "Move successful, removing $DATA" + rm -rf "$DATA" + DATA="$TDATA" + else + wsrep_log_error "Move failed, keeping '$DATA' for further diagnosis" + wsrep_log_error "Check syslog or '$INNOMOVELOG' for details" + exit 22 + fi + + else + + wsrep_log_info "'$IST_FILE' received from donor: Running IST" + + fi + + if [ ! -r "$MAGIC_FILE" ]; then + wsrep_log_error "SST magic file '$MAGIC_FILE' not found/readable" + exit 2 + fi + + coords=$(cat "$MAGIC_FILE") + wsrep_log_info "Galera co-ords from recovery: $coords" + cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id + + wsrep_log_info "Total time on joiner: $totime seconds" +fi + +exit 0 From 1c7dd233a7e081b78ac6cf43c9b625ebb069bac3 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 23 Nov 2021 04:41:14 +0100 Subject: [PATCH 5/7] MDEV-26915 post-fix: deleted unnecessary file --- scripts/wsrep_sst_xtrabackup-v2.sh | 1405 ---------------------------- 1 file changed, 1405 deletions(-) delete mode 100644 scripts/wsrep_sst_xtrabackup-v2.sh diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh deleted file mode 100644 index 73f15e79a4c..00000000000 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ /dev/null @@ -1,1405 +0,0 @@ -#!/bin/bash -ue -# Copyright (C) 2017-2021 MariaDB -# Copyright (C) 2013 Percona Inc -# -# 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 -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; see the file COPYING. If not, write to the -# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston -# MA 02110-1335 USA. - -# Documentation: -# http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html -# Make sure to read that before proceeding! - -. $(dirname "$0")/wsrep_sst_common -wsrep_check_datadir - -OS="$(uname)" -ealgo="" -eformat="" -ekey="" -ekeyfile="" -encrypt=0 -ecode=0 -ssyslog="" -ssystag="" -BACKUP_PID="" -tcert="" -tpath=0 -tpem="" -tkey="" -tmode="DISABLED" -sockopt="" -progress="" -ttime=0 -totime=0 -lsn="" -ecmd="" -rlimit="" -# Initially -stagemsg="$WSREP_SST_OPT_ROLE" -cpat="" -speciald=1 -ib_home_dir="" -ib_log_dir="" -ib_undo_dir="" - -sfmt="" -strmcmd="" -tfmt="" -tcmd="" -rebuild=0 -rebuildcmd="" -payload=0 -pvformat="-F '%N => Rate:%r Avg:%a Elapsed:%t %e Bytes: %b %p'" -pvopts="-f -i 10 -N $WSREP_SST_OPT_ROLE" -STATDIR="" -uextra=0 -disver="" - -tmpopts="" -itmpdir="" -xtmpdir="" - -scomp="" -sdecomp="" - -ssl_dhparams="" - -compress='none' -compress_chunk="" -compress_threads="" - -backup_threads="" - -encrypt_threads="" -encrypt_chunk="" - -readonly SECRET_TAG="secret" - -sst_ver=-1 - -if [ -n "$(command -v pv)" ] && pv --help | grep -qw -- '-F'; then - pvopts="$pvopts $pvformat" -fi -pcmd="pv $pvopts" -declare -a RC - -BACKUP_BIN="$(command -v innobackupex)" -if [ ! -x "$BACKUP_BIN" ]; then - wsrep_log_error 'innobackupex binary not found in path' - exit 42 -fi - -DATA="$WSREP_SST_OPT_DATA" -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" -MAGIC_FILE="$DATA/$INFO_FILE" - -INNOAPPLYLOG="$DATA/innobackupex.prepare.log" -INNOMOVELOG="$DATA/innobackupex.move.log" -INNOBACKUPLOG="$DATA/innobackupex.backup.log" - -# Setting the path for ss and ip -export PATH="/usr/sbin:/sbin:$PATH" - -timeit() -{ - local stage="$1" - shift - local cmd="$@" - local x1 x2 took extcode - - if [ $ttime -eq 1 ]; then - x1=$(date +%s) - wsrep_log_info "Evaluating $cmd" - eval "$cmd" - extcode=$? - x2=$(date +%s) - took=$(( x2-x1 )) - wsrep_log_info "NOTE: $stage took $took seconds" - totime=$(( totime+took )) - else - wsrep_log_info "Evaluating $cmd" - eval "$cmd" - extcode=$? - fi - return $extcode -} - -get_keys() -{ - # $encrypt -eq 1 is for internal purposes only - if [ $encrypt -ge 2 -o $encrypt -eq -1 ]; then - return - fi - - if [ $encrypt -eq 0 ]; then - if [ -n "$ealgo" -o -n "$ekey" -o -n "$ekeyfile" ]; then - wsrep_log_error "Options for encryption are specified, " \ - "but encryption itself is disabled. SST may fail." - fi - return - fi - - if [ $sfmt = 'tar' ]; then - wsrep_log_info "NOTE: key-based encryption (encrypt=1) " \ - "cannot be enabled with tar format" - encrypt=-1 - return - fi - - wsrep_log_info "Key based encryption enabled in my.cnf - supported only from Xtrabackup 2.1.4" - - if [ -z "$ealgo" ]; then - wsrep_log_error "FATAL: Encryption algorithm empty from my.cnf, bailing out" - exit 3 - fi - - if [ -z "$ekey" -a ! -r "$ekeyfile" ]; then - wsrep_log_error "FATAL: Either key must be specified " \ - "or keyfile must be readable" - exit 3 - fi - - if [ "$eformat" = 'openssl' ]; then - get_openssl - if [ -z "$OPENSSL_BINARY" ]; then - wsrep_log_error "If encryption using the openssl is enabled, " \ - "then you need to install openssl" - exit 2 - fi - ecmd="'$OPENSSL_BINARY' enc -$ealgo" - if "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-pbkdf2'; then - ecmd="$ecmd -pbkdf2" - elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-iter'; then - ecmd="$ecmd -iter 1" - elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-md'; then - ecmd="$ecmd -md sha256" - fi - if [ -z "$ekey" ]; then - ecmd="$ecmd -kfile '$ekeyfile'" - else - ecmd="$ecmd -k '$ekey'" - fi - elif [ "$eformat" = 'xbcrypt' ]; then - if [ -z "$(command -v xbcrypt)" ]; then - wsrep_log_error "If encryption using the xbcrypt is enabled, " \ - "then you need to install xbcrypt" - exit 2 - fi - wsrep_log_info "NOTE: xbcrypt-based encryption, " \ - "supported only from Xtrabackup 2.1.4" - if [ -z "$ekey" ]; then - ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key-file='$ekeyfile'" - else - wsrep_log_warning \ - "Using the 'encrypt-key' option causes the encryption key " \ - "to be set via the command-line and is considered insecure. " \ - "It is recommended to use the 'encrypt-key-file' option instead." - ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key='$ekey'" - fi - if [ -n "$encrypt_threads" ]; then - ecmd="$ecmd --encrypt-threads=$encrypt_threads" - fi - if [ -n "$encrypt_chunk" ]; then - ecmd="$ecmd --encrypt-chunk-size=$encrypt_chunk" - fi - else - wsrep_log_error "Unknown encryption format='$eformat'" - exit 2 - fi - - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - ecmd="$ecmd -d" - fi - - stagemsg="$stagemsg-XB-Encrypted" -} - -get_transfer() -{ - if [ $tfmt = 'nc' ]; then - wsrep_log_info "Using netcat as streamer" - wsrep_check_programs nc - tcmd="nc" - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - if nc -h 2>&1 | grep -q 'ncat'; then - wsrep_log_info "Using Ncat as streamer" - tcmd="$tcmd -l" - elif nc -h 2>&1 | grep -qw -- '-d'; then - wsrep_log_info "Using Debian netcat as streamer" - tcmd="$tcmd -dl" - if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then - # When host is not explicitly specified (when only the port - # is specified) netcat can only bind to an IPv4 address if - # the "-6" option is not explicitly specified: - tcmd="$tcmd -6" - fi - else - wsrep_log_info "Using traditional netcat as streamer" - tcmd="$tcmd -l -p" - fi - tcmd="$tcmd $SST_PORT" - else - # Check to see if netcat supports the '-N' flag. - # -N Shutdown the network socket after EOF on stdin - # If it supports the '-N' flag, then we need to use the '-N' - # flag, otherwise the transfer will stay open after the file - # transfer and cause the command to timeout. - # Older versions of netcat did not need this flag and will - # return an error if the flag is used. - if nc -h 2>&1 | grep -qw -- '-N'; then - tcmd="$tcmd -N" - wsrep_log_info "Using nc -N" - fi - # netcat doesn't understand [] around IPv6 address - if nc -h 2>&1 | grep -q ncat; then - wsrep_log_info "Using Ncat as streamer" - elif nc -h 2>&1 | grep -qw -- '-d'; then - wsrep_log_info "Using Debian netcat as streamer" - else - wsrep_log_info "Using traditional netcat as streamer" - tcmd="$tcmd -q0" - fi - tcmd="$tcmd $WSREP_SST_OPT_HOST_UNESCAPED $SST_PORT" - fi - else - tfmt='socat' - - wsrep_log_info "Using socat as streamer" - wsrep_check_programs socat - - if [ -n "$sockopt" ]; then - sockopt=$(trim_string "$sockopt" ',') - if [ -n "$sockopt" ]; then - sockopt=",$sockopt" - fi - fi - - # Add an option for ipv6 if needed: - if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then - # If sockopt contains 'pf=ip6' somewhere in the middle, - # this will not interfere with socat, but exclude the trivial - # cases when sockopt contains 'pf=ip6' as prefix or suffix: - if [ "$sockopt" = "${sockopt#,pf=ip6}" -a \ - "$sockopt" = "${sockopt%,pf=ip6}" ] - then - sockopt=",pf=ip6$sockopt" - fi - fi - - if [ $encrypt -lt 2 ]; then - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - tcmd="socat -u TCP-LISTEN:$SST_PORT,reuseaddr$sockopt stdio" - else - tcmd="socat -u stdio TCP:$REMOTEIP:$SST_PORT$sockopt" - fi - return - fi - - if ! socat -V | grep -q -F 'WITH_OPENSSL 1'; then - wsrep_log_error "******** FATAL ERROR ************************************************ " - wsrep_log_error "* Encryption requested, but socat is not OpenSSL enabled (encrypt=$encrypt) *" - wsrep_log_error "********************************************************************* " - exit 2 - fi - - local action='Decrypting' - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - tcmd="socat -u openssl-listen:$SST_PORT,reuseaddr" - else - tcmd="socat -u stdio openssl-connect:$REMOTEIP:$SST_PORT" - action='Encrypting' - fi - - if [ "${sockopt#*,dhparam=}" != "$sockopt" ]; then - if [ -z "$ssl_dhparams" ]; then - # Determine the socat version - SOCAT_VERSION=$(socat -V 2>&1 | grep -m1 -oe '[0-9]\.[0-9][\.0-9]*') - if [ -z "$SOCAT_VERSION" ]; then - wsrep_log_error "******** FATAL ERROR ******************" - wsrep_log_error "* Cannot determine the socat version. *" - wsrep_log_error "***************************************" - exit 2 - fi - if ! check_for_version "$SOCAT_VERSION" '1.7.3'; then - # socat versions < 1.7.3 will have 512-bit dhparams (too small) - # so create 2048-bit dhparams and send that as a parameter: - check_for_dhparams - fi - fi - if [ -n "$ssl_dhparams" ]; then - tcmd="$tcmd,dhparam='$ssl_dhparams'" - fi - fi - - CN_option=",commonname=''" - - if [ $encrypt -eq 2 ]; then - wsrep_log_info "Using openssl based encryption with socat: with crt and pem" - if [ -z "$tpem" -o -z "$tcert" ]; then - wsrep_log_error \ - "Both PEM file and CRT file (or path) are required" - exit 22 - fi - if [ ! -r "$tpem" -o ! -r "$tcert" ]; then - wsrep_log_error \ - "Both PEM file and CRT file (or path) must be readable" - exit 22 - fi - verify_ca_matches_cert "$tcert" "$tpem" $tpath - if [ $tpath -eq 0 ]; then - tcmd="$tcmd,cert='$tpem',cafile='$tcert'" - else - tcmd="$tcmd,cert='$tpem',capath='$tcert'" - fi - stagemsg="$stagemsg-OpenSSL-Encrypted-2" - wsrep_log_info "$action with cert=$tpem, ca=$tcert" - elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then - wsrep_log_info "Using openssl based encryption with socat: with key and crt" - if [ -z "$tpem" -o -z "$tkey" ]; then - wsrep_log_error "Both certificate file (or path) " \ - "and key file are required" - exit 22 - fi - if [ ! -r "$tpem" -o ! -r "$tkey" ]; then - wsrep_log_error "Both certificate file (or path) " \ - "and key file must be readable" - exit 22 - fi - verify_cert_matches_key "$tpem" "$tkey" - stagemsg="$stagemsg-OpenSSL-Encrypted-3" - if [ -z "$tcert" ]; then - if [ $encrypt -eq 4 ]; then - wsrep_log_error \ - "Peer certificate file (or path) required if encrypt=4" - exit 22 - fi - # no verification - CN_option="" - tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0" - wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0" - else - # CA verification - if [ ! -r "$tcert" ]; then - wsrep_log_error "Certificate file or path must be readable" - exit 22 - fi - verify_ca_matches_cert "$tcert" "$tpem" $tpath - if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then - CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'" - elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ] - then - CN_option=",commonname=''" - elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then - CN_option=',commonname=localhost' - else - CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'" - fi - if [ $tpath -eq 0 ]; then - tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'" - else - tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'" - fi - wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert" - fi - else - wsrep_log_info "Unknown encryption mode: encrypt=$encrypt" - exit 22 - fi - - tcmd="$tcmd$CN_option$sockopt" - - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - tcmd="$tcmd stdio" - fi - fi -} - -get_footprint() -{ - pushd "$WSREP_SST_OPT_DATA" 1>/dev/null - payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c -s | awk 'END { print $1 }') - if [ "$compress" != 'none' ]; then - # QuickLZ has around 50% compression ratio - # When compression/compaction used, the progress is only an approximate. - payload=$(( payload*1/2 )) - fi - popd 1>/dev/null - pcmd="$pcmd -s $payload" - adjust_progress -} - -adjust_progress() -{ - if [ -z "$(command -v pv)" ]; then - wsrep_log_error "pv not found in path: $PATH" - wsrep_log_error "Disabling all progress/rate-limiting" - pcmd="" - rlimit="" - progress="" - return - fi - - if [ -n "$progress" -a "$progress" != '1' ]; then - if [ -e "$progress" ]; then - pcmd="$pcmd 2>>'$progress'" - else - pcmd="$pcmd 2>'$progress'" - fi - elif [ -z "$progress" -a -n "$rlimit" ]; then - # When rlimit is non-zero - pcmd="pv -q" - fi - - if [ -n "$rlimit" -a "$WSREP_SST_OPT_ROLE" = 'donor' ]; then - wsrep_log_info "Rate-limiting SST to $rlimit" - pcmd="$pcmd -L \$rlimit" - fi -} - -encgroups='--mysqld|sst|xtrabackup' - -check_server_ssl_config() -{ - # backward-compatible behavior: - tcert=$(parse_cnf 'sst' 'tca') - tpem=$(parse_cnf 'sst' 'tcert') - tkey=$(parse_cnf 'sst' 'tkey') - # reading new ssl configuration options: - local tcert2=$(parse_cnf "$encgroups" 'ssl-ca') - local tpem2=$(parse_cnf "$encgroups" 'ssl-cert') - local tkey2=$(parse_cnf "$encgroups" 'ssl-key') - # if there are no old options, then we take new ones: - if [ -z "$tcert" -a -z "$tpem" -a -z "$tkey" ]; then - tcert="$tcert2" - tpem="$tpem2" - tkey="$tkey2" - # checking for presence of the new-style SSL configuration: - elif [ -n "$tcert2" -o -n "$tpem2" -o -n "$tkey2" ]; then - if [ "$tcert" != "$tcert2" -o \ - "$tpem" != "$tpem2" -o \ - "$tkey" != "$tkey2" ] - then - wsrep_log_info "new ssl configuration options (ssl-ca, ssl-cert " \ - "and ssl-key) are ignored by SST due to presence " \ - "of the tca, tcert and/or tkey in the [sst] section" - fi - fi - if [ -n "$tcert" ]; then - tcert=$(trim_string "$tcert") - if [ "${tcert%/}" != "$tcert" ]; then - tpath=1 - fi - fi -} - -read_cnf() -{ - sfmt=$(parse_cnf sst streamfmt 'xbstream') - tfmt=$(parse_cnf sst transferfmt 'socat') - - encrypt=$(parse_cnf "$encgroups" 'encrypt' 0) - tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | tr [:lower:] [:upper:]) - - if [ $encrypt -eq 0 -o $encrypt -ge 2 ] - then - if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then - check_server_ssl_config - fi - if [ "$tmode" != 'DISABLED' ]; then - if [ 0 -eq $encrypt -a -n "$tpem" -a -n "$tkey" ] - then - encrypt=3 # enable cert/key SSL encyption - - # avoid CA verification if not set explicitly: - # nodes may happen to have different CA if self-generated - # zeroing up tcert does the trick - [ "${tmode#VERIFY}" != "$tmode" ] || tcert="" - fi - fi - elif [ $encrypt -eq 1 ]; then - ealgo=$(parse_cnf "$encgroups" 'encrypt-algo') - eformat=$(parse_cnf "$encgroups" 'encrypt-format' 'xbcrypt') - ekey=$(parse_cnf "$encgroups" 'encrypt-key') - # The keyfile should be read only when the key - # is not specified or empty: - if [ -z "$ekey" ]; then - ekeyfile=$(parse_cnf "$encgroups" 'encrypt-key-file') - fi - fi - - wsrep_log_info "SSL configuration: CA='$tcert', CERT='$tpem'," \ - "KEY='$tkey', MODE='$tmode', encrypt='$encrypt'" - - sockopt=$(parse_cnf sst sockopt "") - progress=$(parse_cnf sst progress "") - rebuild=$(parse_cnf sst rebuild 0) - ttime=$(parse_cnf sst time 0) - cpat='.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$' - [ "$OS" = 'FreeBSD' ] && cpat=$(echo "$cpat" | sed 's/\\|/|/g') - cpat=$(parse_cnf sst cpat "$cpat") - scomp=$(parse_cnf sst compressor "") - sdecomp=$(parse_cnf sst decompressor "") - - rlimit=$(parse_cnf sst rlimit "") - uextra=$(parse_cnf sst use-extra 0) - speciald=$(parse_cnf sst sst-special-dirs 1) - iopts=$(parse_cnf sst inno-backup-opts "") - iapts=$(parse_cnf sst inno-apply-opts "") - impts=$(parse_cnf sst inno-move-opts "") - stimeout=$(parse_cnf sst sst-initial-timeout 300) - ssyslog=$(parse_cnf sst sst-syslog 0) - ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") - ssystag="$ssystag-" - sstlogarchive=$(parse_cnf sst sst-log-archive 1) - sstlogarchivedir=$(parse_cnf sst sst-log-archive-dir '/tmp/sst_log_archive') - - if [ $speciald -eq 0 ]; then - wsrep_log_error "sst-special-dirs equal to 0 is not supported, falling back to 1" - speciald=1 - fi - - if [ $ssyslog -ne -1 ]; then - ssyslog=$(in_config 'mysqld_safe' 'syslog') - fi - - if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then - compress=$(parse_cnf "$encgroups" 'compress' 'none') - if [ "$compress" != 'none' ]; then - compress_chunk=$(parse_cnf "$encgroups" 'compress-chunk-size') - compress_threads=$(parse_cnf "$encgroups" 'compress-threads') - fi - fi - - backup_threads=$(parse_cnf "$encgroups" 'backup-threads') - - if [ "$eformat" = 'xbcrypt' ]; then - encrypt_threads=$(parse_cnf "$encgroups" 'encrypt-threads') - encrypt_chunk=$(parse_cnf "$encgroups" 'encrypt-chunk-size') - fi -} - -get_stream() -{ - if [ "$sfmt" = 'mbstream' -o "$sfmt" = 'xbstream' ]; then - STREAM_BIN=$(command -v "$sfmt") - if [ -z "$STREAM_BIN" ]; then - if [ "$sfmt" = 'xbstream' ]; then - STREAM_BIN="$(command -v mbstream)" - else - STREAM_BIN="$(command -v xbstream)" - fi - fi - if [ -z "$STREAM_BIN" ]; then - wsrep_log_error "Streaming with $sfmt, but $sfmt not found in path" - exit 42 - fi - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - strmcmd="'$STREAM_BIN' -x" - else - strmcmd="'$STREAM_BIN' -c '$INFO_FILE'" - fi - else - sfmt='tar' - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - strmcmd='tar xfi -' - else - strmcmd="tar cf - '$INFO_FILE'" - fi - fi - wsrep_log_info "Streaming with $sfmt" -} - -sig_joiner_cleanup() -{ - wsrep_log_error "Removing $MAGIC_FILE file due to signal" - [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" -} - -cleanup_at_exit() -{ - # Since this is invoked just after exit NNN - local estatus=$? - if [ $estatus -ne 0 ]; then - wsrep_log_error "Cleanup after exit with status:$estatus" - fi - - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - wsrep_log_info "Removing the sst_in_progress file" - wsrep_cleanup_progress_file - else - if [ -n "$BACKUP_PID" ]; then - if check_pid "$BACKUP_PID" 1; then - wsrep_log_error "xtrabackup process is still running. Killing..." - cleanup_pid $CHECK_PID "$BACKUP_PID" - fi - fi - [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" - fi - - if [ -n "$progress" -a -p "$progress" ]; then - wsrep_log_info "Cleaning up fifo file $progress" - rm -f "$progress" || true - fi - - wsrep_log_info "Cleaning up temporary directories" - - if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then - if [ -n "$STATDIR" ]; then - [ -d "$STATDIR" ] && rm -rf "$STATDIR" - fi - else - [ -n "$xtmpdir" -a -d "$xtmpdir" ] && rm -rf "$xtmpdir" || true - [ -n "$itmpdir" -a -d "$itmpdir" ] && rm -rf "$itmpdir" || true - fi - - # Final cleanup - pgid=$(ps -o pgid= $$ | grep -o '[0-9]*') - - # This means no setsid done in mysqld. - # We don't want to kill mysqld here otherwise. - if [ $$ -eq $pgid ]; then - # This means a signal was delivered to the process. - # So, more cleanup. - if [ $estatus -ge 128 ]; then - kill -KILL -- -$$ || true - fi - fi - - exit $estatus -} - -setup_ports() -{ - SST_PORT="$WSREP_SST_OPT_PORT" - if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then - REMOTEIP="$WSREP_SST_OPT_HOST" - lsn="$WSREP_SST_OPT_LSN" - sst_ver="$WSREP_SST_OPT_SST_VER" - fi -} - -# -# Waits ~30 seconds for socat or nc to open the port and -# then reports ready, regardless of timeout. -# -wait_for_listen() -{ - local PORT="$1" - local ADDR="$2" - local MODULE="$3" - for i in {1..150}; do - if check_port "" "$PORT" 'socat|nc'; then - break - fi - sleep 0.2 - done - echo "ready $ADDR/$MODULE//$sst_ver" -} - -check_extra() -{ - local use_socket=1 - if [ $uextra -eq 1 ]; then - local thread_handling=$(parse_cnf '--mysqld' 'thread-handling') - if [ "$thread_handling" = 'pool-of-threads' ]; then - local eport=$(parse_cnf '--mysqld' 'extra-port') - if [ -n "$eport" ]; then - # Xtrabackup works only locally. - # Hence, setting host to 127.0.0.1 unconditionally: - wsrep_log_info "SST through extra_port $eport" - INNOEXTRA="$INNOEXTRA --host=127.0.0.1 --port=$eport" - use_socket=0 - else - wsrep_log_error "Extra port $eport null, failing" - exit 1 - fi - else - wsrep_log_info "Thread pool not set, ignore the option use_extra" - fi - fi - if [ $use_socket -eq 1 -a -n "$WSREP_SST_OPT_SOCKET" ]; then - INNOEXTRA="$INNOEXTRA --socket='$WSREP_SST_OPT_SOCKET'" - fi -} - -recv_joiner() -{ - local dir="$1" - local msg="$2" - local tmt=$3 - local checkf=$4 - local wait=$5 - - if [ ! -d "$dir" ]; then - # This indicates that IST is in progress - return - fi - - local ltcmd="$tcmd" - if [ $tmt -gt 0 ]; then - if [ -n "$(command -v timeout)" ]; then - if timeout --help | grep -qw -- '-k'; then - ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" - else - ltcmd="timeout -s9 $tmt $tcmd" - fi - fi - fi - - pushd "$dir" 1>/dev/null - set +e - - if [ $wait -ne 0 ]; then - wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" & - fi - - timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" - - set -e - popd 1>/dev/null - - if [ ${RC[0]} -eq 124 ]; then - wsrep_log_error "Possible timeout in receiving first data from " \ - "donor in gtid stage: exit codes: ${RC[@]}" - exit 32 - fi - - for ecode in "${RC[@]}"; do - if [ $ecode -ne 0 ]; then - wsrep_log_error "Error while getting data from donor node: " \ - "exit codes: ${RC[@]}" - exit 32 - fi - done - - if [ $checkf -eq 1 ]; then - if [ ! -r "$MAGIC_FILE" ]; then - # this message should cause joiner to abort - wsrep_log_error "receiving process ended without creating " \ - "'$MAGIC_FILE'" - wsrep_log_info "Contents of datadir" - wsrep_log_info $(ls -l "$dir/"*) - exit 32 - fi - - # check donor supplied secret - SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | cut -d ' ' -f 2) - if [ "$SECRET" != "$MY_SECRET" ]; then - wsrep_log_error "Donor does not know my secret!" - wsrep_log_info "Donor:'$SECRET', my:'$MY_SECRET'" - exit 32 - fi - - # remove secret from the magic file - grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" > "$MAGIC_FILE.new" - mv "$MAGIC_FILE.new" "$MAGIC_FILE" - fi -} - -send_donor() -{ - local dir="$1" - local msg="$2" - - pushd "$dir" 1>/dev/null - set +e - timeit "$msg" "$strmcmd | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - popd 1>/dev/null - - for ecode in "${RC[@]}"; do - if [ $ecode -ne 0 ]; then - wsrep_log_error "Error while sending data to joiner node: " \ - "exit codes: ${RC[@]}" - exit 32 - fi - done -} - -monitor_process() -{ - local sst_stream_pid=$1 - - while true ; do - if ! ps -p "$WSREP_SST_OPT_PARENT" >/dev/null 2>&1; then - wsrep_log_error "Parent mysqld process (PID: $WSREP_SST_OPT_PARENT) terminated unexpectedly." - kill -- -"$WSREP_SST_OPT_PARENT" - exit 32 - fi - if ! ps -p "$sst_stream_pid" >/dev/null 2>&1; then - break - fi - sleep 0.1 - done -} - -# check the version, we require XB-2.4 to ensure that we can pass the -# datadir via the command-line option -XB_REQUIRED_VERSION="2.3.5" - -XB_VERSION=`$BACKUP_BIN --version 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1` -if [[ -z "$XB_VERSION" ]]; then - wsrep_log_error "FATAL: Cannot determine the $BACKUP_BIN version. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" - exit 2 -fi - -if ! check_for_version "$XB_VERSION" "$XB_REQUIRED_VERSION"; then - wsrep_log_error "FATAL: The $BACKUP_BIN version is $XB_VERSION. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" - exit 2 -fi - -[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" - -if [ "$WSREP_SST_OPT_ROLE" != 'joiner' -a "$WSREP_SST_OPT_ROLE" != 'donor' ]; then - wsrep_log_error "Invalid role '$WSREP_SST_OPT_ROLE'" - exit 22 -fi - -read_cnf -setup_ports - -if "$BACKUP_BIN" --help 2>/dev/null | grep -qw -- '--version-check'; then - disver='--no-version-check' -fi - -# if no command line argument and INNODB_DATA_HOME_DIR environment variable -# is not set, try to get it from my.cnf: -if [ -z "$INNODB_DATA_HOME_DIR" ]; then - INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir') -fi - -OLD_PWD="$(pwd)" - -cd "$WSREP_SST_OPT_DATA" -if [ -n "$INNODB_DATA_HOME_DIR" ]; then - # handle both relative and absolute paths - [ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR" - cd "$INNODB_DATA_HOME_DIR" -fi -INNODB_DATA_HOME_DIR=$(pwd -P) - -cd "$OLD_PWD" - -if [ $ssyslog -eq 1 ]; then - if [ -n "$(command -v logger)" ]; then - wsrep_log_info "Logging all stderr of SST/xtrabackup to syslog" - - exec 2> >(logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE) - - wsrep_log_error() - { - logger -p daemon.err -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" - } - - wsrep_log_info() - { - logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" - } - else - wsrep_log_error "logger not in path: $PATH. Ignoring" - fi - INNOAPPLY="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply" - INNOMOVE="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move" - INNOBACKUP="2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" -else - if [ $sstlogarchive -eq 1 ] - then - ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S.%N") - - if [ -n "$sstlogarchivedir" ]; then - if [ ! -d "$sstlogarchivedir" ]; then - mkdir -p "$sstlogarchivedir" - fi - fi - - if [ -e "$INNOAPPLYLOG" ] - then - if [ -n "$sstlogarchivedir" ] - then - newfile=$(basename "$INNOAPPLYLOG") - newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" - else - newfile="$INNOAPPLYLOG.$ARCHIVETIMESTAMP" - fi - wsrep_log_info "Moving '$INNOAPPLYLOG' to '$newfile'" - mv "$INNOAPPLYLOG" "$newfile" - gzip "$newfile" - fi - - if [ -e "$INNOMOVELOG" ] - then - if [ -n "$sstlogarchivedir" ] - then - newfile=$(basename "$INNOMOVELOG") - newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" - else - newfile="$INNOMOVELOG.$ARCHIVETIMESTAMP" - fi - wsrep_log_info "Moving '$INNOMOVELOG' to '$newfile'" - mv "$INNOMOVELOG" "$newfile" - gzip "$newfile" - fi - - if [ -e "$INNOBACKUPLOG" ] - then - if [ -n "$sstlogarchivedir" ] - then - newfile=$(basename "$INNOBACKUPLOG") - newfile="$sstlogarchivedir/$newfile.$ARCHIVETIMESTAMP" - else - newfile="$INNOBACKUPLOG.$ARCHIVETIMESTAMP" - fi - wsrep_log_info "Moving '$INNOBACKUPLOG' to '$newfile'" - mv "$INNOBACKUPLOG" "$newfile" - gzip "$newfile" - fi - fi - INNOAPPLY="> '$INNOAPPLYLOG' 2>&1" - INNOMOVE="> '$INNOMOVELOG' 2>&1" - INNOBACKUP="2> '$INNOBACKUPLOG'" -fi - -setup_commands() -{ - if [ -z "$INNODB_FORCE_RECOVERY" ]; then - INNOAPPLY="$BACKUP_BIN $disver $iapts $INNOEXTRA --apply-log $rebuildcmd '$DATA' $INNOAPPLY" - else - INNOAPPLY="$BACKUP_BIN $disver $iapts $INNOEXTRA --innodb-force-recovery=$INNODB_FORCE_RECOVERY --apply-log $rebuildcmd '$DATA' $INNOAPPLY" - fi - INNOMOVE="$BACKUP_BIN $WSREP_SST_OPT_CONF --move-back $disver $impts --force-non-empty-directories '$DATA' $INNOMOVE" - sfmt_work="$sfmt" - if [ "$sfmt" = 'mbstream' ]; then - sfmt_work='xbstream' - fi - INNOBACKUP="$BACKUP_BIN $WSREP_SST_OPT_CONF $disver $iopts $tmpopts $INNOEXTRA --galera-info --stream=$sfmt_work '$itmpdir' $INNOBACKUP" -} - -get_stream -get_transfer - -if [ "$WSREP_SST_OPT_ROLE" = 'donor' ] -then - trap cleanup_at_exit EXIT - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - if [ -z "$sst_ver" ]; then - wsrep_log_error "Upgrade joiner to 5.6.21 or higher for backup locks support" - wsrep_log_error "The joiner is not supported for this version of donor" - exit 93 - fi - - tmpdir=$(parse_cnf "$encgroups" 'tmpdir') - if [ -z "$tmpdir" ]; then - xtmpdir="$(mktemp -d)" - elif [ "$OS" = 'Linux' ]; then - xtmpdir=$(mktemp '-d' "--tmpdir=$tmpdir") - else - xtmpdir=$(TMPDIR="$tmpdir"; mktemp '-d') - fi - - wsrep_log_info "Using '$xtmpdir' as xtrabackup temporary directory" - tmpopts="--tmpdir='$xtmpdir'" - - itmpdir="$(mktemp -d)" - wsrep_log_info "Using '$itmpdir' as xtrabackup working directory" - - usrst=0 - if [ -n "$WSREP_SST_OPT_USER" ]; then - INNOEXTRA="$INNOEXTRA --user='$WSREP_SST_OPT_USER'" - usrst=1 - fi - - if [ -n "$WSREP_SST_OPT_PSWD" ]; then - INNOEXTRA="$INNOEXTRA --password='$WSREP_SST_OPT_PSWD'" - elif [ $usrst -eq 1 ]; then - # Empty password, used for testing, debugging etc. - INNOEXTRA="$INNOEXTRA --password=" - fi - - check_extra - - wsrep_log_info "Streaming GTID file before SST" - - # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id - # (separated by a space). - echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" - - if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then - # Let joiner know that we know its secret - echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" - fi - - ttcmd="$tcmd" - - if [ -n "$scomp" ]; then - tcmd="$scomp | $tcmd" - fi - - get_keys - if [ $encrypt -eq 1 ]; then - tcmd="$ecmd | $tcmd" - fi - - send_donor "$DATA" "$stagemsg-gtid" - - # Restore the transport commmand to its original state - tcmd="$ttcmd" - - if [ -n "$progress" ]; then - get_footprint - tcmd="$pcmd | $tcmd" - elif [ -n "$rlimit" ]; then - adjust_progress - tcmd="$pcmd | $tcmd" - fi - - wsrep_log_info "Sleeping before data transfer for SST" - sleep 10 - - wsrep_log_info "Streaming the backup to joiner at $REMOTEIP:$SST_PORT" - - # Add compression to the head of the stream (if specified) - if [ -n "$scomp" ]; then - tcmd="$scomp | $tcmd" - fi - - # Add encryption to the head of the stream (if specified) - if [ $encrypt -eq 1 ]; then - tcmd="$ecmd | $tcmd" - fi - - iopts="--databases-exclude='lost+found' $iopts" - - if [ ${FORCE_FTWRL:-0} -eq 1 ]; then - wsrep_log_info "Forcing FTWRL due to environment variable FORCE_FTWRL equal to $FORCE_FTWRL" - iopts="--no-backup-locks $iopts" - fi - - # if compression is enabled for backup files, then add the - # appropriate options to the innobackupex command line: - if [ "$compress" != 'none' ]; then - iopts="--compress${compress:+=$compress} $iopts" - if [ -n "$compress_threads" ]; then - iopts="--compress-threads=$compress_threads $iopts" - fi - if [ -n "$compress_chunk" ]; then - iopts="--compress-chunk-size=$compress_chunk $iopts" - fi - fi - - if [ -n "$backup_threads" ]; then - iopts="--parallel=$backup_threads $iopts" - fi - - setup_commands - set +e - timeit "$stagemsg-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - - if [ ${RC[0]} -ne 0 ]; then - wsrep_log_error "innobackupex finished with error: ${RC[0]}. " \ - "Check syslog or '$INNOBACKUPLOG' for details" - exit 22 - elif [ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]; then - wsrep_log_error "$tcmd finished with error: ${RC[1]}" - exit 22 - fi - - # innobackupex implicitly writes PID to fixed location in $xtmpdir - BACKUP_PID="$xtmpdir/xtrabackup_pid" - - else # BYPASS FOR IST - - wsrep_log_info "Bypassing the SST for IST" - echo "continue" # now server can resume updating data - - # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id - # (separated by a space). - echo "$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" > "$MAGIC_FILE" - echo "1" > "$DATA/$IST_FILE" - - if [ -n "$scomp" ]; then - tcmd="$scomp | $tcmd" - fi - - get_keys - if [ $encrypt -eq 1 ]; then - tcmd="$ecmd | $tcmd" - fi - - strmcmd="$strmcmd '$IST_FILE'" - - send_donor "$DATA" "$stagemsg-IST" - - fi - - echo "done $WSREP_SST_OPT_GTID" - wsrep_log_info "Total time on donor: $totime seconds" - -elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] -then - [ -e "$SST_PROGRESS_FILE" ] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" - [ -n "$SST_PROGRESS_FILE" ] && touch "$SST_PROGRESS_FILE" - - ib_home_dir="$INNODB_DATA_HOME_DIR" - - # if no command line argument and INNODB_LOG_GROUP_HOME is not set, - # try to get it from my.cnf: - if [ -z "$INNODB_LOG_GROUP_HOME" ]; then - INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir') - fi - - ib_log_dir="$INNODB_LOG_GROUP_HOME" - - # if no command line argument then try to get it from my.cnf: - if [ -z "$INNODB_UNDO_DIR" ]; then - INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory') - fi - - ib_undo_dir="$INNODB_UNDO_DIR" - - if [ -n "$backup_threads" ]; then - impts="--parallel=$backup_threads $impts" - fi - - stagemsg='Joiner-Recv' - - sencrypted=1 - nthreads=1 - - MODULE="xtrabackup_sst" - - [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" - - # May need xtrabackup_checkpoints later on - [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" - [ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" - [ -f "$DATA/ib_logfile0" ] && rm -f "$DATA/ib_logfile0" - - ADDR="$WSREP_SST_OPT_ADDR" - - if [ "${tmode#VERIFY}" != "$tmode" ] - then # backward-incompatible behavior - CN="" - if [ -n "$tpem" ] - then - # find out my Common Name - get_openssl - if [ -z "$OPENSSL_BINARY" ]; then - wsrep_log_error 'openssl not found but it is required for authentication' - exit 42 - fi - CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \ - tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ - sed s/\ %//) - fi - MY_SECRET="$(wsrep_gen_secret)" - # Add authentication data to address - ADDR="$CN:$MY_SECRET@$ADDR" - else - MY_SECRET="" # for check down in recv_joiner() - fi - - trap sig_joiner_cleanup HUP PIPE INT TERM - trap cleanup_at_exit EXIT - - if [ -n "$progress" ]; then - adjust_progress - tcmd="$tcmd | $pcmd" - fi - - get_keys - if [ $encrypt -eq 1 -a $sencrypted -eq 1 ]; then - strmcmd="$ecmd | $strmcmd" - fi - - if [ -n "$sdecomp" ]; then - strmcmd="$sdecomp | $strmcmd" - fi - - check_sockets_utils - - STATDIR="$(mktemp -d)" - MAGIC_FILE="$STATDIR/$INFO_FILE" - - recv_joiner "$STATDIR" "$stagemsg-gtid" $stimeout 1 1 - - if ! ps -p "$WSREP_SST_OPT_PARENT" >/dev/null 2>&1 - then - wsrep_log_error "Parent mysqld process (PID: $WSREP_SST_OPT_PARENT) terminated unexpectedly." - exit 32 - fi - - if [ ! -r "$STATDIR/$IST_FILE" ] - then - - if [ -d "$DATA/.sst" ]; then - wsrep_log_info "WARNING: Stale temporary SST directory: '$DATA/.sst' from previous state transfer. Removing" - rm -rf "$DATA/.sst" - fi - mkdir -p "$DATA/.sst" - (recv_joiner "$DATA/.sst" "$stagemsg-SST" 0 0 0) & - jpid=$! - wsrep_log_info "Proceeding with SST" - - wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" - if [ "$OS" = 'FreeBSD' ]; then - find -E ${ib_home_dir:+"$ib_home_dir"} \ - ${ib_undo_dir:+"$ib_undo_dir"} \ - ${ib_log_dir:+"$ib_log_dir"} \ - "$DATA" -mindepth 1 -prune -regex "$cpat" -o -exec rm -rfv {} 1>&2 \+ - else - find ${ib_home_dir:+"$ib_home_dir"} \ - ${ib_undo_dir:+"$ib_undo_dir"} \ - ${ib_log_dir:+"$ib_log_dir"} \ - "$DATA" -mindepth 1 -prune -regex "$cpat" -o -exec rm -rfv {} 1>&2 \+ - fi - - get_binlog - - if [ -n "$WSREP_SST_OPT_BINLOG" ]; then - binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG") - cd "$binlog_dir" - wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" - rm -fv "$WSREP_SST_OPT_BINLOG".[0-9]* 1>&2 \+ || true - [ -f "$WSREP_SST_OPT_BINLOG_INDEX" ] && \ - rm -fv "$WSREP_SST_OPT_BINLOG_INDEX" 1>&2 \+ || true - cd "$OLD_PWD" - fi - - TDATA="$DATA" - DATA="$DATA/.sst" - - MAGIC_FILE="$DATA/$INFO_FILE" - wsrep_log_info "Waiting for SST streaming to complete!" - monitor_process $jpid - - if [ ! -s "$DATA/xtrabackup_checkpoints" ]; then - wsrep_log_error "xtrabackup_checkpoints missing, failed xtrabackup/SST on donor" - exit 2 - fi - - # Rebuild indexes for compact backups - if grep -q -F 'compact = 1' "$DATA/xtrabackup_checkpoints"; then - wsrep_log_info "Index compaction detected" - get_proc - nthreads=$(parse_cnf "$encgroups" 'rebuild-threads' $nproc) - wsrep_log_info "Rebuilding during prepare with $nthreads threads" - rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" - fi - - qpfiles=$(find "$DATA" -maxdepth 1 -type f -name '*.qp' -print -quit) - if [ -n "$qpfiles" ]; then - wsrep_log_info "Compressed qpress files found" - - if [ -z "$(command -v qpress)" ]; then - wsrep_log_error "qpress utility not found in the path" - exit 22 - fi - - get_proc - - dcmd="xargs -n 2 qpress -dT$nproc" - - if [ -n "$progress" ] && pv --help | grep -qw -- '--line-mode'; then - count=$(find "$DATA" -type f -name '*.qp' | wc -l) - count=$(( count*2 )) - pvopts="-f -s $count -l -N Decompression" - if pv --help | grep -qw -- '-F'; then - pvopts="$pvopts -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" - fi - pcmd="pv $pvopts" - adjust_progress - dcmd="$pcmd | $dcmd" - fi - - # Decompress the qpress files - wsrep_log_info "Decompression with $nproc threads" - timeit "Joiner-Decompression" "find '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" - extcode=$? - - if [ $extcode -eq 0 ]; then - wsrep_log_info "Removing qpress files after decompression" - find "$DATA" -type f -name '*.qp' -delete - if [ $? -ne 0 ]; then - wsrep_log_error "Something went wrong with deletion of qpress files. Investigate" - fi - else - wsrep_log_error "Decompression failed. Exit code: $extcode" - exit 22 - fi - fi - - if [ -n "$WSREP_SST_OPT_BINLOG" ]; then - - BINLOG_DIRNAME=$(dirname "$WSREP_SST_OPT_BINLOG") - BINLOG_FILENAME=$(basename "$WSREP_SST_OPT_BINLOG") - - # To avoid comparing data directory and BINLOG_DIRNAME - mv "$DATA/$BINLOG_FILENAME".* "$BINLOG_DIRNAME/" 2>/dev/null || true - - cd "$BINLOG_DIRNAME" - for bfile in $(ls -1 "$BINLOG_FILENAME".[0-9]*); do - echo "$BINLOG_DIRNAME/$bfile" >> "$WSREP_SST_OPT_BINLOG_INDEX" - done - cd "$OLD_PWD" - - fi - - wsrep_log_info "Preparing the backup at $DATA" - setup_commands - timeit "Xtrabackup prepare stage" "$INNOAPPLY" - - if [ $? -ne 0 ]; then - wsrep_log_error "xtrabackup apply finished with errors. Check '$INNOAPPLYLOG' for details" - exit 22 - fi - - # [ -f "$INNOAPPLYLOG" ] && rm "$INNOAPPLYLOG" - - MAGIC_FILE="$TDATA/$INFO_FILE" - - wsrep_log_info "Moving the backup to $TDATA" - timeit "Xtrabackup move stage" "$INNOMOVE" - if [ $? -eq 0 ]; then - wsrep_log_info "Move successful, removing $DATA" - rm -rf "$DATA" - DATA="$TDATA" - else - wsrep_log_error "Move failed, keeping '$DATA' for further diagnosis" - wsrep_log_error "Check syslog or '$INNOMOVELOG' for details" - exit 22 - fi - - else - - wsrep_log_info "'$IST_FILE' received from donor: Running IST" - - fi - - if [ ! -r "$MAGIC_FILE" ]; then - wsrep_log_error "SST magic file '$MAGIC_FILE' not found/readable" - exit 2 - fi - - coords=$(cat "$MAGIC_FILE") - wsrep_log_info "Galera co-ords from recovery: $coords" - cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id - - wsrep_log_info "Total time on joiner: $totime seconds" -fi - -exit 0 From 7e7235faa9ee103fc5164fc2bf1fd31be89b5e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 24 Nov 2021 09:55:29 +0200 Subject: [PATCH 6/7] Cleanup: offsetof instead of my_offsetof mdl_hash_function(): Use plain offsetof; MDL_key has standard layout. --- sql/mdl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mdl.cc b/sql/mdl.cc index 4cb1154b8eb..11bd6f6ed16 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -777,7 +777,7 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg) my_hash_value_type mdl_hash_function(CHARSET_INFO *cs, const uchar *key, size_t length) { - MDL_key *mdl_key= (MDL_key*) (key - my_offsetof(MDL_key, m_ptr)); + MDL_key *mdl_key= (MDL_key*) (key - offsetof(MDL_key, m_ptr)); return mdl_key->hash_value(); } From b53ee760ff17e3d9ed95b75e5ea2de124ae69384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 24 Nov 2021 12:42:31 +0200 Subject: [PATCH 7/7] Cleanup: offsetof instead of my_offsetof Sys_lc_messages, Sys_lc_time_names: Use offsetof(MY_LOCALE, ...) because the type has standard layout. --- sql/sys_vars.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index d42c76245cb..31f29042388 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5425,14 +5425,14 @@ static bool update_locale(sys_var *self, THD* thd, enum_var_type type) static Sys_var_struct Sys_lc_messages( "lc_messages", "Set the language used for the error messages", SESSION_VAR(lc_messages), NO_CMD_LINE, - my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_messages), + offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_messages), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_locale), ON_UPDATE(update_locale)); static Sys_var_struct Sys_lc_time_names( "lc_time_names", "Set the language used for the month " "names and the days of the week", SESSION_VAR(lc_time_names), NO_CMD_LINE, - my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_time_names), + offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_time_names), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_locale)); static Sys_var_tz Sys_time_zone(