1#!/usr/local/bin/bash 2 3set -ue 4 5# Copyright (C) 2009-2015 Codership Oy 6# Copyright (C) 2017-2021 MariaDB 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; version 2 of the License. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; see the file COPYING. If not, write to the 19# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston 20# MA 02110-1335 USA. 21 22# This is a reference script for mysqldump-based state snapshot tansfer 23 24. $(dirname "$0")/wsrep_sst_common 25 26EINVAL=22 27 28if test -z "$WSREP_SST_OPT_HOST"; then wsrep_log_error "HOST cannot be nil"; exit $EINVAL; fi 29if test -z "$WSREP_SST_OPT_PORT"; then wsrep_log_error "PORT cannot be nil"; exit $EINVAL; fi 30if test -z "$WSREP_SST_OPT_LPORT"; then wsrep_log_error "LPORT cannot be nil"; exit $EINVAL; fi 31if test -z "$WSREP_SST_OPT_SOCKET";then wsrep_log_error "SOCKET cannot be nil";exit $EINVAL; fi 32if test -z "$WSREP_SST_OPT_GTID"; then wsrep_log_error "GTID cannot be nil"; exit $EINVAL; fi 33 34if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED" && \ 35 [ "$WSREP_SST_OPT_PORT" = "$WSREP_SST_OPT_LPORT" ] 36then 37 wsrep_log_error \ 38 "destination address '$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT' matches source address." 39 exit $EINVAL 40fi 41 42# Check client version 43if ! $MYSQL_CLIENT --version | grep 'Distrib 10\.[1-9]' >/dev/null 44then 45 $MYSQL_CLIENT --version >&2 46 wsrep_log_error "this operation requires MySQL client version 10.1 or newer" 47 exit $EINVAL 48fi 49 50AUTH="" 51usrst=0 52if [ -n "$WSREP_SST_OPT_USER" ]; then 53 AUTH="-u$WSREP_SST_OPT_USER" 54 usrst=1 55fi 56 57# Refs https://github.com/codership/mysql-wsrep/issues/141 58# Passing password in MYSQL_PWD environment variable is considered 59# "extremely insecure" by MySQL Guidelines for Password Security 60# (https://dev.mysql.com/doc/refman/5.6/en/password-security-user.html) 61# that is even less secure than passing it on a command line! It is doubtful: 62# the whole command line is easily observable by any unprivileged user via ps, 63# whereas (at least on Linux) unprivileged user can't see process environment 64# that he does not own. So while it may be not secure in the NSA sense of the 65# word, it is arguably more secure than passing password on the command line. 66if [ -n "$WSREP_SST_OPT_PSWD" ]; then 67 export MYSQL_PWD="$WSREP_SST_OPT_PSWD" 68elif [ $usrst -eq 1 ]; then 69 # Empty password, used for testing, debugging etc. 70 unset MYSQL_PWD 71fi 72 73STOP_WSREP='SET wsrep_on=OFF;' 74 75# mysqldump cannot restore CSV tables, fix this issue 76CSV_TABLES_FIX=" 77set sql_mode=''; 78 79USE mysql; 80 81SET @cond = (SELECT (SUPPORT = 'YES' or SUPPORT = 'DEFAULT') FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'csv'); 82 83SET @stmt = IF (@cond = '1', 'CREATE TABLE IF NOT EXISTS general_log ( event_time timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), user_host mediumtext NOT NULL, thread_id bigint(21) unsigned NOT NULL, server_id int(10) unsigned NOT NULL, command_type varchar(64) NOT NULL, argument mediumtext NOT NULL) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT=\"General log\"', 'SET @dummy = 0'); 84 85PREPARE stmt FROM @stmt; 86EXECUTE stmt; 87DROP PREPARE stmt; 88 89SET @stmt = IF (@cond = '1', 'CREATE TABLE IF NOT EXISTS slow_log ( start_time timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), user_host mediumtext NOT NULL, query_time time(6) NOT NULL, lock_time time(6) NOT NULL, rows_sent int(11) NOT NULL, rows_examined int(11) NOT NULL, db varchar(512) NOT NULL, last_insert_id int(11) NOT NULL, insert_id int(11) NOT NULL, server_id int(10) unsigned NOT NULL, sql_text mediumtext NOT NULL, thread_id bigint(21) unsigned NOT NULL) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COMMENT=\"Slow log\"', 'SET @dummy = 0'); 90 91PREPARE stmt FROM @stmt; 92EXECUTE stmt; 93DROP PREPARE stmt;" 94 95SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" 96 97SET_WSREP_GTID_DOMAIN_ID="" 98if [ -n $WSREP_SST_OPT_GTID_DOMAIN_ID ]; then 99 SET_WSREP_GTID_DOMAIN_ID=" 100 SET @val = (SELECT GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME = 'WSREP_GTID_STRICT_MODE' AND GLOBAL_VALUE > 0); 101 SET @stmt = IF (@val IS NOT NULL, 'SET GLOBAL WSREP_GTID_DOMAIN_ID=$WSREP_SST_OPT_GTID_DOMAIN_ID', 'SET @dummy = 0'); 102 PREPARE stmt FROM @stmt; 103 EXECUTE stmt; 104 DROP PREPARE stmt;" 105fi 106 107MYSQL="$MYSQL_CLIENT$WSREP_SST_OPT_CONF_UNQUOTED "\ 108"$AUTH -h$WSREP_SST_OPT_HOST_UNESCAPED "\ 109"-P$WSREP_SST_OPT_PORT --disable-reconnect --connect_timeout=10" 110 111# Check if binary logging is enabled on the joiner node. 112# Note: SELECT cannot be used at this point. 113LOG_BIN=$(echo "set statement wsrep_sync_wait=0 for SHOW VARIABLES LIKE 'log_bin'" | $MYSQL | \ 114tail -1 | awk -F ' ' '{ print $2 }') 115 116# Check the joiner node's server version. 117SERVER_VERSION=$(echo "set statement wsrep_sync_wait=0 for SHOW VARIABLES LIKE 'version'" | $MYSQL | \ 118tail -1 | awk -F ' ' '{ print $2 }') 119 120# Retrieve the donor's @@global.gtid_binlog_state. 121GTID_BINLOG_STATE=$(echo "SHOW GLOBAL VARIABLES LIKE 'gtid_binlog_state'" | $MYSQL | \ 122tail -1 | awk -F ' ' '{ print $2 }') 123 124RESET_MASTER="" 125SET_GTID_BINLOG_STATE="" 126SQL_LOG_BIN_OFF="" 127 128# Safety check 129if [ ${SERVER_VERSION%%.*} -gt 5 ]; then 130 # If binary logging is enabled on the joiner node, we need to copy donor's 131 # gtid_binlog_state to joiner. In order to do that, a RESET MASTER must be 132 # executed to erase binary logs (if any). Binary logging should also be 133 # turned off for the session so that gtid state does not get altered while 134 # the dump gets replayed on joiner. 135 if [ "$LOG_BIN" = 'ON' ]; then 136 RESET_MASTER="SET GLOBAL wsrep_on=OFF; RESET MASTER; SET GLOBAL wsrep_on=ON;" 137 SET_GTID_BINLOG_STATE="SET GLOBAL wsrep_on=OFF; SET @@global.gtid_binlog_state='$GTID_BINLOG_STATE'; SET GLOBAL wsrep_on=ON;" 138 SQL_LOG_BIN_OFF="SET @@session.sql_log_bin=OFF;" 139 fi 140fi 141 142# NOTE: we don't use --routines here because we're dumping mysql.proc table 143MYSQLDUMP="$MYSQLDUMP$WSREP_SST_OPT_CONF_UNQUOTED $AUTH -S$WSREP_SST_OPT_SOCKET \ 144--add-drop-database --add-drop-table --skip-add-locks --create-options \ 145--disable-keys --extended-insert --skip-lock-tables --quick --set-charset \ 146--skip-comments --flush-privileges --all-databases --events" 147 148if [ $WSREP_SST_OPT_BYPASS -eq 0 ] 149then 150 # need to disable logging when loading the dump 151 # reason is that dump contains ALTER TABLE for log tables, and 152 # this causes an error if logging is enabled 153 GENERAL_LOG_OPT=$($MYSQL --skip-column-names -e "$STOP_WSREP SELECT @@GENERAL_LOG") 154 SLOW_LOG_OPT=$($MYSQL --skip-column-names -e "$STOP_WSREP SELECT @@SLOW_QUERY_LOG") 155 156 LOG_OFF="SET GLOBAL GENERAL_LOG=OFF; SET GLOBAL SLOW_QUERY_LOG=OFF;" 157 158 # commands to restore log settings 159 RESTORE_GENERAL_LOG="SET GLOBAL GENERAL_LOG=$GENERAL_LOG_OPT;" 160 RESTORE_SLOW_QUERY_LOG="SET GLOBAL SLOW_QUERY_LOG=$SLOW_LOG_OPT;" 161 162 (echo "$STOP_WSREP" && echo "$LOG_OFF" && echo "$RESET_MASTER" && \ 163 echo "$SET_GTID_BINLOG_STATE" && echo "$SQL_LOG_BIN_OFF" && \ 164 echo "$STOP_WSREP" && $MYSQLDUMP && echo "$CSV_TABLES_FIX" && \ 165 echo "$RESTORE_GENERAL_LOG" && echo "$RESTORE_SLOW_QUERY_LOG" && \ 166 echo "$SET_START_POSITION" && echo "$SET_WSREP_GTID_DOMAIN_ID" \ 167 || echo "SST failed to complete;") | $MYSQL 168else 169 wsrep_log_info "Bypassing state dump." 170 echo "$SET_START_POSITION" | $MYSQL 171fi 172 173# 174