diff options
author | Julius Goryavsky <sysprg@gmail.com> | 2018-12-06 14:36:57 +0100 |
---|---|---|
committer | Julius Goryavsky <sysprg@gmail.com> | 2018-12-17 11:14:54 +0100 |
commit | cadb6ac770d818d1ed14aa1c2b84647619900935 (patch) | |
tree | 4696955e345412b3f9867daf3873f9a3ae1fa400 | |
parent | b6f203984bc519a31ac695cbcb6de7f1f638d321 (diff) | |
download | mariadb-git-cadb6ac770d818d1ed14aa1c2b84647619900935.tar.gz |
DEV-17835: Remove wsrep-sst-method=xtrabackup
The use of the xtrabackup and xtrabackup-v2 methods for SST
has been declared obsolete since version 10.2, now it cannot
be used because of the different redo log format. Accordingly,
we need to remove the xtrabackup-related scripts and dynamically
replace the call to xtrabackup[-v2] to the mariabackup (with a
corresponding warning in the log) when the server performs SST.
https://jira.mariadb.org/browse/MDEV-17835
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Docs/README-wsrep | 18 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result | 204 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf | 1 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test | 8 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf | 13 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test | 13 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test | 1 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result | 4 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test | 5 | ||||
-rw-r--r-- | scripts/CMakeLists.txt | 2 | ||||
-rw-r--r-- | scripts/wsrep_sst_xtrabackup-v2.sh | 1260 | ||||
-rw-r--r-- | scripts/wsrep_sst_xtrabackup.sh | 692 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 21 | ||||
-rw-r--r-- | sql/wsrep_sst.h | 3 |
16 files changed, 277 insertions, 1972 deletions
diff --git a/.gitignore b/.gitignore index 3f28c0fb66b..859551d62a0 100644 --- a/.gitignore +++ b/.gitignore @@ -128,8 +128,6 @@ scripts/wsrep_sst_mysqldump scripts/wsrep_sst_rsync scripts/wsrep_sst_rsync_wan scripts/wsrep_sst_mariabackup -scripts/wsrep_sst_xtrabackup -scripts/wsrep_sst_xtrabackup-v2 scripts/maria_add_gis_sp.sql scripts/maria_add_gis_sp_bootstrap.sql scripts/galera_new_cluster diff --git a/Docs/README-wsrep b/Docs/README-wsrep index 6bb329e9396..02642e80efb 100644 --- a/Docs/README-wsrep +++ b/Docs/README-wsrep @@ -137,7 +137,7 @@ Additional packages to consider (if not yet installed): * galera (multi-master replication provider, https://launchpad.net/galera) * MySQL-client-community (for connecting to server and mysqldump-based SST) * rsync (for rsync-based SST) - * xtrabackup and nc (for xtrabackup-based SST) + * mariabackup and nc (for mariabackup-based SST) 2.2 Upgrade system tables. @@ -380,14 +380,14 @@ to join or start a cluster. wsrep_sst_method=rsync What method to use to copy database state to a newly joined node. Supported methods: - - mysqldump: slow (except for small datasets) but allows for upgrade - between major MySQL versions or InnoDB features. - - rsync: much faster on large datasets (default). - - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. - - xtrabackup: very fast and practically non-blocking SST method based on - Percona's xtrabackup tool. - - (for xtrabackup to work the following settings must be present in my.cnf + - mysqldump: slow (except for small datasets) but allows for upgrade + between major MySQL versions or InnoDB features. + - rsync: much faster on large datasets (default). + - rsync_wan: same as rsync but with deltaxfer to minimize network traffic. + - mariabackup: very fast and practically non-blocking SST method based on + mariabackup tool (enhanced version of Percona's xtrabackup). + + (for mariabackup to work the following settings must be present in my.cnf on all nodes: [mysqld] wsrep_sst_auth=root:<root password> diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result index d0fac1e3d14..91f45c93257 100644 --- a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result @@ -1,4 +1,6 @@ connection node_1; +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; CREATE PROCEDURE p1 () BEGIN diff --git a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result new file mode 100644 index 00000000000..481a85711be --- /dev/null +++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result @@ -0,0 +1,204 @@ +Performing State Transfer on a server that has been killed and restarted +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +COMMIT; +connection node_2; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +INSERT INTO t1 VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('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 ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('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 ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +INSERT INTO t1 VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave; +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +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; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +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 AUTOCOMMIT=ON; +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 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('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 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('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 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('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 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +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; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +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 AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf index 7e557717744..bd6bf9d4f98 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf @@ -9,4 +9,3 @@ wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' - diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test index 731059dc584..9d5f821a170 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test @@ -8,6 +8,10 @@ --source include/have_innodb.inc --source include/have_mariabackup.inc +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + --connection node_1 --let $connection_id = `SELECT CONNECTION_ID()` @@ -94,3 +98,7 @@ DROP TABLE t1; CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); + +--let $node_1=node_1a +--let $node_2=node_2a +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf new file mode 100644 index 00000000000..7979b23e085 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf @@ -0,0 +1,13 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep_sst_method=mariabackup +wsrep_sst_auth=root: + +innodb_flush_log_at_trx_commit=0 + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test new file mode 100644 index 00000000000..fd362a26840 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.test @@ -0,0 +1,13 @@ +# +# This test performs server kill and IST while innodb_flush_logs_on_trx_commit = 0 +# This confirms that IST can properly catch up even in the face of relaxed single-node durability +# +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_mariabackup.inc + +--source suite/galera/include/galera_st_kill_slave.inc +--source suite/galera/include/galera_st_kill_slave_ddl.inc diff --git a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test index 07838702deb..fd362a26840 100644 --- a/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test +++ b/mysql-test/suite/galera/t/galera_ist_mariabackup_innodb_flush_logs.test @@ -7,6 +7,7 @@ --source include/big_test.inc --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/have_mariabackup.inc --source suite/galera/include/galera_st_kill_slave.inc --source suite/galera/include/galera_st_kill_slave_ddl.inc diff --git a/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result b/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result index cbdac640c36..51f167b8f47 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_sst_method_basic.result @@ -33,6 +33,10 @@ SET @@global.wsrep_sst_method="xtrabackup-v2"; SELECT @@global.wsrep_sst_method; @@global.wsrep_sst_method xtrabackup-v2 +SET @@global.wsrep_sst_method="mariabackup"; +SELECT @@global.wsrep_sst_method; +@@global.wsrep_sst_method +mariabackup SET @@global.wsrep_sst_method=default; SELECT @@global.wsrep_sst_method; @@global.wsrep_sst_method diff --git a/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test b/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test index 3f40a3922dd..be038eb4baf 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_sst_method_basic.test @@ -23,10 +23,15 @@ SET @@global.wsrep_sst_method=rsync; SELECT @@global.wsrep_sst_method; SET @@global.wsrep_sst_method=mysqldump; SELECT @@global.wsrep_sst_method; +# The xtrabackup and xtrabackup-v2 methods are obsolete, +# but we can still select them (they will be automatically +# replaced to mariabackup): SET @@global.wsrep_sst_method=xtrabackup; SELECT @@global.wsrep_sst_method; SET @@global.wsrep_sst_method="xtrabackup-v2"; SELECT @@global.wsrep_sst_method; +SET @@global.wsrep_sst_method="mariabackup"; +SELECT @@global.wsrep_sst_method; SET @@global.wsrep_sst_method=default; SELECT @@global.wsrep_sst_method; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 464c00d57da..901a774be4b 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -274,8 +274,6 @@ ELSE() SET(WSREP_SCRIPTS wsrep_sst_mysqldump wsrep_sst_rsync - wsrep_sst_xtrabackup - wsrep_sst_xtrabackup-v2 wsrep_sst_mariabackup ) # The following script is sourced from other SST scripts, so it should diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh deleted file mode 100644 index 2de384806b2..00000000000 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ /dev/null @@ -1,1260 +0,0 @@ -#!/bin/bash -ue -# 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-1301 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 - -ealgo="" -ekey="" -ekeyfile="" -encrypt=0 -nproc=1 -ecode=0 -ssyslog="" -ssystag="" -XTRABACKUP_PID="" -tca="" -tcert="" -tkey="" -sockopt="" -progress="" -ttime=0 -totime=0 -ecmd="" -rlimit="" -# Initially -stagemsg="${WSREP_SST_OPT_ROLE}" -cpat="" -ib_home_dir="" -ib_log_dir="" -ib_undo_dir="" - -sfmt="tar" -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="" - -ssl_cert="" -ssl_ca="" -ssl_key="" - -if pv --help 2>/dev/null | grep -q FORMAT;then - pvopts+=$pvformat -fi -pcmd="pv $pvopts" -declare -a RC - -INNOBACKUPEX_BIN=innobackupex -DATA="${WSREP_SST_OPT_DATA}" -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" -MAGIC_FILE="${DATA}/${INFO_FILE}" - -# Setting the path for ss and ip -export PATH="/usr/sbin:/sbin:$PATH" - -OS=$(uname) - -if ! which lsof > /dev/null; then - wsrep_log_error "lsof tool not found in PATH! Make sure you have it installed." - exit 2 # ENOENT -fi - -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 || $encrypt -eq -1 ]];then - return - fi - - if [[ $encrypt -eq 0 ]];then - if $MY_PRINT_DEFAULTS xtrabackup | grep -q encrypt;then - wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " - fi - return - fi - - if [[ $sfmt == 'tar' ]];then - wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" - encrypt=-1 - return - fi - - wsrep_log_info "Xtrabackup 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 && ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Either key or keyfile must be readable" - exit 3 - fi - - 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" - wsrep_log_warning "to be set via the command-line and is considered insecure." - wsrep_log_warning "It is recommended to use the 'encrypt-key-file' option instead." - - ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" - fi - - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - ecmd+=" -d" - fi - - stagemsg+="-XB-Encrypted" -} - -# -# If the ssl_dhparams variable is already set, uses that as a source -# of dh parameters for OpenSSL. Otherwise, looks for dhparams.pem in the -# datadir, and creates it there if it can't find the file. -# No input parameters -# -check_for_dhparams() -{ - if [[ -z "$ssl_dhparams" ]]; then - if ! [[ -r "$DATA/dhparams.pem" ]]; then - wsrep_check_programs openssl - wsrep_log_info "Could not find dhparams file, creating $DATA/dhparams.pem" - - if ! openssl dhparam -out "$DATA/dhparams.pem" 2048 >/dev/null 2>&1 - then - wsrep_log_error "******** FATAL ERROR ********************************* " - wsrep_log_error "* Could not create the dhparams.pem file with OpenSSL. " - wsrep_log_error "****************************************************** " - exit 22 - fi - fi - ssl_dhparams="$DATA/dhparams.pem" - fi -} - -# -# verifies that the certificate matches the private key -# doing this will save us having to wait for a timeout that would -# otherwise occur. -# -# 1st param: path to the cert -# 2nd param: path to the private key -# -verify_cert_matches_key() -{ - local cert_path=$1 - local key_path=$2 - - wsrep_check_programs openssl diff - - # generate the public key from the cert and the key - # they should match (otherwise we can't create an SSL connection) - if ! diff <(openssl x509 -in "$cert_path" -pubkey -noout) <(openssl rsa -in "$key_path" -pubout 2>/dev/null) >/dev/null 2>&1 - then - wsrep_log_error "******** FATAL ERROR ************************* " - wsrep_log_error "* The certifcate and private key do not match. " - wsrep_log_error "* Please check your certificate and key files. " - wsrep_log_error "********************************************** " - exit 22 - fi -} - -# Checks to see if the file exists -# If the file does not exist (or cannot be read), issues an error -# and exits -# -# 1st param: file name to be checked (for read access) -# 2nd param: 1st error message (header) -# 3rd param: 2nd error message (footer, optional) -# -verify_file_exists() -{ - local file_path=$1 - local error_message1=$2 - local error_message2=$3 - - if ! [[ -r "$file_path" ]]; then - wsrep_log_error "******** FATAL ERROR ************************* " - wsrep_log_error "* $error_message1 " - wsrep_log_error "* Could not find/access : $file_path " - - if ! [[ -z "$error_message2" ]]; then - wsrep_log_error "* $error_message2 " - fi - - wsrep_log_error "********************************************** " - exit 22 - fi -} - -get_transfer() -{ - TSST_PORT=${WSREP_SST_OPT_PORT:-4444} - - if [[ $tfmt == 'nc' ]];then - wsrep_check_programs nc - - if [[ $encrypt -eq 2 || $encrypt -eq 3 || $encrypt -eq 4 ]]; then - wsrep_log_error "******** FATAL ERROR *********************** " - wsrep_log_error "* Using SSL encryption (encrypt= 2, 3, or 4) " - wsrep_log_error "* is not supported when using nc(netcat). " - wsrep_log_error "******************************************** " - exit 22 - fi - - wsrep_log_info "Using netcat as streamer" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - if nc -h 2>&1 | grep -q ncat; then - # Ncat - tcmd="nc $sockopt -l ${TSST_PORT}" - elif nc -h 2>&1 | grep -q -- '-d\>';then - # Debian netcat - tcmd="nc $sockopt -dl ${TSST_PORT}" - else - # traditional netcat - tcmd="nc $sockopt -l -p ${TSST_PORT}" - fi - else - if nc -h 2>&1 | grep -q ncat;then - # Ncat - tcmd="nc ${WSREP_SST_OPT_HOST_UNESCAPED} ${TSST_PORT}" - elif nc -h 2>&1 | grep -q -- '-d\>';then - # Debian netcat - tcmd="nc ${WSREP_SST_OPT_HOST_UNESCAPED} ${TSST_PORT}" - else - # traditional netcat - tcmd="nc -q0 ${WSREP_SST_OPT_HOST_UNESCAPED} ${TSST_PORT}" - fi - fi - else - tfmt='socat' - wsrep_log_info "Using socat as streamer" - wsrep_check_programs socat - - donor_extra="" - joiner_extra="" - if [[ $encrypt -eq 2 || $encrypt -eq 3 || $encrypt -eq 4 ]]; then - if ! socat -V | grep -q WITH_OPENSSL; then - wsrep_log_error "******** FATAL ERROR ****************** " - wsrep_log_error "* socat is not openssl enabled. " - wsrep_log_error "* Unable to encrypt SST communications. " - wsrep_log_error "*************************************** " - exit 2 - fi - - # Determine the socat version - SOCAT_VERSION=`socat -V 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1` - if [[ -z "$SOCAT_VERSION" ]]; then - wsrep_log_error "******** FATAL ERROR **************** " - wsrep_log_error "* Cannot determine the socat version. " - wsrep_log_error "************************************* " - exit 2 - fi - - # socat versions < 1.7.3 will have 512-bit dhparams (too small) - # so create 2048-bit dhparams and send that as a parameter - # socat version >= 1.7.3, checks to see if the peername matches the hostname - # set commonname="" to disable the peername checks - # - if ! check_for_version "$SOCAT_VERSION" "1.7.3"; then - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then - # dhparams check (will create ssl_dhparams if needed) - check_for_dhparams - joiner_extra=",dhparam=$ssl_dhparams" - fi - fi - if check_for_version "$SOCAT_VERSION" "1.7.3"; then - donor_extra=',commonname=""' - fi - fi - - if [[ $encrypt -eq 2 ]]; then - wsrep_log_warning "**** WARNING **** encrypt=2 is deprecated and will be removed in a future release" - wsrep_log_info "Using openssl based encryption with socat: with crt and ca" - - verify_file_exists "$tcert" "Both certificate and CA files are required." \ - "Please check the 'tcert' option. " - verify_file_exists "$tca" "Both certificate and CA files are required." \ - "Please check the 'tca' option. " - - stagemsg+="-OpenSSL-Encrypted-2" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with CERT: $tcert, CA: $tca" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},cafile=${tca}${joiner_extra}${sockopt} stdio" - else - wsrep_log_info "Encrypting with CERT: $tcert, CA: $tca" - tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${tcert},cafile=${tca}${donor_extra}${sockopt}" - fi - elif [[ $encrypt -eq 3 ]];then - wsrep_log_warning "**** WARNING **** encrypt=3 is deprecated and will be removed in a future release" - wsrep_log_info "Using openssl based encryption with socat: with key and crt" - - verify_file_exists "$tcert" "Both certificate and key files are required." \ - "Please check the 'tcert' option. " - verify_file_exists "$tkey" "Both certificate and key files are required." \ - "Please check the 'tkey' option. " - - stagemsg+="-OpenSSL-Encrypted-3" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with CERT: $tcert, KEY: $tkey" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},key=${tkey},verify=0${joiner_extra}${sockopt} stdio" - else - wsrep_log_info "Encrypting with CERT: $tcert, KEY: $tkey" - tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${tcert},key=${tkey},verify=0${sockopt}" - fi - elif [[ $encrypt -eq 4 ]]; then - wsrep_log_info "Using openssl based encryption with socat: with key, crt, and ca" - - verify_file_exists "$ssl_ca" "CA, certificate, and key files are required." \ - "Please check the 'ssl-ca' option. " - verify_file_exists "$ssl_cert" "CA, certificate, and key files are required." \ - "Please check the 'ssl-cert' option. " - verify_file_exists "$ssl_key" "CA, certificate, and key files are required." \ - "Please check the 'ssl-key' option. " - - # Check to see that the key matches the cert - verify_cert_matches_key $ssl_cert $ssl_key - - stagemsg+="-OpenSSL-Encrypted-4" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then - wsrep_log_info "Decrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${joiner_extra}${sockopt} stdio" - else - wsrep_log_info "Encrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca" - tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${donor_extra}${sockopt}" - fi - - else - if [[ $encrypt -eq 1 ]]; then - wsrep_log_warning "**** WARNING **** encrypt=1 is deprecated and will be removed in a future release" - fi - - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then - tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" - else - tcmd="socat -u stdio TCP:${WSREP_SST_OPT_HOST}:${TSST_PORT}${sockopt}" - fi - 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 $MY_PRINT_DEFAULTS xtrabackup | grep -q -- "--compress";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+=" -s $payload" - adjust_progress -} - -adjust_progress() -{ - - if ! command -v pv >/dev/null;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 && $progress != '1' ]];then - if [[ -e $progress ]];then - pcmd+=" 2>>$progress" - else - pcmd+=" 2>$progress" - fi - elif [[ -z $progress && -n $rlimit ]];then - # When rlimit is non-zero - pcmd="pv -q" - fi - - if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then - wsrep_log_info "Rate-limiting SST to $rlimit" - pcmd+=" -L \$rlimit" - fi -} - -read_cnf() -{ - sfmt=$(parse_cnf sst streamfmt "xbstream") - tfmt=$(parse_cnf sst transferfmt "socat") - tca=$(parse_cnf sst tca "") - tcert=$(parse_cnf sst tcert "") - tkey=$(parse_cnf sst tkey "") - encrypt=$(parse_cnf sst encrypt 0) - sockopt=$(parse_cnf sst sockopt "") - progress=$(parse_cnf sst progress "") - rebuild=$(parse_cnf sst rebuild 0) - ttime=$(parse_cnf sst time 0) - if [ "${OS}" = "FreeBSD" ]; then - cpat=$(parse_cnf sst cpat '.*\.pem$|.*init\.ok$|.*galera\.cache$|.*sst_in_progress$|.*\.sst$|.*gvwstate\.dat$|.*grastate\.dat$|.*\.err$|.*\.log$|.*RPM_UPGRADE_MARKER$|.*RPM_UPGRADE_HISTORY$') - else - cpat=$(parse_cnf sst cpat '.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') - fi - ealgo=$(parse_cnf xtrabackup encrypt "") - ekey=$(parse_cnf xtrabackup encrypt-key "") - ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") - scomp=$(parse_cnf sst compressor "") - sdecomp=$(parse_cnf sst decompressor "") - - - # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html - if [[ -z $ealgo ]];then - ealgo=$(parse_cnf sst encrypt-algo "") - ekey=$(parse_cnf sst encrypt-key "") - ekeyfile=$(parse_cnf sst encrypt-key-file "") - fi - - # Pull the parameters needed for encrypt=4 - ssl_ca=$(parse_cnf sst ssl-ca "") - if [[ -z "$ssl_ca" ]]; then - ssl_ca=$(parse_cnf --mysqld ssl-ca "") - fi - ssl_cert=$(parse_cnf sst ssl-cert "") - if [[ -z "$ssl_cert" ]]; then - ssl_cert=$(parse_cnf --mysqld ssl-cert "") - fi - ssl_key=$(parse_cnf sst ssl-key "") - if [[ -z "$ssl_key" ]]; then - ssl_key=$(parse_cnf --mysqld ssl-key "") - fi - - rlimit=$(parse_cnf sst rlimit "") - uextra=$(parse_cnf sst use-extra 0) - 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 100) - ssyslog=$(parse_cnf sst sst-syslog 0) - ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") - ssystag+="-" - - if [[ $ssyslog -ne -1 ]];then - if $MY_PRINT_DEFAULTS mysqld_safe | grep -q -- "--syslog";then - ssyslog=1 - fi - fi -} - -get_stream() -{ - if [[ $sfmt == 'xbstream' ]];then - wsrep_log_info "Streaming with xbstream" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="xbstream -x" - else - strmcmd="xbstream -c \${INFO_FILE}" - fi - else - sfmt="tar" - wsrep_log_info "Streaming with tar" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="tar xfi - " - else - strmcmd="tar cf - \${INFO_FILE} " - fi - - fi -} - -get_proc() -{ - set +e - nproc=$(grep -c processor /proc/cpuinfo) - [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 - set -e -} - -sig_joiner_cleanup() -{ - wsrep_log_error "Removing $MAGIC_FILE file due to signal" - rm -f "$MAGIC_FILE" -} - -cleanup_joiner() -{ - # Since this is invoked just after exit NNN - local estatus=$? - if [[ $estatus -ne 0 ]];then - wsrep_log_error "Cleanup after exit with status:$estatus" - elif [ "${WSREP_SST_OPT_ROLE}" = "joiner" ];then - wsrep_log_info "Removing the sst_in_progress file" - wsrep_cleanup_progress_file - fi - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm $progress - fi - if [[ -n ${STATDIR:-} ]];then - [[ -d $STATDIR ]] && rm -rf $STATDIR - 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 -} - -check_pid() -{ - local pid_file="$1" - [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 -} - -cleanup_donor() -{ - # 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 [[ -n ${XTRABACKUP_PID:-} ]];then - if check_pid $XTRABACKUP_PID - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - fi - - fi - rm -f ${DATA}/${IST_FILE} || true - - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm -f $progress || true - fi - - wsrep_log_info "Cleaning up temporary directories" - - if [[ -n $xtmpdir ]];then - [[ -d $xtmpdir ]] && rm -rf $xtmpdir || true - fi - - if [[ -n $itmpdir ]];then - [[ -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 - -} - -kill_xtrabackup() -{ - local PID=$(cat $XTRABACKUP_PID) - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - wsrep_log_info "Removing xtrabackup pid file $XTRABACKUP_PID" - rm -f "$XTRABACKUP_PID" || true -} - -# waits ~1 minute for nc/socat to open the port and then reports ready -# (regardless of timeout) -wait_for_listen() -{ - local HOST=$1 - local PORT=$2 - local MODULE=$3 - local LSOF_OUT - - for i in {1..300} - do - LSOF_OUT=$(lsof -sTCP:LISTEN -i TCP:${PORT} -a -c nc -c socat -F c 2> /dev/null || :) - [ -n "${LSOF_OUT}" ] && break - sleep 0.2 - done - - echo "ready ${HOST}:${PORT}/${MODULE}//${WSREP_SST_OPT_SST_VER:-1}" -} - -check_extra() -{ - local use_socket=1 - if [[ $uextra -eq 1 ]];then - if [ $(parse_cnf --mysqld 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+=" --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 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then - INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" - fi -} - -recv_joiner() -{ - local dir=$1 - local msg=$2 - local tmt=$3 - local checkf=$4 - local ltcmd - - if [[ ! -d ${dir} ]];then - # This indicates that IST is in progress - return - fi - - pushd ${dir} 1>/dev/null - set +e - - if [[ $tmt -gt 0 ]] && command -v timeout >/dev/null;then - if timeout --help | grep -q -- '-k';then - ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" - else - ltcmd="timeout -s9 $tmt $tcmd" - fi - timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" - else - timeit "$msg" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" - fi - - set -e - popd 1>/dev/null - - if [[ ${RC[0]} -eq 124 ]];then - wsrep_log_error "Possible timeout in receving first data from donor in gtid stage" - 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 && ! -r "${MAGIC_FILE}" ]];then - # this message should cause joiner to abort - wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" - wsrep_log_info "Contents of datadir" - wsrep_log_info "$(ls -l ${dir}/*)" - exit 32 - 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 getting data from donor node: " \ - "exit codes: ${RC[@]}" - exit 32 - fi - done - -} - -# Returns the version string in a standardized format -# Input "1.2.3" => echoes "010203" -# Wrongly formatted values => echoes "000000" -normalize_version() -{ - local major=0 - local minor=0 - local patch=0 - - # Only parses purely numeric version numbers, 1.2.3 - # Everything after the first three values are ignored - if [[ $1 =~ ^([0-9]+)\.([0-9]+)\.?([0-9]*)([\.0-9])*$ ]]; then - major=${BASH_REMATCH[1]} - minor=${BASH_REMATCH[2]} - patch=${BASH_REMATCH[3]} - fi - - printf %02d%02d%02d $major $minor $patch -} - -# Compares two version strings -# The first parameter is the version to be checked -# The second parameter is the minimum version required -# Returns 1 (failure) if $1 >= $2, 0 (success) otherwise -check_for_version() -{ - local local_version_str="$( normalize_version $1 )" - local required_version_str="$( normalize_version $2 )" - - if [[ "$local_version_str" < "$required_version_str" ]]; then - return 1 - else - return 0 - fi -} - -monitor_process() -{ - local sst_stream_pid=$1 - - while true ; do - - if ! ps --pid "${WSREP_SST_OPT_PARENT}" &>/dev/null; then - wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." - kill -- -"${WSREP_SST_OPT_PARENT}" - exit 32 - fi - - if ! ps --pid "${sst_stream_pid}" &>/dev/null; then - break - fi - - sleep 0.1 - - done -} - - -wsrep_check_programs "$INNOBACKUPEX_BIN" - -# 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=`$INNOBACKUPEX_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 $INNOBACKUPEX_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 $INNOBACKUPEX_BIN version is $XB_VERSION. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" - exit 2 -fi - - -rm -f "${MAGIC_FILE}" - -if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then - wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" - exit 22 -fi - -read_cnf - -if ${INNOBACKUPEX_BIN} /tmp --help 2>/dev/null | grep -q -- '--version-check'; then - disver="--no-version-check" -fi - -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 " -fi - - -INNOEXTRA="" - -if [[ $ssyslog -eq 1 ]];then - - if ! command -v logger >/dev/null;then - wsrep_log_error "logger not in path: $PATH. Ignoring" - else - - wsrep_log_info "Logging all stderr of SST/Innobackupex 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 "$@" - } - - 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)" - fi - -else - INNOAPPLY="&>\${DATA}/innobackup.prepare.log" - INNOMOVE="&>\${DATA}/innobackup.move.log" - INNOBACKUP="2>\${DATA}/innobackup.backup.log" -fi - -get_stream -get_transfer - -INNODB_DATA_HOME_DIR=${INNODB_DATA_HOME_DIR:-""} -# Try to set INNODB_DATA_HOME_DIR from the command line: -if [ ! -z "$INNODB_DATA_HOME_DIR_ARG" ]; then - INNODB_DATA_HOME_DIR=$INNODB_DATA_HOME_DIR_ARG -fi -# if INNODB_DATA_HOME_DIR env. 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$WSREP_SST_OPT_SUFFIX_VALUE innodb-data-home-dir '') -fi -if [ -z "$INNODB_DATA_HOME_DIR" ]; then - INNODB_DATA_HOME_DIR=$(parse_cnf --mysqld innodb-data-home-dir "") -fi -if [ ! -z "$INNODB_DATA_HOME_DIR" ]; then - INNOEXTRA+=" --innodb-data-home-dir=$INNODB_DATA_HOME_DIR" -fi - -if [ -n "$INNODB_DATA_HOME_DIR" ]; then - # handle both relative and absolute paths - INNODB_DATA_HOME_DIR=$(cd $DATA; mkdir -p "$INNODB_DATA_HOME_DIR"; cd $INNODB_DATA_HOME_DIR; pwd -P) -else - # default to datadir - INNODB_DATA_HOME_DIR=$(cd $DATA; pwd -P) -fi - -INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts \$INNOEXTRA --apply-log \$rebuildcmd \${DATA} ${INNOAPPLY}" -INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} ${INNOMOVE}" -INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir ${INNOBACKUP}" - -if [ "$WSREP_SST_OPT_ROLE" = "donor" ] -then - trap cleanup_donor EXIT - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - usrst=0 - if [[ -z $WSREP_SST_OPT_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 - - if [[ -z $(parse_cnf --mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then - xtmpdir=$(mktemp -d) - tmpopts=" --tmpdir=$xtmpdir " - wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" - fi - - itmpdir=$(mktemp -d) - wsrep_log_info "Using $itmpdir as innobackupex temporary directory" - - if [[ -n "${WSREP_SST_OPT_USER:-}" && "$WSREP_SST_OPT_USER" != "(null)" ]]; then - INNOEXTRA+=" --user=$WSREP_SST_OPT_USER" - usrst=1 - fi - - if [ -n "${WSREP_SST_OPT_PSWD:-}" ]; then - INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" - elif [[ $usrst -eq 1 ]];then - # Empty password, used for testing, debugging etc. - INNOEXTRA+=" --password=" - fi - - get_keys - 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}" - - ttcmd="$tcmd" - - if [[ $encrypt -eq 1 ]];then - if [[ -n $scomp ]];then - tcmd=" \$ecmd | $scomp | $tcmd " - else - tcmd=" \$ecmd | $tcmd " - fi - elif [[ -n $scomp ]];then - tcmd=" $scomp | $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 ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT:-4444}" - - # 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 - - set +e - timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - - if [ ${RC[0]} -ne 0 ]; then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ - "Check ${DATA}/innobackup.backup.log" - 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 - XTRABACKUP_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}" - get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $scomp ]];then - tcmd=" \$ecmd | $scomp | $tcmd " - else - tcmd=" \$ecmd | $tcmd " - fi - elif [[ -n $scomp ]];then - tcmd=" $scomp | $tcmd " - fi - 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 - ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") - ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") - - stagemsg="Joiner-Recv" - - sencrypted=1 - nthreads=1 - - MODULE="xtrabackup_sst" - - rm -f "${DATA}/${IST_FILE}" - - # May need xtrabackup_checkpoints later on - rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile - - wait_for_listen ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT:-4444} ${MODULE} & - - trap sig_joiner_cleanup HUP PIPE INT TERM - trap cleanup_joiner EXIT - - if [[ -n $progress ]];then - adjust_progress - tcmd+=" | $pcmd" - fi - - get_keys - if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then - if [[ -n $sdecomp ]];then - strmcmd=" $sdecomp | \$ecmd | $strmcmd" - else - strmcmd=" \$ecmd | $strmcmd" - fi - elif [[ -n $sdecomp ]];then - strmcmd=" $sdecomp | $strmcmd" - fi - - STATDIR=$(mktemp -d) - MAGIC_FILE="${STATDIR}/${INFO_FILE}" - recv_joiner $STATDIR "${stagemsg}-gtid" $stimeout 1 - - - if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null - 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) & - 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_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ - else - find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ - fi - - tempdir=$(parse_cnf --mysqld log-bin "") - if [[ -n ${tempdir:-} ]];then - binlog_dir=$(dirname $tempdir) - binlog_file=$(basename $tempdir) - if [[ -n ${binlog_dir:-} && $binlog_dir != '.' && $binlog_dir != $DATA ]];then - pattern="$binlog_dir/$binlog_file\.[0-9]+$" - wsrep_log_info "Cleaning the binlog directory $binlog_dir as well" - find $binlog_dir -maxdepth 1 -type f -regex $pattern -exec rm -fv {} 1>&2 \+ || true - rm $binlog_dir/*.index || true - fi - fi - - - - TDATA=${DATA} - DATA="${DATA}/.sst" - - - MAGIC_FILE="${DATA}/${INFO_FILE}" - wsrep_log_info "Waiting for SST streaming to complete!" - monitor_process $jpid - - get_proc - - if [[ ! -s ${DATA}/xtrabackup_checkpoints ]];then - wsrep_log_error "xtrabackup_checkpoints missing, failed innobackupex/SST on donor" - exit 2 - fi - - # Rebuild indexes for compact backups - if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then - wsrep_log_info "Index compaction detected" - rebuild=1 - fi - - if [[ $rebuild -eq 1 ]];then - nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) - wsrep_log_info "Rebuilding during prepare with $nthreads threads" - rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" - fi - - if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then - - wsrep_log_info "Compressed qpress files found" - - if ! command -v qpress >/dev/null;then - wsrep_log_error "qpress not found in path: $PATH" - exit 22 - fi - - if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then - count=$(find ${DATA} -type f -name '*.qp' | wc -l) - count=$(( count*2 )) - if pv --help | grep -q FORMAT;then - pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" - else - pvopts="-f -s $count -l -N Decompression" - fi - pcmd="pv $pvopts" - adjust_progress - dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" - else - dcmd="xargs -n 2 qpress -T${nproc}d" - 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 [[ ! -z $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 - - pushd $BINLOG_DIRNAME &>/dev/null - for bfiles in $(ls -1 ${BINLOG_FILENAME}.[0-9]*);do - echo ${BINLOG_DIRNAME}/${bfiles} >> ${BINLOG_FILENAME}.index - done - popd &> /dev/null - - fi - - wsrep_log_info "Preparing the backup at ${DATA}" - timeit "Xtrabackup prepare stage" "$INNOAPPLY" - - if [ $? -ne 0 ]; - then - wsrep_log_error "${INNOBACKUPEX_BIN} apply finished with errors. Check ${DATA}/innobackup.prepare.log" - exit 22 - fi - - MAGIC_FILE="${TDATA}/${INFO_FILE}" - set +e - rm $TDATA/innobackup.prepare.log $TDATA/innobackup.move.log - set -e - 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 ${DATA}/innobackup.move.log 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 - wsrep_log_info "Galera co-ords from recovery: $(cat ${MAGIC_FILE})" - cat "${MAGIC_FILE}" # Output : UUID:seqno wsrep_gtid_domain_id - wsrep_log_info "Total time on joiner: $totime seconds" -fi - -exit 0 diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh deleted file mode 100644 index 41ed4485de5..00000000000 --- a/scripts/wsrep_sst_xtrabackup.sh +++ /dev/null @@ -1,692 +0,0 @@ -#!/bin/bash -ue -# 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-1301 USA. - -# Optional dependencies and options documented here: http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html -# Make sure to read that before proceeding! - - - - -. $(dirname $0)/wsrep_sst_common - -ealgo="" -ekey="" -ekeyfile="" -encrypt=0 -nproc=1 -ecode=0 -XTRABACKUP_PID="" -tcert="" -tpem="" -sockopt="" -progress="" -ttime=0 -totime=0 -lsn="${WSREP_SST_OPT_LSN}" -incremental=0 -ecmd="" -rlimit="" - -sfmt="tar" -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 " -uextra=0 - -if pv --help 2>/dev/null | grep -q FORMAT;then - pvopts+=$pvformat -fi -pcmd="pv $pvopts" -declare -a RC - -INNOBACKUPEX_BIN=innobackupex -DATA="${WSREP_SST_OPT_DATA}" -INFO_FILE="xtrabackup_galera_info" -IST_FILE="xtrabackup_ist" -MAGIC_FILE="${DATA}/${INFO_FILE}" - -# 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() -{ - if [[ $encrypt -eq 2 ]];then - return - fi - - if [[ $encrypt -eq 0 ]];then - if $MY_PRINT_DEFAULTS xtrabackup | grep -q encrypt;then - wsrep_log_error "Unexpected option combination. SST may fail. Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html " - fi - return - fi - - if [[ $sfmt == 'tar' ]];then - wsrep_log_info "NOTE: Xtrabackup-based encryption - encrypt=1 - cannot be enabled with tar format" - encrypt=0 - return - fi - - wsrep_log_info "Xtrabackup 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 && ! -r $ekeyfile ]];then - wsrep_log_error "FATAL: Either key or keyfile must be readable" - exit 3 - fi - - if [[ -z $ekey ]];then - ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" - else - ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" - fi - - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - ecmd+=" -d" - fi -} - -get_transfer() -{ - TSST_PORT=${WSREP_SST_OPT_PORT:-4444} - - if [[ $tfmt == 'nc' ]];then - wsrep_check_programs nc - wsrep_log_info "Using netcat as streamer" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - if nc -h 2>&1 | grep -q ncat;then - # Ncat - tcmd="nc -l ${TSST_PORT}" - elif nc -h 2>&1 | grep -q -- '-d\>';then - # Debian netcat - tcmd="nc -dl ${TSST_PORT}" - else - # traditional netcat - tcmd="nc -l -p ${TSST_PORT}" - fi - else - if nc -h 2>&1 | grep -q ncat;then - # Ncat - tcmd="nc ${REMOTEIP} ${TSST_PORT}" - elif nc -h 2>&1 | grep -q -- '-d\>';then - # Debian netcat - tcmd="nc ${REMOTEIP} ${TSST_PORT}" - else - # traditional netcat - tcmd="nc -q0 ${REMOTEIP} ${TSST_PORT}" - fi - fi - else - tfmt='socat' - wsrep_check_programs socat - wsrep_log_info "Using socat as streamer" - - if [[ $encrypt -eq 2 ]] && ! socat -V | grep -q OPENSSL;then - wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" - encrypt=0 - fi - - if [[ $encrypt -eq 2 ]];then - wsrep_log_info "Using openssl based encryption with socat" - if [[ -z $tpem || -z $tcert ]];then - wsrep_log_error "Both PEM and CRT files required" - exit 22 - fi - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" - else - wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" - tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" - fi - else - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" - else - tcmd="socat -u stdio TCP:${WSREP_SST_OPT_HOST}:${TSST_PORT}${sockopt}" - fi - 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 $MY_PRINT_DEFAULTS xtrabackup | grep -q -- "--compress";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+=" -s $payload" - adjust_progress -} - -adjust_progress() -{ - if [[ -n $progress && $progress != '1' ]];then - if [[ -e $progress ]];then - pcmd+=" 2>>$progress" - else - pcmd+=" 2>$progress" - fi - elif [[ -z $progress && -n $rlimit ]];then - # When rlimit is non-zero - pcmd="pv -q" - fi - - if [[ -n $rlimit && "$WSREP_SST_OPT_ROLE" == "donor" ]];then - wsrep_log_info "Rate-limiting SST to $rlimit" - pcmd+=" -L \$rlimit" - fi -} - -read_cnf() -{ - sfmt=$(parse_cnf sst streamfmt "tar") - tfmt=$(parse_cnf sst transferfmt "socat") - tcert=$(parse_cnf sst tca "") - tpem=$(parse_cnf sst tcert "") - encrypt=$(parse_cnf sst encrypt 0) - sockopt=$(parse_cnf sst sockopt "") - progress=$(parse_cnf sst progress "") - rebuild=$(parse_cnf sst rebuild 0) - ttime=$(parse_cnf sst time 0) - incremental=$(parse_cnf sst incremental 0) - ealgo=$(parse_cnf xtrabackup encrypt "") - ekey=$(parse_cnf xtrabackup encrypt-key "") - ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") - - # Refer to http://www.percona.com/doc/percona-xtradb-cluster/manual/xtrabackup_sst.html - if [[ -z $ealgo ]];then - ealgo=$(parse_cnf sst encrypt-algo "") - ekey=$(parse_cnf sst encrypt-key "") - ekeyfile=$(parse_cnf sst encrypt-key-file "") - fi - rlimit=$(parse_cnf sst rlimit "") - uextra=$(parse_cnf sst use_extra 0) -} - -get_stream() -{ - if [[ $sfmt == 'xbstream' ]];then - wsrep_log_info "Streaming with xbstream" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="xbstream -x" - else - strmcmd="xbstream -c \${INFO_FILE} \${IST_FILE}" - fi - else - sfmt="tar" - wsrep_log_info "Streaming with tar" - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - strmcmd="tar xfi - --recursive-unlink -h" - else - strmcmd="tar cf - \${INFO_FILE} \${IST_FILE}" - fi - - fi -} - -get_proc() -{ - set +e - nproc=$(grep -c processor /proc/cpuinfo) - [[ -z $nproc || $nproc -eq 0 ]] && nproc=1 - set -e -} - -sig_joiner_cleanup() -{ - wsrep_log_error "Removing $MAGIC_FILE file due to signal" - rm -f "$MAGIC_FILE" -} - -cleanup_joiner() -{ - # 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 - fi - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm $progress - fi -} - -check_pid() -{ - local pid_file="$1" - [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 -} - -cleanup_donor() -{ - # 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 [[ -n $XTRABACKUP_PID ]];then - if check_pid $XTRABACKUP_PID - then - wsrep_log_error "xtrabackup process is still running. Killing... " - kill_xtrabackup - fi - - rm -f $XTRABACKUP_PID - fi - rm -f ${DATA}/${IST_FILE} - - if [[ -n $progress && -p $progress ]];then - wsrep_log_info "Cleaning up fifo file $progress" - rm $progress - fi -} - -kill_xtrabackup() -{ - local PID=$(cat $XTRABACKUP_PID) - [ -n "$PID" -a "0" != "$PID" ] && kill $PID && (kill $PID && kill -9 $PID) || : - rm -f "$XTRABACKUP_PID" -} - -# waits ~10 seconds for 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..50} - do - ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break - sleep 0.2 - done - if [[ $incremental -eq 1 ]];then - echo "ready ${ADDR}/${MODULE}/$lsn" - else - echo "ready ${ADDR}/${MODULE}" - fi -} - -check_extra() -{ - local use_socket=1 - if [[ $uextra -eq 1 ]];then - if [ $(parse_cnf --mysqld 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+=" --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 ]] && [[ -n "${WSREP_SST_OPT_SOCKET}" ]];then - INNOEXTRA+=" --socket=${WSREP_SST_OPT_SOCKET}" - fi -} - -wsrep_check_programs "innobackupex" - -rm -f "${MAGIC_FILE}" - -if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then - wsrep_log_error "Invalid role ${WSREP_SST_OPT_ROLE}" - exit 22 -fi - -read_cnf -get_stream -get_transfer - -INNOEXTRA="" -INNOAPPLY="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" -INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} \$INNOEXTRA --galera-info --stream=\$sfmt \${TMPDIR} 2>\${DATA}/innobackup.backup.log" - -if [ "$WSREP_SST_OPT_ROLE" = "donor" ] -then - trap cleanup_donor EXIT - - if [ $WSREP_SST_OPT_BYPASS -eq 0 ] - then - usrst=0 - TMPDIR="${TMPDIR:-/tmp}" - - if [[ -n "${WSREP_SST_OPT_USER:-}" && "$WSREP_SST_OPT_USER" != "(null)" ]]; then - INNOEXTRA+=" --user=$WSREP_SST_OPT_USER" - usrst=1 - fi - - if [ -n "${WSREP_SST_OPT_PSWD:-}" ]; then - INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" - elif [[ $usrst -eq 1 ]];then - # Empty password, used for testing, debugging etc. - INNOEXTRA+=" --password=" - fi - - get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $ekey ]];then - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " - else - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " - fi - fi - - if [[ -n $lsn ]];then - INNOEXTRA+=" --incremental --incremental-lsn=$lsn " - fi - - check_extra - - wsrep_log_info "Streaming the backup to joiner at ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT}" - - if [[ -n $progress ]];then - get_footprint - tcmd="$pcmd | $tcmd" - elif [[ -n $rlimit ]];then - adjust_progress - tcmd="$pcmd | $tcmd" - fi - - set +e - timeit "Donor-Transfer" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" - set -e - - if [ ${RC[0]} -ne 0 ]; then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with error: ${RC[0]}. " \ - "Check ${DATA}/innobackup.backup.log" - 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 ${TMPDIR} - XTRABACKUP_PID="${TMPDIR}/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}" - get_keys - pushd ${DATA} 1>/dev/null - set +e - if [[ $encrypt -eq 1 ]];then - tcmd=" $ecmd | $tcmd" - fi - timeit "Donor-IST-Unencrypted-transfer" "$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 streaming data to joiner node: " \ - "exit codes: ${RC[@]}" - exit 1 - fi - done - 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" - touch $SST_PROGRESS_FILE - - if [[ ! -e ${DATA}/ibdata1 ]];then - incremental=0 - fi - - if [[ $incremental -eq 1 ]];then - wsrep_log_info "Incremental SST enabled" - #lsn=$(/pxc/bin/mysqld $WSREP_SST_OPT_CONF --basedir=/pxc --wsrep-recover 2>&1 | grep -o 'log sequence number .*' | cut -d " " -f 4 | head -1) - lsn=$(grep to_lsn xtrabackup_checkpoints | cut -d= -f2 | tr -d ' ') - wsrep_log_info "Recovered LSN: $lsn" - fi - - sencrypted=1 - nthreads=1 - - MODULE="xtrabackup_sst" - - # May need xtrabackup_checkpoints later on - rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile - - ADDR="${WSREP_SST_OPT_HOST}:${WSREP_SST_OPT_PORT:-4444}" - - wait_for_listen ${WSREP_SST_OPT_PORT:-4444} ${ADDR} ${MODULE} & - - trap sig_joiner_cleanup HUP PIPE INT TERM - trap cleanup_joiner EXIT - - if [[ -n $progress ]];then - adjust_progress - tcmd+=" | $pcmd" - fi - - if [[ $incremental -eq 1 ]];then - BDATA=$DATA - DATA=$(mktemp -d) - MAGIC_FILE="${DATA}/${INFO_FILE}" - fi - - get_keys - set +e - if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then - strmcmd=" $ecmd | $strmcmd" - fi - - pushd ${DATA} 1>/dev/null - timeit "Joiner-Recv-Unencrypted" "$tcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" - popd 1>/dev/null - - set -e - - if [[ $sfmt == 'xbstream' ]];then - # Special handling till lp:1193240 is fixed" - if [[ ${RC[$(( ${#RC[@]}-1 ))]} -eq 1 ]];then - wsrep_log_error "Xbstream failed" - wsrep_log_error "Data directory ${DATA} may not be empty: lp:1193240" \ - "Manual intervention required in that case" - exit 32 - fi - fi - - wait %% # join for wait_for_listen thread - - 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 [ ! -r "${MAGIC_FILE}" ] - then - # this message should cause joiner to abort - wsrep_log_error "xtrabackup process ended without creating '${MAGIC_FILE}'" - wsrep_log_info "Contents of datadir" - wsrep_log_info "$(ls -l ${DATA}/**/*)" - exit 32 - fi - - if ! ps -p ${WSREP_SST_OPT_PARENT} &>/dev/null - then - wsrep_log_error "Parent mysqld process (PID:${WSREP_SST_OPT_PARENT}) terminated unexpectedly." - exit 32 - fi - - if [ ! -r "${DATA}/${IST_FILE}" ] - then - wsrep_log_info "Proceeding with SST" - wsrep_log_info "Removing existing ib_logfile files" - if [[ $incremental -ne 1 ]];then - rm -f ${DATA}/ib_logfile* - else - rm -f ${BDATA}/ib_logfile* - fi - - get_proc - - # Rebuild indexes for compact backups - if grep -q 'compact = 1' ${DATA}/xtrabackup_checkpoints;then - wsrep_log_info "Index compaction detected" - rebuild=1 - fi - - if [[ $rebuild -eq 1 ]];then - nthreads=$(parse_cnf xtrabackup rebuild-threads $nproc) - wsrep_log_info "Rebuilding during prepare with $nthreads threads" - rebuildcmd="--rebuild-indexes --rebuild-threads=$nthreads" - fi - - if test -n "$(find ${DATA} -maxdepth 1 -type f -name '*.qp' -print -quit)";then - - wsrep_log_info "Compressed qpress files found" - - if ! command -v qpress >/dev/null;then - wsrep_log_error "qpress not found in path: $PATH" - exit 22 - fi - - if [[ -n $progress ]] && pv --help | grep -q 'line-mode';then - count=$(find ${DATA} -type f -name '*.qp' | wc -l) - count=$(( count*2 )) - if pv --help | grep -q FORMAT;then - pvopts="-f -s $count -l -N Decompression -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" - else - pvopts="-f -s $count -l -N Decompression" - fi - pcmd="pv $pvopts" - adjust_progress - dcmd="$pcmd | xargs -n 2 qpress -T${nproc}d" - else - dcmd="xargs -n 2 qpress -T${nproc}d" - fi - - wsrep_log_info "Removing existing ibdata1 file" - rm -f ${DATA}/ibdata1 - - # Decompress the qpress files - wsrep_log_info "Decompression with $nproc threads" - timeit "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 [[ $incremental -eq 1 ]];then - # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. - INNOAPPLY="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} \ - --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" - fi - - wsrep_log_info "Preparing the backup at ${DATA}" - timeit "Xtrabackup prepare stage" "$INNOAPPLY" - - if [[ $incremental -eq 1 ]];then - wsrep_log_info "Cleaning up ${DATA} after incremental SST" - [[ -d ${DATA} ]] && rm -rf ${DATA} - DATA=$BDATA - fi - - if [ $? -ne 0 ]; - then - wsrep_log_error "${INNOBACKUPEX_BIN} finished with errors. Check ${DATA}/innobackup.prepare.log" - 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 - - cat "${MAGIC_FILE}" # Output : UUID:seqno wsrep_gtid_domain_id - wsrep_log_info "Total time on joiner: $totime seconds" -fi - -exit 0 diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index e648a7f4c69..7a542ab88f1 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -803,6 +803,7 @@ ssize_t wsrep_sst_prepare (void** msg) { const char* addr_in= NULL; const char* addr_out= NULL; + const char* method; if (!strcmp(wsrep_sst_method, WSREP_SST_SKIP)) { @@ -861,7 +862,8 @@ ssize_t wsrep_sst_prepare (void** msg) } ssize_t addr_len= -ENOSYS; - if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP)) + method = wsrep_sst_method; + if (!strcmp(method, WSREP_SST_MYSQLDUMP)) { addr_len= sst_prepare_mysqldump (addr_in, &addr_out); if (addr_len < 0) unireg_abort(1); @@ -871,6 +873,13 @@ ssize_t wsrep_sst_prepare (void** msg) /*! A heuristic workaround until we learn how to stop and start engines */ if (SE_initialized) { + if (!strcmp(method, WSREP_SST_XTRABACKUP) || + !strcmp(method, WSREP_SST_XTRABACKUPV2)) + { + WSREP_WARN("The %s SST method is deprecated, so it is automatically " + "replaced by %s", method, WSREP_SST_MARIABACKUP); + method = WSREP_SST_MARIABACKUP; + } // we already did SST at initializaiton, now engines are running // sql_print_information() is here because the message is too long // for WSREP_INFO. @@ -880,28 +889,28 @@ ssize_t wsrep_sst_prepare (void** msg) "Wsrep provider won't be able to fall back to it " "if other means of state transfer are unavailable. " "In that case you will need to restart the server.", - wsrep_sst_method); + method); *msg = 0; return 0; } - addr_len = sst_prepare_other (wsrep_sst_method, sst_auth_real, + addr_len = sst_prepare_other (method, sst_auth_real, addr_in, &addr_out); if (addr_len < 0) { WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", - wsrep_sst_method); + method); unireg_abort(1); } } - size_t const method_len(strlen(wsrep_sst_method)); + size_t const method_len(strlen(method)); size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); *msg = malloc (msg_len); if (NULL != *msg) { char* const method_ptr(reinterpret_cast<char*>(*msg)); - strcpy (method_ptr, wsrep_sst_method); + strcpy (method_ptr, method); char* const addr_ptr(method_ptr + method_len + 1); strcpy (addr_ptr, addr_out); diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index cc0f1f5389d..29724a00797 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -49,6 +49,9 @@ #define WSREP_SST_MYSQLDUMP "mysqldump" #define WSREP_SST_RSYNC "rsync" #define WSREP_SST_SKIP "skip" +#define WSREP_SST_MARIABACKUP "mariabackup" +#define WSREP_SST_XTRABACKUP "xtrabackup" +#define WSREP_SST_XTRABACKUPV2 "xtrabackupv2" #define WSREP_SST_DEFAULT WSREP_SST_RSYNC #define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_SST_AUTH_MASK "********" |