1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä
2022-02-25 13:00:48 +02:00
45 changed files with 1436 additions and 614 deletions

View File

@@ -578,7 +578,6 @@ datafile_read(datafile_cur_t *cursor)
Check to see if a file exists. Check to see if a file exists.
Takes name of the file to check. Takes name of the file to check.
@return true if file exists. */ @return true if file exists. */
static
bool bool
file_exists(const char *filename) file_exists(const char *filename)
{ {
@@ -1540,13 +1539,14 @@ bool backup_start(CorruptedPages &corrupted_pages)
if (!write_galera_info(mysql_connection)) { if (!write_galera_info(mysql_connection)) {
return(false); return(false);
} }
write_current_binlog_file(mysql_connection);
} }
if (opt_binlog_info == BINLOG_INFO_ON) { bool with_binlogs = opt_binlog_info == BINLOG_INFO_ON;
lock_binlog_maybe(mysql_connection); if (with_binlogs || opt_galera_info) {
write_binlog_info(mysql_connection); if (!write_current_binlog_file(mysql_connection, with_binlogs)) {
return(false);
}
} }
if (have_flush_engine_logs && !opt_no_lock) { if (have_flush_engine_logs && !opt_no_lock) {
@@ -1580,15 +1580,34 @@ void backup_release()
} }
} }
static const char *default_buffer_pool_file = "ib_buffer_pool";
static
const char * get_buffer_pool_filename(size_t *length)
{
/* If mariabackup is run for Galera, then the file
name is changed to the default so that the receiving
node can find this file and rename it according to its
settings, otherwise we keep the original file name: */
size_t dir_length = 0;
const char *dst_name = default_buffer_pool_file;
if (!opt_galera_info) {
dir_length = dirname_length(buffer_pool_filename);
dst_name = buffer_pool_filename + dir_length;
}
if (length) {
*length=dir_length;
}
return dst_name;
}
/** Finish after backup_start() and backup_release() */ /** Finish after backup_start() and backup_release() */
bool backup_finish() bool backup_finish()
{ {
/* Copy buffer pool dump or LRU dump */ /* Copy buffer pool dump or LRU dump */
if (!opt_rsync) { if (!opt_rsync) {
if (buffer_pool_filename && file_exists(buffer_pool_filename)) { if (buffer_pool_filename && file_exists(buffer_pool_filename)) {
const char *dst_name; const char *dst_name = get_buffer_pool_filename(NULL);
dst_name = trim_dotslash(buffer_pool_filename);
copy_file(ds_data, buffer_pool_filename, dst_name, 0); copy_file(ds_data, buffer_pool_filename, dst_name, 0);
} }
if (file_exists("ib_lru_dump")) { if (file_exists("ib_lru_dump")) {
@@ -1677,17 +1696,14 @@ ibx_copy_incremental_over_full()
/* copy buffer pool dump */ /* copy buffer pool dump */
if (innobase_buffer_pool_filename) { if (innobase_buffer_pool_filename) {
const char *src_name; const char *src_name = get_buffer_pool_filename(NULL);
src_name = trim_dotslash(innobase_buffer_pool_filename);
snprintf(path, sizeof(path), "%s/%s", snprintf(path, sizeof(path), "%s/%s",
xtrabackup_incremental_dir, xtrabackup_incremental_dir,
src_name); src_name);
if (file_exists(path)) { if (file_exists(path)) {
copy_file(ds_data, path, copy_file(ds_data, path, src_name, 0);
innobase_buffer_pool_filename, 0);
} }
} }
@@ -1922,6 +1938,14 @@ copy_back()
datadir_node_init(&node); datadir_node_init(&node);
/* If mariabackup is run for Galera, then the file
name is changed to the default so that the receiving
node can find this file and rename it according to its
settings, otherwise we keep the original file name: */
size_t dir_length;
const char *src_buffer_pool;
src_buffer_pool = get_buffer_pool_filename(&dir_length);
while (datadir_iter_next(it, &node)) { while (datadir_iter_next(it, &node)) {
const char *ext_list[] = {"backup-my.cnf", const char *ext_list[] = {"backup-my.cnf",
"xtrabackup_binary", "xtrabackup_binlog_info", "xtrabackup_binary", "xtrabackup_binlog_info",
@@ -1984,6 +2008,11 @@ copy_back()
continue; continue;
} }
/* skip buffer pool dump */
if (!strcmp(filename, src_buffer_pool)) {
continue;
}
/* skip innodb data files */ /* skip innodb data files */
is_ibdata_file = false; is_ibdata_file = false;
for (Tablespace::const_iterator iter(srv_sys_space.begin()), for (Tablespace::const_iterator iter(srv_sys_space.begin()),
@@ -2006,23 +2035,18 @@ copy_back()
/* copy buffer pool dump */ /* copy buffer pool dump */
if (innobase_buffer_pool_filename) { if (file_exists(src_buffer_pool)) {
const char *src_name; char dst_dir[FN_REFLEN];
char path[FN_REFLEN]; while (IS_TRAILING_SLASH(buffer_pool_filename, dir_length)) {
dir_length--;
src_name = trim_dotslash(innobase_buffer_pool_filename); }
memcpy(dst_dir, buffer_pool_filename, dir_length);
snprintf(path, sizeof(path), "%s/%s", dst_dir[dir_length] = 0;
mysql_data_home, if (!(ret = copy_or_move_file(src_buffer_pool,
src_name); src_buffer_pool,
dst_dir, 1)))
/* could be already copied with other files {
from data directory */ goto cleanup;
if (file_exists(src_name) &&
!file_exists(innobase_buffer_pool_filename)) {
copy_or_move_file(src_name,
innobase_buffer_pool_filename,
mysql_data_home, 0);
} }
} }

View File

@@ -32,6 +32,13 @@ copy_file(ds_ctxt_t *datasink,
const char *dst_file_path, const char *dst_file_path,
uint thread_n); uint thread_n);
/************************************************************************
Check to see if a file exists.
Takes name of the file to check.
@return true if file exists. */
bool
file_exists(const char *filename);
/** Start --backup */ /** Start --backup */
bool backup_start(CorruptedPages &corrupted_pages); bool backup_start(CorruptedPages &corrupted_pages);
/** Release resources after backup_start() */ /** Release resources after backup_start() */

View File

@@ -84,7 +84,6 @@ os_event_t kill_query_thread_stop;
bool sql_thread_started = false; bool sql_thread_started = false;
char *mysql_slave_position = NULL; char *mysql_slave_position = NULL;
char *mysql_binlog_position = NULL; char *mysql_binlog_position = NULL;
char *buffer_pool_filename = NULL;
/* History on server */ /* History on server */
time_t history_start_time; time_t history_start_time;
@@ -1224,27 +1223,29 @@ cleanup:
} }
static
bool
write_binlog_info(MYSQL *connection, char *log_bin_dir,
MYSQL_RES *mysql_result, my_ulonglong n_rows,
my_ulonglong start);
/*********************************************************************//** /*********************************************************************//**
Flush and copy the current binary log file into the backup, Flush and copy the current binary log file into the backup,
if GTID is enabled */ if GTID is enabled */
bool bool
write_current_binlog_file(MYSQL *connection) write_current_binlog_file(MYSQL *connection, bool write_binlogs)
{ {
char *log_bin = NULL;
char *filename = NULL;
char *position = NULL;
char *executed_gtid_set = NULL; char *executed_gtid_set = NULL;
char *gtid_binlog_state = NULL; char *gtid_binlog_state = NULL;
char *log_bin_file = NULL;
char *log_bin_dir = NULL; char *log_bin_dir = NULL;
bool gtid_exists; bool gtid_exists;
bool result = true; bool result = true;
char filepath[FN_REFLEN];
mysql_variable status[] = { mysql_variable log_bin_var[] = {
{"Executed_Gtid_Set", &executed_gtid_set}, {"@@GLOBAL.log_bin", &log_bin},
{NULL, NULL}
};
mysql_variable status_after_flush[] = {
{"File", &log_bin_file},
{NULL, NULL} {NULL, NULL}
}; };
@@ -1254,21 +1255,36 @@ write_current_binlog_file(MYSQL *connection)
{NULL, NULL} {NULL, NULL}
}; };
mysql_variable status[] = {
{"File", &filename},
{"Position", &position},
{"Executed_Gtid_Set", &executed_gtid_set},
{NULL, NULL}
};
read_mysql_variables(connection, "SELECT @@GLOBAL.log_bin", log_bin_var, false);
/* Do not create xtrabackup_binlog_info if binary log is disabled: */
if (strncmp(log_bin, "1", 2) != 0) {
goto binlog_disabled;
}
lock_binlog_maybe(connection);
read_mysql_variables(connection, "SHOW MASTER STATUS", status, false); read_mysql_variables(connection, "SHOW MASTER STATUS", status, false);
/* Do not create xtrabackup_binlog_info if replication
has not started yet: */
if (filename == NULL || position == NULL) {
goto no_replication;
}
read_mysql_variables(connection, "SHOW VARIABLES", vars, true); read_mysql_variables(connection, "SHOW VARIABLES", vars, true);
gtid_exists = (executed_gtid_set && *executed_gtid_set) gtid_exists = (executed_gtid_set && *executed_gtid_set)
|| (gtid_binlog_state && *gtid_binlog_state); || (gtid_binlog_state && *gtid_binlog_state);
if (gtid_exists) { if (write_binlogs || gtid_exists) {
size_t log_bin_dir_length;
lock_binlog_maybe(connection);
xb_mysql_query(connection, "FLUSH BINARY LOGS", false);
read_mysql_variables(connection, "SHOW MASTER STATUS",
status_after_flush, false);
if (opt_log_bin != NULL && strchr(opt_log_bin, FN_LIBCHAR)) { if (opt_log_bin != NULL && strchr(opt_log_bin, FN_LIBCHAR)) {
/* If log_bin is set, it has priority */ /* If log_bin is set, it has priority */
@@ -1278,34 +1294,89 @@ write_current_binlog_file(MYSQL *connection)
log_bin_dir = strdup(opt_log_bin); log_bin_dir = strdup(opt_log_bin);
} else if (log_bin_dir == NULL) { } else if (log_bin_dir == NULL) {
/* Default location is MySQL datadir */ /* Default location is MySQL datadir */
log_bin_dir = strdup("./"); log_bin_dir = static_cast<char*>(malloc(3));
ut_a(log_bin_dir);
log_bin_dir[0] = '.';
log_bin_dir[1] = FN_LIBCHAR;
log_bin_dir[2] = 0;
} }
size_t log_bin_dir_length;
dirname_part(log_bin_dir, log_bin_dir, &log_bin_dir_length); dirname_part(log_bin_dir, log_bin_dir, &log_bin_dir_length);
/* strip final slash if it is not the only path component */ /* strip final slash if it is not the only path component */
if (log_bin_dir_length > 1 && while (IS_TRAILING_SLASH(log_bin_dir, log_bin_dir_length)) {
log_bin_dir[log_bin_dir_length - 1] == FN_LIBCHAR) { log_bin_dir_length--;
log_bin_dir[log_bin_dir_length - 1] = 0;
} }
log_bin_dir[log_bin_dir_length] = 0;
if (log_bin_dir == NULL || log_bin_file == NULL) { if (log_bin_dir == NULL) {
msg("Failed to get master binlog coordinates from " msg("Failed to locate binary log files");
"SHOW MASTER STATUS");
result = false; result = false;
goto cleanup; goto cleanup;
} }
snprintf(filepath, sizeof(filepath), "%s%c%s", uint max_binlogs;
log_bin_dir, FN_LIBCHAR, log_bin_file); max_binlogs = opt_max_binlogs;
result = copy_file(ds_data, filepath, log_bin_file, 0); if (max_binlogs == 0) {
if (gtid_exists) {
max_binlogs = 1;
} else {
goto cleanup;
}
}
xb_mysql_query(connection, "FLUSH BINARY LOGS", false);
MYSQL_RES *mysql_result;
mysql_result = xb_mysql_query(connection, "SHOW BINARY LOGS", true);
ut_ad(mysql_num_fields(mysql_result) >= 2);
my_ulonglong n_rows;
my_ulonglong start;
n_rows = mysql_num_rows(mysql_result);
start = 0;
if (max_binlogs < n_rows) {
start = n_rows - max_binlogs;
}
if (start) {
mysql_data_seek(mysql_result, start);
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(mysql_result))) {
const char *binlog_name = row[0];
char filepath[FN_REFLEN];
snprintf(filepath, sizeof(filepath), "%s%c%s",
log_bin_dir, FN_LIBCHAR, binlog_name);
if (file_exists(filepath)) {
result = copy_file(ds_data, filepath, binlog_name, 0);
if (!result) break;
}
}
if (result) {
write_binlog_info(connection, log_bin_dir,
mysql_result, n_rows, start);
}
mysql_free_result(mysql_result);
} }
cleanup: cleanup:
free_mysql_variables(status_after_flush);
free_mysql_variables(status);
free_mysql_variables(vars); free_mysql_variables(vars);
no_replication:
free_mysql_variables(status);
binlog_disabled:
free_mysql_variables(log_bin_var);
return(result); return(result);
} }
@@ -1313,8 +1384,11 @@ cleanup:
/*********************************************************************//** /*********************************************************************//**
Retrieves MySQL binlog position and Retrieves MySQL binlog position and
saves it in a file. It also prints it to stdout. */ saves it in a file. It also prints it to stdout. */
static
bool bool
write_binlog_info(MYSQL *connection) write_binlog_info(MYSQL *connection, char *log_bin_dir,
MYSQL_RES *mysql_result, my_ulonglong n_rows,
my_ulonglong start)
{ {
char *filename = NULL; char *filename = NULL;
char *position = NULL; char *position = NULL;
@@ -1322,9 +1396,13 @@ write_binlog_info(MYSQL *connection)
char *gtid_current_pos = NULL; char *gtid_current_pos = NULL;
char *gtid_executed = NULL; char *gtid_executed = NULL;
char *gtid = NULL; char *gtid = NULL;
bool result; char *buffer;
char *buf;
size_t total;
bool result = true;
bool mysql_gtid; bool mysql_gtid;
bool mariadb_gtid; bool mariadb_gtid;
bool with_gtid;
mysql_variable status[] = { mysql_variable status[] = {
{"File", &filename}, {"File", &filename},
@@ -1342,39 +1420,106 @@ write_binlog_info(MYSQL *connection)
read_mysql_variables(connection, "SHOW MASTER STATUS", status, false); read_mysql_variables(connection, "SHOW MASTER STATUS", status, false);
read_mysql_variables(connection, "SHOW VARIABLES", vars, true); read_mysql_variables(connection, "SHOW VARIABLES", vars, true);
if (filename == NULL || position == NULL) { mysql_gtid = gtid_mode && (strcmp(gtid_mode, "ON") == 0);
/* Do not create xtrabackup_binlog_info if binary mariadb_gtid = gtid_current_pos && *gtid_current_pos;
log is disabled */
result = true;
goto cleanup;
}
mysql_gtid = ((gtid_mode != NULL) && (strcmp(gtid_mode, "ON") == 0)); gtid = (gtid_executed && *gtid_executed) ? gtid_executed : gtid_current_pos;
mariadb_gtid = (gtid_current_pos != NULL);
gtid = (gtid_executed != NULL ? gtid_executed : gtid_current_pos); with_gtid = mariadb_gtid || mysql_gtid;
if (with_gtid) {
if (mariadb_gtid || mysql_gtid) {
ut_a(asprintf(&mysql_binlog_position, ut_a(asprintf(&mysql_binlog_position,
"filename '%s', position '%s', " "filename '%s', position '%s', "
"GTID of the last change '%s'", "GTID of the last change '%s'",
filename, position, gtid) != -1); filename, position, gtid) != -1);
result = backup_file_printf(XTRABACKUP_BINLOG_INFO,
"%s\t%s\t%s\n", filename, position,
gtid);
} else { } else {
ut_a(asprintf(&mysql_binlog_position, ut_a(asprintf(&mysql_binlog_position,
"filename '%s', position '%s'", "filename '%s', position '%s'",
filename, position) != -1); filename, position) != -1);
result = backup_file_printf(XTRABACKUP_BINLOG_INFO,
"%s\t%s\n", filename, position);
} }
mysql_data_seek(mysql_result, start);
MYSQL_ROW row;
my_ulonglong current;
total = 1;
current = start;
while ((row = mysql_fetch_row(mysql_result))) {
const char *binlog_name = row[0];
/* The position in the current binlog is taken from
the global variable, but for the previous ones it is
determined by their length: */
const char *binlog_pos =
++current == n_rows ? position : row[1];
total += strlen(binlog_name) + strlen(binlog_pos) + 2;
if (with_gtid && current != n_rows) {
/* Add the "\t[]" length to the buffer size: */
total += 3;
}
}
/* For the last of the binray log files, also add
the length of the GTID (+ one character for '\t'): */
if (with_gtid) {
total += strlen(gtid) + 1;
}
buffer = static_cast<char*>(malloc(total));
if (!buffer) {
msg("Failed to allocate memory for temporary buffer");
result = false;
goto cleanup;
}
mysql_data_seek(mysql_result, start);
buf = buffer;
current = start;
while ((row = mysql_fetch_row(mysql_result))) {
const char *binlog_name = row[0];
char filepath[FN_REFLEN];
snprintf(filepath, sizeof(filepath), "%s%c%s",
log_bin_dir, FN_LIBCHAR, binlog_name);
current++;
if (file_exists(filepath)) {
/* The position in the current binlog is taken from
the global variable, but for the previous ones it is
determined by their length: */
char *binlog_pos =
current == n_rows ? position : row[1];
int bytes;
if (with_gtid) {
bytes = snprintf(buf, total, "%s\t%s\t%s\n",
binlog_name, binlog_pos,
current == n_rows ? gtid : "[]");
} else {
bytes = snprintf(buf, total, "%s\t%s\n",
binlog_name, binlog_pos);
}
if (bytes <= 0) {
goto buffer_overflow;
}
buf += bytes;
total -= bytes;
}
}
if (buf != buffer) {
result = backup_file_printf(XTRABACKUP_BINLOG_INFO, "%s", buffer);
}
cleanup2:
free(buffer);
cleanup: cleanup:
free_mysql_variables(status);
free_mysql_variables(vars); free_mysql_variables(vars);
free_mysql_variables(status);
return(result); return(result);
buffer_overflow:
msg("Internal error: buffer overflow in the write_binlog_info()");
result = false;
goto cleanup2;
} }
struct escape_and_quote struct escape_and_quote
@@ -1702,7 +1847,6 @@ backup_cleanup()
{ {
free(mysql_slave_position); free(mysql_slave_position);
free(mysql_binlog_position); free(mysql_binlog_position);
free(buffer_pool_filename);
if (mysql_connection) { if (mysql_connection) {
mysql_close(mysql_connection); mysql_close(mysql_connection);

View File

@@ -28,7 +28,6 @@ extern time_t history_lock_time;
extern bool sql_thread_started; extern bool sql_thread_started;
extern char *mysql_slave_position; extern char *mysql_slave_position;
extern char *mysql_binlog_position; extern char *mysql_binlog_position;
extern char *buffer_pool_filename;
/** connection to mysql server */ /** connection to mysql server */
extern MYSQL *mysql_connection; extern MYSQL *mysql_connection;
@@ -62,10 +61,7 @@ void
unlock_all(MYSQL *connection); unlock_all(MYSQL *connection);
bool bool
write_current_binlog_file(MYSQL *connection); write_current_binlog_file(MYSQL *connection, bool write_binlogs);
bool
write_binlog_info(MYSQL *connection);
bool bool
write_xtrabackup_info(MYSQL *connection, const char * filename, bool history, write_xtrabackup_info(MYSQL *connection, const char * filename, bool history,

View File

@@ -187,4 +187,14 @@ xb_read_full(File fd, uchar *buf, size_t len)
return tlen; return tlen;
} }
#ifdef _WIN32
#define IS_TRAILING_SLASH(name, length) \
((length) > 1 && \
(name[(length) - 1] == '/' || \
name[(length) - 1] == '\\'))
#else
#define IS_TRAILING_SLASH(name, length) \
((length) > 1 && name[(length) - 1] == FN_LIBCHAR)
#endif
#endif #endif

View File

@@ -4,7 +4,7 @@ MariaBackup: hot backup tool for InnoDB
Originally Created 3/3/2009 Yasufumi Kinoshita Originally Created 3/3/2009 Yasufumi Kinoshita
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
(c) 2017, 2021, MariaDB Corporation. (c) 2017, 2022, MariaDB Corporation.
Portions written by Marko Mäkelä. Portions written by Marko Mäkelä.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@@ -245,7 +245,8 @@ long innobase_read_io_threads = 4;
long innobase_write_io_threads = 4; long innobase_write_io_threads = 4;
longlong innobase_page_size = (1LL << 14); /* 16KB */ longlong innobase_page_size = (1LL << 14); /* 16KB */
char* innobase_buffer_pool_filename = NULL; char *innobase_buffer_pool_filename = NULL;
char *buffer_pool_filename = NULL;
/* The default values for the following char* start-up parameters /* The default values for the following char* start-up parameters
are determined in innobase_init below: */ are determined in innobase_init below: */
@@ -354,6 +355,7 @@ uint opt_lock_wait_timeout = 0;
uint opt_lock_wait_threshold = 0; uint opt_lock_wait_threshold = 0;
uint opt_debug_sleep_before_unlock = 0; uint opt_debug_sleep_before_unlock = 0;
uint opt_safe_slave_backup_timeout = 0; uint opt_safe_slave_backup_timeout = 0;
uint opt_max_binlogs = UINT_MAX;
const char *opt_history = NULL; const char *opt_history = NULL;
@@ -1054,7 +1056,8 @@ enum options_xtrabackup
OPT_XTRA_CHECK_PRIVILEGES, OPT_XTRA_CHECK_PRIVILEGES,
OPT_XTRA_MYSQLD_ARGS, OPT_XTRA_MYSQLD_ARGS,
OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION, OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION,
OPT_INNODB_FORCE_RECOVERY OPT_INNODB_FORCE_RECOVERY,
OPT_MAX_BINLOGS
}; };
struct my_option xb_client_options[]= { struct my_option xb_client_options[]= {
@@ -1457,6 +1460,17 @@ struct my_option xb_client_options[]= {
&opt_log_innodb_page_corruption, &opt_log_innodb_page_corruption, 0, &opt_log_innodb_page_corruption, &opt_log_innodb_page_corruption, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"sst_max_binlogs", OPT_MAX_BINLOGS,
"Number of recent binary logs to be included in the backup. "
"Setting this parameter to zero normally disables transmission "
"of binary logs to the joiner nodes during SST using Galera. "
"But sometimes a single current binlog can still be transmitted "
"to the joiner even with sst_max_binlogs=0, because it is "
"required for Galera to work properly with GTIDs support.",
(G_PTR *) &opt_max_binlogs,
(G_PTR *) &opt_max_binlogs, 0, GET_UINT, OPT_ARG,
UINT_MAX, 0, UINT_MAX, 0, 1, 0},
#define MYSQL_CLIENT #define MYSQL_CLIENT
#include "sslopt-longopts.h" #include "sslopt-longopts.h"
#undef MYSQL_CLIENT #undef MYSQL_CLIENT
@@ -1505,14 +1519,14 @@ struct my_option xb_server_options[] =
(G_PTR*)&opt_encrypted_backup, (G_PTR*)&opt_encrypted_backup,
0, GET_BOOL, NO_ARG, TRUE, 0, 0, 0, 0, 0}, 0, GET_BOOL, NO_ARG, TRUE, 0, 0, 0, 0, 0},
{"log", OPT_LOG, "Ignored option for MySQL option compatibility", {"log", OPT_LOG, "Ignored option for MySQL option compatibility",
(G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0, (G_PTR*) &log_ignored_opt, (G_PTR*) &log_ignored_opt, 0,
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log_bin", OPT_LOG, "Base name for the log sequence", {"log_bin", OPT_LOG, "Base name for the log sequence",
&opt_log_bin, &opt_log_bin, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, &opt_log_bin, &opt_log_bin, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"innodb", OPT_INNODB, "Ignored option for MySQL option compatibility", {"innodb", OPT_INNODB, "Ignored option for MySQL option compatibility",
(G_PTR*) &innobase_ignored_opt, (G_PTR*) &innobase_ignored_opt, 0, (G_PTR*) &innobase_ignored_opt, (G_PTR*) &innobase_ignored_opt, 0,
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
@@ -1634,10 +1648,10 @@ struct my_option xb_server_options[] =
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"plugin-dir", OPT_PLUGIN_DIR, {"plugin-dir", OPT_PLUGIN_DIR,
"Server plugin directory. Used to load encryption plugin during 'prepare' phase." "Server plugin directory. Used to load encryption plugin during 'prepare' phase."
"Has no effect in the 'backup' phase (plugin directory during backup is the same as server's)", "Has no effect in the 'backup' phase (plugin directory during backup is the same as server's)",
&xb_plugin_dir, &xb_plugin_dir, &xb_plugin_dir, &xb_plugin_dir,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"innodb-log-checksums", OPT_INNODB_LOG_CHECKSUMS, {"innodb-log-checksums", OPT_INNODB_LOG_CHECKSUMS,
"Whether to require checksums for InnoDB redo log blocks", "Whether to require checksums for InnoDB redo log blocks",
@@ -1659,12 +1673,12 @@ struct my_option xb_server_options[] =
&xb_rocksdb_datadir, &xb_rocksdb_datadir, &xb_rocksdb_datadir, &xb_rocksdb_datadir,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "rocksdb-backup", OPT_BACKUP_ROCKSDB, "Backup rocksdb data, if rocksdb plugin is installed." {"rocksdb-backup", OPT_BACKUP_ROCKSDB, "Backup rocksdb data, if rocksdb plugin is installed."
"Used only with --backup option. Can be useful for partial backups, to exclude all rocksdb data", "Used only with --backup option. Can be useful for partial backups, to exclude all rocksdb data",
&xb_backup_rocksdb, &xb_backup_rocksdb, &xb_backup_rocksdb, &xb_backup_rocksdb,
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
{"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user " {"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user "
"privileges fro the backup user", "privileges fro the backup user",
&opt_check_privileges, &opt_check_privileges, &opt_check_privileges, &opt_check_privileges,
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
@@ -6426,6 +6440,44 @@ static bool check_all_privileges()
return true; return true;
} }
static
void
xb_init_buffer_pool(const char * filename)
{
if (filename &&
#ifdef _WIN32
(filename[0] == '/' ||
filename[0] == '\\' ||
strchr(filename, ':')))
#else
filename[0] == FN_LIBCHAR)
#endif
{
buffer_pool_filename = strdup(filename);
} else {
char filepath[FN_REFLEN];
char *dst_dir =
(innobase_data_home_dir && *innobase_data_home_dir) ?
innobase_data_home_dir : mysql_data_home;
size_t dir_length;
if (dst_dir && *dst_dir) {
dir_length = strlen(dst_dir);
while (IS_TRAILING_SLASH(dst_dir, dir_length)) {
dir_length--;
}
memcpy(filepath, dst_dir, dir_length);
}
else {
filepath[0] = '.';
dir_length = 1;
}
snprintf(filepath + dir_length,
sizeof(filepath) - dir_length, "%c%s", FN_LIBCHAR,
filename ? filename : "ib_buffer_pool");
buffer_pool_filename = strdup(filepath);
}
}
bool bool
xb_init() xb_init()
{ {
@@ -6490,11 +6542,16 @@ xb_init()
if (!get_mysql_vars(mysql_connection)) { if (!get_mysql_vars(mysql_connection)) {
return(false); return(false);
} }
xb_init_buffer_pool(buffer_pool_filename);
if (opt_check_privileges && !check_all_privileges()) { if (opt_check_privileges && !check_all_privileges()) {
return(false); return(false);
} }
history_start_time = time(NULL);
history_start_time = time(NULL);
} else {
xb_init_buffer_pool(innobase_buffer_pool_filename);
} }
return(true); return(true);
@@ -6884,6 +6941,8 @@ int main(int argc, char **argv)
free_error_messages(); free_error_messages();
mysql_mutex_destroy(&LOCK_error_log); mysql_mutex_destroy(&LOCK_error_log);
free(buffer_pool_filename);
if (status == EXIT_SUCCESS) { if (status == EXIT_SUCCESS) {
msg("completed OK!"); msg("completed OK!");
} }

View File

@@ -71,6 +71,7 @@ extern char *xtrabackup_incremental_dir;
extern char *xtrabackup_incremental_basedir; extern char *xtrabackup_incremental_basedir;
extern char *innobase_data_home_dir; extern char *innobase_data_home_dir;
extern char *innobase_buffer_pool_filename; extern char *innobase_buffer_pool_filename;
extern char *buffer_pool_filename;
extern char *xb_plugin_dir; extern char *xb_plugin_dir;
extern char *xb_rocksdb_datadir; extern char *xb_rocksdb_datadir;
extern my_bool xb_backup_rocksdb; extern my_bool xb_backup_rocksdb;
@@ -166,6 +167,7 @@ extern uint opt_lock_wait_timeout;
extern uint opt_lock_wait_threshold; extern uint opt_lock_wait_threshold;
extern uint opt_debug_sleep_before_unlock; extern uint opt_debug_sleep_before_unlock;
extern uint opt_safe_slave_backup_timeout; extern uint opt_safe_slave_backup_timeout;
extern uint opt_max_binlogs;
extern const char *opt_history; extern const char *opt_history;

View File

@@ -262,7 +262,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2c ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join) 2 DEPENDENT SUBQUERY t2c ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join)
Warnings: Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t2a`.`c2` from `test`.`t2` `t2a` join `test`.`t2` `t2b` join `test`.`t2` `t2c` where (`test`.`t2b`.`m` <> `test`.`t1`.`a` or `test`.`t2b`.`m` = `test`.`t2a`.`m`) and trigcond(<cache>(`test`.`t1`.`c1`) = `test`.`t2a`.`c2` or `test`.`t2a`.`c2` is null) and `test`.`t2c`.`c2` = `test`.`t2b`.`c2` and `test`.`t2b`.`n` = `test`.`t2a`.`m` having trigcond(`test`.`t2a`.`c2` is null)))) Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t2a`.`c2` from `test`.`t2` `t2a` join `test`.`t2` `t2b` join `test`.`t2` `t2c` where `test`.`t2c`.`c2` = `test`.`t2b`.`c2` and `test`.`t2b`.`n` = `test`.`t2a`.`m` and (`test`.`t2b`.`m` <> `test`.`t1`.`a` or `test`.`t2b`.`m` = `test`.`t2a`.`m`) and trigcond(<cache>(`test`.`t1`.`c1`) = `test`.`t2a`.`c2` or `test`.`t2a`.`c2` is null) having trigcond(`test`.`t2a`.`c2` is null))))
DROP TABLE t1,t2; DROP TABLE t1,t2;
# #
# MDEV-614, also MDEV-536, also LP:1050806: # MDEV-614, also MDEV-536, also LP:1050806:

View File

@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where 2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where
Warnings: Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3` Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` and `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 (a int NOT NULL, b int NOT NULL, key(a)); create table t1 (a int NOT NULL, b int NOT NULL, key(a));
insert into t1 values insert into t1 values
@@ -197,7 +197,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where 2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where
Warnings: Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3` Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` and `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`)))) AS `Z` from `test`.`t3`
drop table t1,t2,t3; drop table t1,t2,t3;
create table t1 (oref int, grp int); create table t1 (oref int, grp int);
insert into t1 (oref, grp) values insert into t1 (oref, grp) values

View File

@@ -172,7 +172,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan 2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
Warnings: Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) and `test`.`t2`.`a` = `test`.`t1`.`b` having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3` Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` and `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a` or `test`.`t1`.`a` is null) having trigcond(`test`.`t1`.`a` is null)))) AS `Z` from `test`.`t3`
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 (a int NOT NULL, b int NOT NULL, key(a)); create table t1 (a int NOT NULL, b int NOT NULL, key(a));
insert into t1 values insert into t1 values
@@ -200,7 +200,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan 2 DEPENDENT SUBQUERY t2 ref a a 4 test.t1.b 1 100.00 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
Warnings: Warnings:
Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t3.oref' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`) and `test`.`t2`.`a` = `test`.`t1`.`b`))) AS `Z` from `test`.`t3` Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`test`.`t3`.`oref` AS `oref`,<expr_cache><`test`.`t3`.`a`,`test`.`t3`.`oref`>(<in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`b` and `test`.`t2`.`b` = `test`.`t3`.`oref` and trigcond(<cache>(`test`.`t3`.`a`) = `test`.`t1`.`a`)))) AS `Z` from `test`.`t3`
drop table t1,t2,t3; drop table t1,t2,t3;
create table t1 (oref int, grp int); create table t1 (oref int, grp int);
insert into t1 (oref, grp) values insert into t1 (oref, grp) values

View File

@@ -2351,7 +2351,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 system NULL NULL NULL NULL 1 100.00
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings: Warnings:
Note 1003 /* select#1 */ select 3 AS `f` from dual where !<expr_cache><3>(<in_optimizer>(3,<exists>(/* select#2 */ select `test`.`t1`.`b` from `test`.`t1` where (`test`.`t1`.`c` = 'USA' or `test`.`t1`.`c` <> 'USA') and trigcond(<cache>(3) = `test`.`t1`.`b` or `test`.`t1`.`b` is null) and `test`.`t1`.`b` = `test`.`t1`.`a` having trigcond(`test`.`t1`.`b` is null)))) Note 1003 /* select#1 */ select 3 AS `f` from dual where !<expr_cache><3>(<in_optimizer>(3,<exists>(/* select#2 */ select `test`.`t1`.`b` from `test`.`t1` where `test`.`t1`.`b` = `test`.`t1`.`a` and (`test`.`t1`.`c` = 'USA' or `test`.`t1`.`c` <> 'USA') and trigcond(<cache>(3) = `test`.`t1`.`b` or `test`.`t1`.`b` is null) having trigcond(`test`.`t1`.`b` is null))))
SELECT * FROM t2 SELECT * FROM t2
WHERE f NOT IN (SELECT b FROM t1 WHERE f NOT IN (SELECT b FROM t1
WHERE 0 OR (c IN ('USA') OR c NOT IN ('USA')) AND a = b); WHERE 0 OR (c IN ('USA') OR c NOT IN ('USA')) AND a = b);
@@ -2867,6 +2867,44 @@ FROM (t1 JOIN t1 AS ref_t1 ON
(t1.i1 > (SELECT ref_t1.i1 AS c0 FROM t1 b ORDER BY -c0))); (t1.i1 > (SELECT ref_t1.i1 AS c0 FROM t1 b ORDER BY -c0)));
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-22377: Subquery in an UPDATE query uses full scan instead of range
#
CREATE TABLE t1 (
key1 varchar(30) NOT NULL,
col1 int(11) NOT NULL,
filler char(100)
);
insert into t1 select seq, seq, seq from seq_1_to_100;
CREATE TABLE t10 (
key1 varchar(30) NOT NULL,
col1 int,
filler char(100),
PRIMARY KEY (key1)
);
insert into t10 select seq, seq, seq from seq_1_to_1000;
CREATE TABLE t11 (
key1 varchar(30) NOT NULL,
filler char(100),
PRIMARY KEY (key1)
);
insert into t11 select seq, seq from seq_1_to_1000;
set @tmp_os=@@optimizer_switch;
set optimizer_switch='semijoin=off,materialization=off';
# Must use range access (not full scan) for table tms:
explain select * from t1 hist
WHERE
key1 IN ('1','2','3','4','5','6','7','8','9','10') AND
hist.col1 NOT IN (SELECT tn.col1
FROM t10 tn JOIN t11 tms ON tms.key1 = tn.key1
WHERE tn.key1 IN ('1','2','3','4','5','6','7','8','9','10')
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY hist ALL NULL NULL NULL NULL 100 Using where
2 DEPENDENT SUBQUERY tms range PRIMARY PRIMARY 32 NULL 10 Using where; Using index
2 DEPENDENT SUBQUERY tn eq_ref PRIMARY PRIMARY 32 test.tms.key1 1 Using where
set optimizer_switch=@tmp_os;
drop table t1, t10, t11;
# End of 10.2 tests # End of 10.2 tests
# End of 10.3 tests # End of 10.3 tests
# #

View File

@@ -2378,6 +2378,49 @@ FROM (t1 JOIN t1 AS ref_t1 ON
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-22377: Subquery in an UPDATE query uses full scan instead of range
--echo #
CREATE TABLE t1 (
key1 varchar(30) NOT NULL,
col1 int(11) NOT NULL,
filler char(100)
);
insert into t1 select seq, seq, seq from seq_1_to_100;
CREATE TABLE t10 (
key1 varchar(30) NOT NULL,
col1 int,
filler char(100),
PRIMARY KEY (key1)
);
insert into t10 select seq, seq, seq from seq_1_to_1000;
CREATE TABLE t11 (
key1 varchar(30) NOT NULL,
filler char(100),
PRIMARY KEY (key1)
);
insert into t11 select seq, seq from seq_1_to_1000;
set @tmp_os=@@optimizer_switch;
set optimizer_switch='semijoin=off,materialization=off';
--echo # Must use range access (not full scan) for table tms:
explain select * from t1 hist
WHERE
key1 IN ('1','2','3','4','5','6','7','8','9','10') AND
hist.col1 NOT IN (SELECT tn.col1
FROM t10 tn JOIN t11 tms ON tms.key1 = tn.key1
WHERE tn.key1 IN ('1','2','3','4','5','6','7','8','9','10')
);
set optimizer_switch=@tmp_os;
drop table t1, t10, t11;
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # End of 10.3 tests --echo # End of 10.3 tests

View File

@@ -100,7 +100,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DEPENDENT SUBQUERY t2 index c3 c3 9 NULL 2 100.00 Using where; Using index; Using join buffer (flat, BNL join) 2 DEPENDENT SUBQUERY t2 index c3 c3 9 NULL 2 100.00 Using where; Using index; Using join buffer (flat, BNL join)
Warnings: Warnings:
Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where <expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t1a`.`c1` from `test`.`t1b` join `test`.`t2` left join `test`.`t1a` on(`test`.`t1a`.`c2` = `test`.`t1b`.`pk` and 2) where `test`.`t1`.`pk` <> 0 and <cache>(`test`.`t1`.`c1`) = `test`.`t1a`.`c1` and `test`.`t2`.`c3` = `test`.`t1b`.`c4`))) Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where <expr_cache><`test`.`t1`.`c1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`c1`,<exists>(/* select#2 */ select `test`.`t1a`.`c1` from `test`.`t1b` join `test`.`t2` left join `test`.`t1a` on(`test`.`t1a`.`c2` = `test`.`t1b`.`pk` and 2) where `test`.`t2`.`c3` = `test`.`t1b`.`c4` and `test`.`t1`.`pk` <> 0 and <cache>(`test`.`t1`.`c1`) = `test`.`t1a`.`c1`)))
SELECT pk SELECT pk
FROM t1 FROM t1
WHERE c1 IN WHERE c1 IN
@@ -364,7 +364,7 @@ AND a = SOME (SELECT b FROM t5));
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY t5 index c c 10 NULL 2 Using where; Using index; Start temporary 2 DEPENDENT SUBQUERY t5 index c c 10 NULL 2 Using where; Using index; Start temporary
2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using index condition; Using where; End temporary 2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using where; End temporary
SELECT * SELECT *
FROM t3 FROM t3
WHERE t3.b > ALL ( WHERE t3.b > ALL (

View File

@@ -4230,6 +4230,14 @@ i LAST_VALUE(COUNT(i)) OVER (PARTITION BY i ORDER BY j)
4 2 4 2
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-15208: server crashed, when using ORDER BY with window function and UNION
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(2),(2),(2),(2),(2);
SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ());
ERROR HY000: Expression #1 of ORDER BY contains aggregate function and applies to a UNION
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #

View File

@@ -2730,6 +2730,16 @@ INSERT INTO t1 VALUES (1,1), (1,5),(1,4), (2,2),(2,5), (3,3),(4,4);
SELECT i, LAST_VALUE(COUNT(i)) OVER (PARTITION BY i ORDER BY j) FROM t1 GROUP BY i; SELECT i, LAST_VALUE(COUNT(i)) OVER (PARTITION BY i ORDER BY j) FROM t1 GROUP BY i;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-15208: server crashed, when using ORDER BY with window function and UNION
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(2),(2),(2),(2),(2);
--error ER_AGGREGATE_ORDER_FOR_UNION
SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ());
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #

View File

@@ -4236,6 +4236,14 @@ i LAST_VALUE(COUNT(i)) OVER (PARTITION BY i ORDER BY j)
4 2 4 2
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-15208: server crashed, when using ORDER BY with window function and UNION
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(2),(2),(2),(2),(2);
SELECT 1 UNION SELECT a FROM t1 ORDER BY (row_number() over ());
ERROR HY000: Expression #1 of ORDER BY contains aggregate function and applies to a UNION
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
# #

View File

@@ -1,5 +1,12 @@
--echo Performing --wsrep-recover ... --echo Performing --wsrep-recover ...
if ($wsrep_recover_additional)
{
--exec $MYSQLD --defaults-group-suffix=.$galera_wsrep_recover_server_id --defaults-file=$MYSQLTEST_VARDIR/my.cnf --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.log --innodb --wsrep-recover $wsrep_recover_additional > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1
}
if (!$wsrep_recover_additional)
{
--exec $MYSQLD --defaults-group-suffix=.$galera_wsrep_recover_server_id --defaults-file=$MYSQLTEST_VARDIR/my.cnf --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.log --innodb --wsrep-recover > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1 --exec $MYSQLD --defaults-group-suffix=.$galera_wsrep_recover_server_id --defaults-file=$MYSQLTEST_VARDIR/my.cnf --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.log --innodb --wsrep-recover > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1
}
--perl --perl
use strict; use strict;

View File

@@ -78,3 +78,4 @@ DROP TABLE t2;
connection node_1; connection node_1;
SET GLOBAL wsrep_on=OFF; SET GLOBAL wsrep_on=OFF;
RESET MASTER; RESET MASTER;
SET GLOBAL wsrep_on=ON;

View File

@@ -1,6 +1,8 @@
connection node_2; connection node_2;
connection node_1; connection node_1;
connection node_1; connection node_1;
connection node_2;
connection node_1;
set global wsrep_on=OFF; set global wsrep_on=OFF;
reset master; reset master;
set global wsrep_on=ON; set global wsrep_on=ON;
@@ -46,6 +48,12 @@ hostname1-bin.000001 # Xid # # COMMIT /* XID */
hostname1-bin.000001 # Gtid # # GTID #-#-# hostname1-bin.000001 # Gtid # # GTID #-#-#
hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER
connection node_2; connection node_2;
Shutting down server ...
connection node_1;
Cleaning var directory ...
connection node_2;
Starting server ...
connection node_2;
SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
COUNT(*) = 2 COUNT(*) = 2
1 1
@@ -72,9 +80,11 @@ hostname1-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
hostname1-bin.000001 # Xid # # COMMIT /* XID */ hostname1-bin.000001 # Xid # # COMMIT /* XID */
hostname1-bin.000001 # Gtid # # GTID #-#-# hostname1-bin.000001 # Gtid # # GTID #-#-#
hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER hostname1-bin.000001 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER
hostname1-bin.000001 # Rotate # # hostname1-bin.000002;pos=4
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
#cleanup #cleanup
connection node_1; connection node_1;
SET GLOBAL wsrep_on=OFF; SET GLOBAL wsrep_on=OFF;
RESET MASTER; RESET MASTER;
SET GLOBAL wsrep_on=ON;

View File

@@ -0,0 +1,90 @@
connection node_2;
connection node_1;
connection node_1;
connection node_2;
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;
Shutting down server ...
connection node_1;
Cleaning var directory ...
connection node_2;
Starting server ...
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
hostname1-bin.000001 # Rotate # # hostname1-bin.000002;pos=4
DROP TABLE t1;
DROP TABLE t2;
#cleanup
connection node_1;
SET GLOBAL wsrep_on=OFF;
RESET MASTER;
SET GLOBAL wsrep_on=ON;

View File

@@ -78,3 +78,4 @@ DROP TABLE t2;
connection node_1; connection node_1;
SET GLOBAL wsrep_on=OFF; SET GLOBAL wsrep_on=OFF;
RESET MASTER; RESET MASTER;
SET GLOBAL wsrep_on=ON;

View File

@@ -1,5 +1,5 @@
--- r/galera_sst_mariabackup.result 2021-04-10 14:25:04.142716409 +0300 --- r/galera_sst_mariabackup.result
+++ r/galera_sst_mariabackup,debug.reject 2021-04-10 14:53:30.033162191 +0300 +++ r/galera_sst_mariabackup.reject
@@ -516,5 +516,189 @@ @@ -516,5 +516,189 @@
1 1
DROP TABLE t1; DROP TABLE t1;

View File

@@ -1,5 +1,5 @@
--- r/galera_sst_rsync_data_dir.result 2021-04-10 14:35:28.090610315 +0300 --- galera_sst_rsync.result
+++ r/galera_sst_rsync_data_dir,debug.reject 2021-04-10 15:41:44.876068411 +0300 +++ galera_sst_rsync.reject
@@ -516,3 +516,187 @@ @@ -516,3 +516,187 @@
1 1
DROP TABLE t1; DROP TABLE t1;

View File

@@ -1,17 +1,21 @@
connection node_2; connection node_2;
connection node_1; connection node_1;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
VARIABLE_VALUE = 4 connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
1 connection node_1;
connection node_2;
connection node_3;
connection node_4;
SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
EXPECT_4
4
connection node_1; connection node_1;
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER);
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (2);
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connection node_3; connection node_3;
INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (3);
connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connection node_4; connection node_4;
INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (4);
connection node_3; connection node_3;
@@ -85,3 +89,6 @@ CALL mtr.add_suppression("Action message in non-primary configuration from membe
connection node_4; connection node_4;
CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside"); CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside");
CALL mtr.add_suppression("Action message in non-primary configuration from member 0"); CALL mtr.add_suppression("Action message in non-primary configuration from member 0");
connection node_1;
disconnect node_3;
disconnect node_4;

View File

@@ -44,3 +44,4 @@ DROP TABLE t2;
--connection node_1 --connection node_1
SET GLOBAL wsrep_on=OFF; SET GLOBAL wsrep_on=OFF;
RESET MASTER; RESET MASTER;
SET GLOBAL wsrep_on=ON;

View File

@@ -9,3 +9,6 @@ log-slave-updates
log-bin = hostname2-bin log-bin = hostname2-bin
log-bin-index = hostname2.bdx log-bin-index = hostname2.bdx
log-slave-updates log-slave-updates
[sst]
sst_max_binlogs=

View File

@@ -1 +1 @@
--source galera_log_bin.inc --source galera_log_bin_sst.inc

View File

@@ -0,0 +1,19 @@
!include ../galera_2nodes.cnf
[mysqld]
wsrep_sst_method=mariabackup
wsrep_sst_auth="root:"
[mysqld.1]
log-bin=@ENV.MYSQLTEST_VARDIR/mysqld.1/data/hostname1-bin
log-bin-index = hostname1.bdx
log-slave-updates
[mysqld.2]
log-bin=@ENV.MYSQLTEST_VARDIR/mysqld.2/data/hostname2-bin
log-bin-index = hostname2.bdx
log-slave-updates
[sst]
transferfmt=@ENV.MTR_GALERA_TFMT
sst_max_binlogs=

View File

@@ -0,0 +1,2 @@
--source include/have_mariabackup.inc
--source galera_log_bin_sst.inc

View File

@@ -0,0 +1,90 @@
--source include/galera_cluster.inc
--source include/force_restart.inc
# Save original auto_increment_offset values.
--let $node_1=node_1
--let $node_2=node_2
--source include/auto_increment_offset_save.inc
--connection node_1
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;
#
# Test Galera with --log-bin --log-slave-updates .
# This way the actual MySQL binary log is used,
# rather than Galera's own implementation
#
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;
SELECT COUNT(*) = 2 FROM t2;
--connection node_1
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
--let $MASTER_MYPORT=$NODE_MYPORT_1
--source include/show_binlog_events.inc
--connection node_2
#--connection node_2
#--source suite/galera/include/galera_stop_replication.inc
--echo Shutting down server ...
--source include/shutdown_mysqld.inc
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
--source include/wait_condition.inc
#
# Force SST
#
--echo Cleaning var directory ...
--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mtr
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data
--connection node_2
--echo Starting server ...
let $restart_noprint=2;
--source include/start_mysqld.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc
--connection node_2
SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1';
--let $MASTER_MYPORT=$NODE_MYPORT_2
--source include/show_binlog_events.inc
DROP TABLE t1;
DROP TABLE t2;
--echo #cleanup
--connection node_1
SET GLOBAL wsrep_on=OFF;
RESET MASTER;
SET GLOBAL wsrep_on=ON;
# Restore original auto_increment_offset values.
--source include/auto_increment_offset_restore.inc

View File

@@ -10,4 +10,5 @@
--source suite/galera/include/galera_st_kill_slave.inc --source suite/galera/include/galera_st_kill_slave.inc
--source suite/galera/include/galera_st_kill_slave_ddl.inc --source suite/galera/include/galera_st_kill_slave_ddl.inc
--source include/auto_increment_offset_restore.inc --source include/auto_increment_offset_restore.inc

View File

@@ -12,4 +12,3 @@ log_bin
wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true'
log_basename=server2 log_basename=server2
log_bin log_bin

View File

@@ -12,7 +12,19 @@
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/have_innodb.inc --source include/have_innodb.inc
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
# Save original auto_increment_offset values.
--let $node_1=node_1
--let $node_2=node_2
--let $node_3=node_3
--let $node_4=node_4
--source include/auto_increment_offset_save.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--connection node_1 --connection node_1
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER);
@@ -21,11 +33,9 @@ INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (2);
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connection node_3 --connection node_3
INSERT INTO t1 VALUES (3); INSERT INTO t1 VALUES (3);
--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connection node_4 --connection node_4
INSERT INTO t1 VALUES (4); INSERT INTO t1 VALUES (4);
@@ -136,3 +146,10 @@ CALL mtr.add_suppression("Action message in non-primary configuration from membe
--connection node_4 --connection node_4
CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside"); CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside");
CALL mtr.add_suppression("Action message in non-primary configuration from member 0"); CALL mtr.add_suppression("Action message in non-primary configuration from member 0");
# Restore original auto_increment_offset values.
--source include/auto_increment_offset_restore.inc
--connection node_1
--disconnect node_3
--disconnect node_4

View File

@@ -118,7 +118,7 @@ SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
select * from t2; select * from t2;
f1 f2 f1 f2
1 2 1 2
SET GLOBAL innodb_lock_wait_timeout=1; SET SESSION innodb_lock_wait_timeout=1;
insert into t2 values(1,2); insert into t2 values(1,2);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
insert into t2 values(9,10); insert into t2 values(9,10);

View File

@@ -163,7 +163,7 @@ SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
select * from t2; select * from t2;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
select * from t2; select * from t2;
SET GLOBAL innodb_lock_wait_timeout=1; SET SESSION innodb_lock_wait_timeout=1;
--error ER_LOCK_WAIT_TIMEOUT --error ER_LOCK_WAIT_TIMEOUT
insert into t2 values(1,2); insert into t2 values(1,2);
insert into t2 values(9,10); insert into t2 values(9,10);

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2017-2021 MariaDB # Copyright (C) 2017-2022 MariaDB
# Copyright (C) 2012-2015 Codership Oy # Copyright (C) 2012-2015 Codership Oy
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,62 @@ set -ue
# Setting the path for some utilities on CentOS # Setting the path for some utilities on CentOS
export PATH="$PATH:/usr/sbin:/usr/bin:/sbin:/bin" export PATH="$PATH:/usr/sbin:/usr/bin:/sbin:/bin"
trim_string()
{
if [ -n "$BASH_VERSION" ]; then
local pattern="[![:space:]${2:-}]"
local x="${1#*$pattern}"
local z=${#1}
x=${#x}
if [ $x -ne $z ]; then
local y="${1%$pattern*}"
y=${#y}
x=$(( z-x-1 ))
y=$(( y-x+1 ))
printf '%s' "${1:$x:$y}"
else
printf ''
fi
else
local pattern="[[:space:]${2:-}]"
echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g"
fi
}
trim_dir()
{
local t=$(trim_string "$1")
if [ "$t" != '/' ]; then
if [ "${t%/}" != "$t" ]; then
t=$(trim_string "${t%/}")
fi
else
t='.'
fi
if [ -n "$BASH_VERSION" ]; then
printf '%s' "$t"
else
echo "$t"
fi
}
to_minuses()
{
local x="$1"
local t="${1#*_}"
local r=""
while [ "$t" != "$x" ]; do
r="$r${x%%_*}-"
x="$t"
t="${t#*_}"
done
if [ -n "$BASH_VERSION" ]; then
printf '%s' "$r$x"
else
echo "$r$x"
fi
}
WSREP_SST_OPT_BYPASS=0 WSREP_SST_OPT_BYPASS=0
WSREP_SST_OPT_BINLOG="" WSREP_SST_OPT_BINLOG=""
WSREP_SST_OPT_BINLOG_INDEX="" WSREP_SST_OPT_BINLOG_INDEX=""
@@ -43,10 +99,9 @@ WSREP_SST_OPT_ADDR=""
WSREP_SST_OPT_ADDR_PORT="" WSREP_SST_OPT_ADDR_PORT=""
WSREP_SST_OPT_HOST="" WSREP_SST_OPT_HOST=""
WSREP_SST_OPT_HOST_UNESCAPED="" WSREP_SST_OPT_HOST_UNESCAPED=""
WSREP_SST_OPT_HOST_ESCAPED="" INNODB_DATA_HOME_DIR=$(trim_dir "${INNODB_DATA_HOME_DIR:-}")
INNODB_DATA_HOME_DIR="${INNODB_DATA_HOME_DIR:-}" INNODB_LOG_GROUP_HOME=$(trim_dir "${INNODB_LOG_GROUP_HOME:-}")
INNODB_LOG_GROUP_HOME="${INNODB_LOG_GROUP_HOME:-}" INNODB_UNDO_DIR=$(trim_dir "${INNODB_UNDO_DIR:-}")
INNODB_UNDO_DIR="${INNODB_UNDO_DIR:-}"
INNODB_FORCE_RECOVERY="" INNODB_FORCE_RECOVERY=""
INNOEXTRA="" INNOEXTRA=""
@@ -66,20 +121,22 @@ case "$1" in
# without square brackets: # without square brackets:
readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}" readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}"
# Square brackets are needed in most cases: # Square brackets are needed in most cases:
readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]" readonly WSREP_SST_OPT_HOST="[$WSREP_SST_OPT_HOST_UNESCAPED]"
readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]"
# Mark this address as IPv6: # Mark this address as IPv6:
readonly WSREP_SST_OPT_HOST_IPv6=1 readonly WSREP_SST_OPT_HOST_IPv6=1
# Let's remove the leading part that contains the host address:
remain="${WSREP_SST_OPT_ADDR#*\]}"
;; ;;
*) *)
readonly WSREP_SST_OPT_HOST="${WSREP_SST_OPT_ADDR%%[:/]*}" readonly WSREP_SST_OPT_HOST="${WSREP_SST_OPT_ADDR%%[:/]*}"
readonly WSREP_SST_OPT_HOST_UNESCAPED="$WSREP_SST_OPT_HOST" readonly WSREP_SST_OPT_HOST_UNESCAPED="$WSREP_SST_OPT_HOST"
readonly WSREP_SST_OPT_HOST_ESCAPED="$WSREP_SST_OPT_HOST"
readonly WSREP_SST_OPT_HOST_IPv6=0 readonly WSREP_SST_OPT_HOST_IPv6=0
# Let's remove the leading part that contains the host address:
remain="${WSREP_SST_OPT_ADDR#*[:/]}"
;; ;;
esac esac
# Let's remove the leading part that contains the host address: # If there is nothing but the address, then the remainder is empty:
remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}" [ "$remain" = "$WSREP_SST_OPT_ADDR" ] && remain=""
# Let's remove the ":" character that separates the port number # Let's remove the ":" character that separates the port number
# from the hostname: # from the hostname:
remain="${remain#:}" remain="${remain#:}"
@@ -87,39 +144,32 @@ case "$1" in
# up to "/" (if present): # up to "/" (if present):
WSREP_SST_OPT_ADDR_PORT="${remain%%/*}" WSREP_SST_OPT_ADDR_PORT="${remain%%/*}"
# If the "/" character is present, then the path is not empty: # If the "/" character is present, then the path is not empty:
if [ "${remain#*/}" != "$remain" ]; then if [ "$WSREP_SST_OPT_ADDR_PORT" != "$remain" ]; then
# This operation removes everything up to the "/" character, # This operation removes everything up to the "/" character,
# effectively removing the port number from the string: # effectively removing the port number from the string:
readonly WSREP_SST_OPT_PATH="${remain#*/}" readonly WSREP_SST_OPT_PATH="${remain#*/}"
else else
readonly WSREP_SST_OPT_PATH="" readonly WSREP_SST_OPT_PATH=""
fi fi
# The rest of the string is the same as the path (for now):
remain="$WSREP_SST_OPT_PATH"
# If there is one more "/" in the string, then everything before
# it will be the module name, otherwise the module name is empty:
if [ "${remain%%/*}" != "$remain" ]; then
# This operation removes the tail after the very first
# occurrence of the "/" character (inclusively):
readonly WSREP_SST_OPT_MODULE="${remain%%/*}"
else
readonly WSREP_SST_OPT_MODULE=""
fi
# Remove the module name part from the string, which ends with "/": # Remove the module name part from the string, which ends with "/":
remain="${WSREP_SST_OPT_PATH#*/}" remain="${WSREP_SST_OPT_PATH#*/}"
# If the rest of the string does not match the original, then there # This operation removes the tail after the very first occurrence
# was something else besides the module name: # of the "/" character, inclusively:
readonly WSREP_SST_OPT_MODULE="${WSREP_SST_OPT_PATH%%/*}"
# If there is one more "/" in the string, then everything before
# it will be the LSN, otherwise the LSN is empty:
if [ "$remain" != "$WSREP_SST_OPT_PATH" ]; then if [ "$remain" != "$WSREP_SST_OPT_PATH" ]; then
# Extract the part that matches the LSN by removing all # Extract the part that matches the LSN by removing all
# characters starting from the very first "/": # characters starting from the very first "/":
readonly WSREP_SST_OPT_LSN="${remain%%/*}" readonly WSREP_SST_OPT_LSN="${remain%%/*}"
# Exctract everything after the first occurrence of # Exctract everything after the first occurrence of
# the "/" character in the string: # the "/" character in the string:
source="$remain"
remain="${remain#*/}" remain="${remain#*/}"
# If the remainder does not match the original string, # If the remainder does not match the original string,
# then there is something else (the version number in # then there is something else (the version number in
# our case): # our case):
if [ "$remain" != "$WSREP_SST_OPT_LSN" ]; then if [ "$remain" != "$source" ]; then
# Let's extract the version number by removing the tail # Let's extract the version number by removing the tail
# after the very first occurence of the "/" character # after the very first occurence of the "/" character
# (inclusively): # (inclusively):
@@ -138,22 +188,22 @@ case "$1" in
;; ;;
'--datadir') '--datadir')
# Let's remove the trailing slash: # Let's remove the trailing slash:
readonly WSREP_SST_OPT_DATA="${2%/}" readonly WSREP_SST_OPT_DATA=$(trim_dir "$2")
shift shift
;; ;;
'--innodb-data-home-dir') '--innodb-data-home-dir')
# Let's remove the trailing slash: # Let's remove the trailing slash:
readonly INNODB_DATA_HOME_DIR="${2%/}" readonly INNODB_DATA_HOME_DIR=$(trim_dir "$2")
shift shift
;; ;;
'--innodb-log-group-home-dir') '--innodb-log-group-home-dir')
# Let's remove the trailing slash: # Let's remove the trailing slash:
readonly INNODB_LOG_GROUP_HOME="${2%/}" readonly INNODB_LOG_GROUP_HOME=$(trim_dir "$2")
shift shift
;; ;;
'--innodb-undo-directory') '--innodb-undo-directory')
# Let's remove the trailing slash: # Let's remove the trailing slash:
readonly INNODB_UNDO_DIR="${2%/}" readonly INNODB_UNDO_DIR=$(trim_dir "$2")
shift shift
;; ;;
'--defaults-file') '--defaults-file')
@@ -182,14 +232,12 @@ case "$1" in
readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}" readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}"
# Square brackets are needed in most cases: # Square brackets are needed in most cases:
readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]" readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]"
readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]"
# Mark this address as IPv6: # Mark this address as IPv6:
readonly WSREP_SST_OPT_HOST_IPv6=1 readonly WSREP_SST_OPT_HOST_IPv6=1
;; ;;
*) *)
readonly WSREP_SST_OPT_HOST="$2" readonly WSREP_SST_OPT_HOST="$2"
readonly WSREP_SST_OPT_HOST_UNESCAPED="$2" readonly WSREP_SST_OPT_HOST_UNESCAPED="$2"
readonly WSREP_SST_OPT_HOST_ESCAPED="$2"
readonly WSREP_SST_OPT_HOST_IPv6=0 readonly WSREP_SST_OPT_HOST_IPv6=0
;; ;;
esac esac
@@ -247,6 +295,7 @@ case "$1" in
'--mysqld-args') '--mysqld-args')
original_cmd="" original_cmd=""
shift shift
cmd_tail=0
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
lname="${1#--}" lname="${1#--}"
# "--" is interpreted as the end of the list of options: # "--" is interpreted as the end of the list of options:
@@ -261,7 +310,7 @@ case "$1" in
shift shift
done done
fi fi
break; break
fi fi
# Make sure the argument does not start with "--", otherwise it # Make sure the argument does not start with "--", otherwise it
# is a long option, which is processed after this "if": # is a long option, which is processed after this "if":
@@ -279,7 +328,7 @@ case "$1" in
else else
# If it's not bash, then we need to use slow # If it's not bash, then we need to use slow
# external utilities: # external utilities:
option=$(echo "$options" | cut -c1-1) option=$(echo "$options" | cut -c1)
fi fi
# And the subsequent characters consider option value: # And the subsequent characters consider option value:
value="" value=""
@@ -301,15 +350,25 @@ case "$1" in
if [ "${2#-}" = "$2" ]; then if [ "${2#-}" = "$2" ]; then
shift shift
value="$1" value="$1"
elif [ "$2" = '--' ]; then
shift
if [ $# -gt 1 ]; then
cmd_tail=1
shift
value="$1"
fi
fi fi
fi fi
if [ $option = 'h' ]; then if [ "$option" = 'h' ]; then
if [ -z "$WSREP_SST_OPT_DATA" ]; then if [ -z "$WSREP_SST_OPT_DATA" ]; then
MYSQLD_OPT_DATADIR="${value%/}" MYSQLD_OPT_DATADIR=$(trim_dir "$value")
fi fi
elif [ $option != 'u' -a \ elif [ "$option" != 'u' -a \
$option != 'P' ] "$option" != 'P' ]
then then
if [ $cmd_tail -ne 0 ]; then
option="$option --"
fi
if [ -z "$value" ]; then if [ -z "$value" ]; then
slist="$slist$option" slist="$slist$option"
elif [ -z "$slist" ]; then elif [ -z "$slist" ]; then
@@ -317,9 +376,16 @@ case "$1" in
else else
slist="$slist -$option '$value'" slist="$slist -$option '$value'"
fi fi
break
fi
if [ $cmd_tail -ne 0 ]; then
if [ -n "$slist" ]; then
slist="$slist --"
else
slist='-'
fi
fi fi
break break
else else
slist="$slist$option" slist="$slist$option"
fi fi
@@ -329,7 +395,7 @@ case "$1" in
original_cmd="$original_cmd -$slist" original_cmd="$original_cmd -$slist"
fi fi
elif [ -z "$options" ]; then elif [ -z "$options" ]; then
# We found an equal sign without any characters after it: # We found an minus sign without any characters after it:
original_cmd="$original_cmd -" original_cmd="$original_cmd -"
else else
# We found a value that does not start with a minus - # We found a value that does not start with a minus -
@@ -338,12 +404,25 @@ case "$1" in
original_cmd="$original_cmd '$1'" original_cmd="$original_cmd '$1'"
fi fi
shift shift
continue; if [ $cmd_tail -ne 0 ]; then
# All other arguments must be copied unchanged:
while [ $# -gt 0 ]; do
original_cmd="$original_cmd '$1'"
shift
done
break
fi
continue
fi fi
# Now we are sure that we are working with an option # Now we are sure that we are working with an option
# that has a "long" name, so remove all characters after # that has a "long" name, so remove all characters after
# the first equal sign: # the first equal sign:
option="${1%%=*}" option="${1%%=*}"
# If the option name contains underscores, then replace
# them to minuses:
if [ "${option#*_}" != "$option" ]; then
option=$(to_minuses "$option")
fi
# The "--loose-" prefix should not affect the recognition # The "--loose-" prefix should not affect the recognition
# of the option name: # of the option name:
if [ "${option#--loose-}" != "$option" ]; then if [ "${option#--loose-}" != "$option" ]; then
@@ -370,49 +449,49 @@ case "$1" in
case "$option" in case "$option" in
'--innodb-data-home-dir') '--innodb-data-home-dir')
if [ -z "$INNODB_DATA_HOME_DIR" ]; then if [ -z "$INNODB_DATA_HOME_DIR" ]; then
MYSQLD_OPT_INNODB_DATA_HOME_DIR="${value%/}" MYSQLD_OPT_INNODB_DATA_HOME_DIR=$(trim_dir "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--innodb-log-group-home-dir') '--innodb-log-group-home-dir')
if [ -z "$INNODB_LOG_GROUP_HOME" ]; then if [ -z "$INNODB_LOG_GROUP_HOME" ]; then
MYSQLD_OPT_INNODB_LOG_GROUP_HOME="${value%/}" MYSQLD_OPT_INNODB_LOG_GROUP_HOME=$(trim_dir "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--innodb-undo-directory') '--innodb-undo-directory')
if [ -z "$INNODB_UNDO_DIR" ]; then if [ -z "$INNODB_UNDO_DIR" ]; then
MYSQLD_OPT_INNODB_UNDO_DIR="${value%/}" MYSQLD_OPT_INNODB_UNDO_DIR=$(trim_dir "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--innodb-force-recovery') '--innodb-force-recovery')
if [ -n "$value" -a "$value" != "0" ]; then if [ -n "$value" -a "$value" != "0" ]; then
INNODB_FORCE_RECOVERY="$value" INNODB_FORCE_RECOVERY=$(trim_string "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--log-bin') '--log-bin')
if [ -z "$WSREP_SST_OPT_BINLOG" ]; then if [ -z "$WSREP_SST_OPT_BINLOG" ]; then
MYSQLD_OPT_LOG_BIN="$value" MYSQLD_OPT_LOG_BIN=$(trim_string "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--log-bin-index') '--log-bin-index')
if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then
MYSQLD_OPT_LOG_BIN_INDEX="$value" MYSQLD_OPT_LOG_BIN_INDEX=$(trim_string "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--log-basename') '--log-basename')
if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then
MYSQLD_OPT_LOG_BASENAME="$value" MYSQLD_OPT_LOG_BASENAME=$(trim_string "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
'--datadir') '--datadir')
if [ -z "$WSREP_SST_OPT_DATA" ]; then if [ -z "$WSREP_SST_OPT_DATA" ]; then
MYSQLD_OPT_DATADIR="${value%/}" MYSQLD_OPT_DATADIR=$(trim_dir "$value")
fi fi
skip_mysqld_arg=1 skip_mysqld_arg=1
;; ;;
@@ -471,8 +550,8 @@ if [ -z "$WSREP_SST_OPT_BINLOG" -a -n "${MYSQLD_OPT_LOG_BIN+x}" ]; then
if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then
# If the WSREP_SST_OPT_BINLOG variable is not set, but # If the WSREP_SST_OPT_BINLOG variable is not set, but
# --log-basename is present among the arguments to mysqld, # --log-basename is present among the arguments to mysqld,
# then set WSREP_SST_OPT_BINLOG equal to the base name with # then set WSREP_SST_OPT_BINLOG equal to the base name
# the "-bin" suffix: # with the "-bin" suffix:
readonly WSREP_SST_OPT_BINLOG="$WSREP_SST_OPT_LOG_BASENAME-bin" readonly WSREP_SST_OPT_BINLOG="$WSREP_SST_OPT_LOG_BASENAME-bin"
else else
# Take the default name: # Take the default name:
@@ -525,26 +604,23 @@ get_binlog()
WSREP_SST_OPT_BINLOG_INDEX=$(parse_cnf '--mysqld' 'log-bin-index') WSREP_SST_OPT_BINLOG_INDEX=$(parse_cnf '--mysqld' 'log-bin-index')
fi fi
# if no command line argument and WSREP_SST_OPT_LOG_BASENAME is not set, # if no command line argument and WSREP_SST_OPT_LOG_BASENAME is not set,
# try to get it from my.cnf: # then try to get it from my.cnf:
if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then
WSREP_SST_OPT_LOG_BASENAME=$(parse_cnf '--mysqld' 'log-basename') WSREP_SST_OPT_LOG_BASENAME=$(parse_cnf '--mysqld' 'log-basename')
fi fi
if [ -z "$WSREP_SST_OPT_BINLOG" ]; then if [ -z "$WSREP_SST_OPT_BINLOG" ]; then
# If the --log-bin option is specified without a parameter, # If the log-bin option is specified without a parameter,
# then we need to build the name of the index file according # then we need to build the name of the index file according
# to the rules described in the server documentation: # to the rules described in the server documentation:
if [ -n "${MYSQLD_OPT_LOG_BIN+x}" -o \ if [ $(in_config '--mysqld' 'log-bin') -ne 0 ]; then
$(in_config '--mysqld' 'log-bin') -eq 1 ]
then
if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then
# If the WSREP_SST_OPT_BINLOG variable is not set, but # If the WSREP_SST_OPT_BINLOG variable is not set, but
# --log-basename is present among the arguments of mysqld, # --log-basename is present among the arguments of mysqld,
# then set WSREP_SST_OPT_BINLOG equal to the base name with # then set WSREP_SST_OPT_BINLOG equal to the base name
# the "-bin" suffix: # with the "-bin" suffix:
readonly WSREP_SST_OPT_BINLOG="$WSREP_SST_OPT_LOG_BASENAME-bin" readonly WSREP_SST_OPT_BINLOG="$WSREP_SST_OPT_LOG_BASENAME-bin"
else else
# If the --log-bin option is present without a value, then # Take the default name:
# we take the default name:
readonly WSREP_SST_OPT_BINLOG='mysql-bin' readonly WSREP_SST_OPT_BINLOG='mysql-bin'
fi fi
fi fi
@@ -554,13 +630,13 @@ get_binlog()
# it according to the specifications for the server: # it according to the specifications for the server:
if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then
if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then if [ -n "$WSREP_SST_OPT_LOG_BASENAME" ]; then
# If the WSREP_SST_OPT_BINLOG variable is not set, but # If the WSREP_SST_OPT_BINLOG_INDEX variable is not set, but
# --log-basename is present among the arguments of mysqld, # --log-basename is present among the arguments of mysqld,
# then set WSREP_SST_OPT_BINLOG equal to the base name with # then set WSREP_SST_OPT_BINLOG_INDEX equal to the base name
# the "-bin" suffix: # with the "-bin" suffix:
readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_LOG_BASENAME-bin.index" readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_LOG_BASENAME-bin.index"
else else
# the default name (note that base of this name # Use the default name (note that base of this name
# is already defined above): # is already defined above):
readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_BINLOG.index" readonly WSREP_SST_OPT_BINLOG_INDEX="$WSREP_SST_OPT_BINLOG.index"
fi fi
@@ -594,27 +670,18 @@ if [ -n "$WSREP_SST_OPT_ADDR_PORT" ]; then
# the corresponding variable: # the corresponding variable:
readonly WSREP_SST_OPT_PORT="$WSREP_SST_OPT_ADDR_PORT" readonly WSREP_SST_OPT_PORT="$WSREP_SST_OPT_ADDR_PORT"
fi fi
elif [ -n "$WSREP_SST_OPT_ADDR" ]; then else
# If the port is missing, take the default port: # If the port is missing, take the default port:
if [ -z "$WSREP_SST_OPT_PORT" ]; then if [ -z "$WSREP_SST_OPT_PORT" ]; then
readonly WSREP_SST_OPT_PORT=4444 readonly WSREP_SST_OPT_PORT=4444
fi fi
WSREP_SST_OPT_ADDR_PORT="$WSREP_SST_OPT_PORT" WSREP_SST_OPT_ADDR_PORT="$WSREP_SST_OPT_PORT"
# Let's remove the leading part that contains the host address:
remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}"
# Let's remove the ":" character that separates the port number
# from the hostname:
remain="${remain#:}"
# Let's remove all characters upto first "/" character that
# separates the hostname with port number from the path:
remain="${remain#/}"
# Let's construct a new value for the address with the port:
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT"
if [ -n "$remain" ]; then
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_ADDR/$remain"
fi
fi fi
# Let's construct a new value for the address with the port:
sst_path="${WSREP_SST_OPT_PATH:+/}$WSREP_SST_OPT_PATH"
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT$sst_path"
readonly WSREP_SST_OPT_ADDR readonly WSREP_SST_OPT_ADDR
readonly WSREP_SST_OPT_ADDR_PORT readonly WSREP_SST_OPT_ADDR_PORT
@@ -632,7 +699,7 @@ commandex()
# try to use my_print_defaults, mysql and mysqldump that come # try to use my_print_defaults, mysql and mysqldump that come
# with the sources (for MTR suite): # with the sources (for MTR suite):
script_binary=$(dirname "$0") script_binary=$(dirname "$0")
SCRIPTS_DIR=$(cd "$script_binary"; pwd -P) SCRIPTS_DIR=$(cd "$script_binary"; pwd)
EXTRA_DIR="$SCRIPTS_DIR/../extra" EXTRA_DIR="$SCRIPTS_DIR/../extra"
CLIENT_DIR="$SCRIPTS_DIR/../client" CLIENT_DIR="$SCRIPTS_DIR/../client"
@@ -725,8 +792,11 @@ parse_cnf()
local group="${groups%%\|*}" local group="${groups%%\|*}"
# Remove the remainder (the group name) from the rest # Remove the remainder (the group name) from the rest
# of the groups list (as if it were a prefix): # of the groups list (as if it were a prefix):
groups="${groups#$group}" if [ "$group" != "$groups" ]; then
groups="${groups#\|}" groups="${groups#*\|}"
else
groups=""
fi
# If the group name is the same as the "mysqld" without "--" prefix, # If the group name is the same as the "mysqld" without "--" prefix,
# then try to use it together with the group suffix: # then try to use it together with the group suffix:
if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
@@ -751,10 +821,16 @@ parse_cnf()
done done
# Use default if we haven't found a value: # Use default if we haven't found a value:
if [ -z "$reval" ]; then [ -z "$reval" ] && reval="${3:-}"
[ -n "${3:-}" ] && reval="$3"
# Truncate spaces:
[ -n "$reval" ] && reval=$(trim_string "$reval")
if [ -n "$BASH_VERSION" ]; then
printf '%s' "$reval"
else
echo "$reval"
fi fi
echo "$reval"
} }
# #
@@ -780,8 +856,11 @@ in_config()
local group="${groups%%\|*}" local group="${groups%%\|*}"
# Remove the remainder (the group name) from the rest # Remove the remainder (the group name) from the rest
# of the groups list (as if it were a prefix): # of the groups list (as if it were a prefix):
groups="${groups#$group}" if [ "$group" != "$groups" ]; then
groups="${groups#\|}" groups="${groups#*\|}"
else
groups=""
fi
# If the group name is the same as the "mysqld" without "--" prefix, # If the group name is the same as the "mysqld" without "--" prefix,
# then try to use it together with the group suffix: # then try to use it together with the group suffix:
if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
@@ -804,7 +883,11 @@ in_config()
break break
fi fi
done done
echo $found if [ -n "$BASH_VERSION" ]; then
printf '%s' $found
else
echo $found
fi
} }
wsrep_auth_not_set() wsrep_auth_not_set()
@@ -937,11 +1020,22 @@ wsrep_gen_secret()
{ {
get_openssl get_openssl
if [ -n "$OPENSSL_BINARY" ]; then if [ -n "$OPENSSL_BINARY" ]; then
echo $("$OPENSSL_BINARY" rand -hex 16) "$OPENSSL_BINARY" rand -hex 16
else elif [ -n "$BASH_VERSION" ]; then
printf "%04x%04x%04x%04x%04x%04x%04x%04x" \ printf '%04x%04x%04x%04x%04x%04x%04x%04x' \
$RANDOM $RANDOM $RANDOM $RANDOM \ $RANDOM $RANDOM $RANDOM $RANDOM \
$RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM $RANDOM
elif [ -n "$(commandex cksum)" -a \
-n "$(commandex printf)" ]
then
printf '%08x%08x%08x%08x' \
$(head -8 /dev/urandom | cksum | cut -d ' ' -f1) \
$(head -8 /dev/urandom | cksum | cut -d ' ' -f1) \
$(head -8 /dev/urandom | cksum | cut -d ' ' -f1) \
$(head -8 /dev/urandom | cksum | cut -d ' ' -f1)
else
wsrep_log_error "Unable to generate 16-byte secret"
exit 22
fi fi
} }
@@ -979,14 +1073,14 @@ is_local_ip()
if [ -n "$ip_util" ]; then if [ -n "$ip_util" ]; then
# ip address show ouput format is " inet[6] <address>/<mask>": # ip address show ouput format is " inet[6] <address>/<mask>":
"$ip_util" address show \ "$ip_util" address show \
| grep -E "^[[:space:]]*inet.? [^[:space:]]+/" -o \ | grep -E '^[[:space:]]*inet.? [^[:space:]]+/' -o \
| grep -F " $1/" >/dev/null && return 0 | grep -F " $1/" >/dev/null && return 0
else else
local ifconfig_util=$(commandex 'ifconfig') local ifconfig_util=$(commandex 'ifconfig')
if [ -n "$ifconfig_util" ]; then if [ -n "$ifconfig_util" ]; then
# ifconfig output format is " inet[6] <address> ...": # ifconfig output format is " inet[6] <address> ...":
"$ifconfig_util" \ "$ifconfig_util" \
| grep -E "^[[:space:]]*inet.? [^[:space:]]+ " -o \ | grep -E '^[[:space:]]*inet.? [^[:space:]]+ ' -o \
| grep -F " $1 " >/dev/null && return 0 | grep -F " $1 " >/dev/null && return 0
fi fi
fi fi
@@ -1049,7 +1143,7 @@ check_port()
ss -nlpH "( sport = :$port )" 2>/dev/null | \ ss -nlpH "( sport = :$port )" 2>/dev/null | \
grep -q -E "users:\\(.*\\(\"($utils)[^[:space:]]*\"[^)]*,pid=$pid(,[^)]*)?\\)" && rc=0 grep -q -E "users:\\(.*\\(\"($utils)[^[:space:]]*\"[^)]*,pid=$pid(,[^)]*)?\\)" && rc=0
else else
wsrep_log_error "unknown sockets utility" wsrep_log_error "Unknown sockets utility"
exit 2 # ENOENT exit 2 # ENOENT
fi fi
@@ -1158,13 +1252,6 @@ verify_cert_matches_key()
exit 22 exit 22
fi fi
# If the diff utility is not installed, then
# we will not do this certificate check:
if [ -z "$(commandex diff)" ]; then
wsrep_log_info "diff utility not found"
return
fi
# If the openssl utility is not installed, then # If the openssl utility is not installed, then
# we will not do this certificate check: # we will not do this certificate check:
get_openssl get_openssl
@@ -1175,9 +1262,9 @@ verify_cert_matches_key()
# Generate the public key from the cert and the key. # Generate the public key from the cert and the key.
# They should match (otherwise we can't create an SSL connection). # They should match (otherwise we can't create an SSL connection).
if ! diff <("$OPENSSL_BINARY" x509 -in "$cert" -pubkey -noout 2>/dev/null) \ local pk1=$("$OPENSSL_BINARY" x509 -in "$cert" -pubkey -noout 2>/dev/null || :)
<("$OPENSSL_BINARY" pkey -in "$key" -pubout 2>/dev/null) >/dev/null 2>&1 local pk2=$("$OPENSSL_BINARY" pkey -in "$key" -pubout 2>/dev/null || :)
then if [ "$pk1" != "$pk2" ]; then
wsrep_log_error "******************* FATAL ERROR *****************" wsrep_log_error "******************* FATAL ERROR *****************"
wsrep_log_error "* The certificate and private key do not match. *" wsrep_log_error "* The certificate and private key do not match. *"
wsrep_log_error "* Please check your certificate and key files. *" wsrep_log_error "* Please check your certificate and key files. *"
@@ -1220,28 +1307,6 @@ check_for_version()
return 0 return 0
} }
trim_string()
{
if [ -n "$BASH_VERSION" ]; then
local pattern="[![:space:]${2:-}]"
local x="${1#*$pattern}"
local z=${#1}
x=${#x}
if [ $x -ne $z ]; then
local y="${1%$pattern*}"
y=${#y}
x=$(( z-x-1 ))
y=$(( y-x+1 ))
printf '%s' "${1:$x:$y}"
else
printf ''
fi
else
local pattern="[[:space:]${2:-}]"
echo "$1" | sed -E "s/^$pattern+|$pattern+\$//g"
fi
}
# #
# Check whether process is still running. # Check whether process is still running.
# The first parameter contains the name of the PID file. # The first parameter contains the name of the PID file.
@@ -1272,6 +1337,10 @@ check_pid()
rm -f "$pid_file" || : rm -f "$pid_file" || :
fi fi
fi fi
local config="${3:-}"
if [ -n "$config" -a -f "$config" ]; then
rm -f "$config" || :
fi
CHECK_PID=0 CHECK_PID=0
return 1 return 1
} }
@@ -1377,13 +1446,9 @@ check_server_ssl_config()
fi fi
fi fi
if [ -n "$tcert" ]; then if [ -n "$tcert" ]; then
tcert=$(trim_string "$tcert")
if [ "${tcert%/}" != "$tcert" -o -d "$tcert" ]; then if [ "${tcert%/}" != "$tcert" -o -d "$tcert" ]; then
tcap="$tcert" tcap="$tcert"
tcert="" tcert=""
fi fi
fi fi
if [ -n "$tcap" ]; then
tcap=$(trim_string "$tcap")
fi
} }

View File

@@ -2,7 +2,7 @@
set -ue set -ue
# Copyright (C) 2017-2021 MariaDB # Copyright (C) 2017-2022 MariaDB
# Copyright (C) 2013 Percona Inc # Copyright (C) 2013 Percona Inc
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@@ -40,7 +40,7 @@ tcert=""
tcap="" tcap=""
tpem="" tpem=""
tkey="" tkey=""
tmode="DISABLED" tmode=""
sockopt="" sockopt=""
progress="" progress=""
ttime=0 ttime=0
@@ -85,13 +85,13 @@ backup_threads=""
encrypt_threads="" encrypt_threads=""
encrypt_chunk="" encrypt_chunk=""
readonly SECRET_TAG="secret" readonly SECRET_TAG='secret'
# Required for backup locks # Required for backup locks
# For backup locks it is 1 sent by joiner # For backup locks it is 1 sent by joiner
sst_ver=1 sst_ver=1
if [ -n "$(commandex pv)" ] && pv --help | grep -qw -- '-F'; then if [ -n "$(commandex pv)" ] && pv --help | grep -qw -F -- '-F'; then
pvopts="$pvopts $pvformat" pvopts="$pvopts $pvformat"
fi fi
pcmd="pv $pvopts" pcmd="pv $pvopts"
@@ -104,17 +104,14 @@ if [ -z "$BACKUP_BIN" ]; then
fi fi
DATA="$WSREP_SST_OPT_DATA" DATA="$WSREP_SST_OPT_DATA"
INFO_FILE="xtrabackup_galera_info" INFO_FILE='xtrabackup_galera_info'
IST_FILE="xtrabackup_ist" IST_FILE='xtrabackup_ist'
MAGIC_FILE="$DATA/$INFO_FILE" MAGIC_FILE="$DATA/$INFO_FILE"
INNOAPPLYLOG="$DATA/mariabackup.prepare.log" INNOAPPLYLOG="$DATA/mariabackup.prepare.log"
INNOMOVELOG="$DATA/mariabackup.move.log" INNOMOVELOG="$DATA/mariabackup.move.log"
INNOBACKUPLOG="$DATA/mariabackup.backup.log" INNOBACKUPLOG="$DATA/mariabackup.backup.log"
# Setting the path for ss and ip
export PATH="/usr/sbin:/sbin:$PATH"
timeit() timeit()
{ {
local stage="$1" local stage="$1"
@@ -154,7 +151,7 @@ get_keys()
return return
fi fi
if [ $sfmt = 'tar' ]; then if [ "$sfmt" = 'tar' ]; then
wsrep_log_info "NOTE: key-based encryption (encrypt=1)" \ wsrep_log_info "NOTE: key-based encryption (encrypt=1)" \
"cannot be enabled with tar format" "cannot be enabled with tar format"
encrypt=-1 encrypt=-1
@@ -184,11 +181,11 @@ get_keys()
exit 2 exit 2
fi fi
ecmd="'$OPENSSL_BINARY' enc -$ealgo" ecmd="'$OPENSSL_BINARY' enc -$ealgo"
if "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-pbkdf2'; then if "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -F -- '-pbkdf2'; then
ecmd="$ecmd -pbkdf2" ecmd="$ecmd -pbkdf2"
elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-iter'; then elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -F -- '-iter'; then
ecmd="$ecmd -iter 1" ecmd="$ecmd -iter 1"
elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -- '-md'; then elif "$OPENSSL_BINARY" enc -help 2>&1 | grep -qw -F -- '-md'; then
ecmd="$ecmd -md sha256" ecmd="$ecmd -md sha256"
fi fi
if [ -z "$ekey" ]; then if [ -z "$ekey" ]; then
@@ -229,15 +226,15 @@ get_keys()
get_transfer() get_transfer()
{ {
if [ $tfmt = 'nc' ]; then if [ "$tfmt" = 'nc' ]; then
wsrep_log_info "Using netcat as streamer" wsrep_log_info "Using netcat as streamer"
wsrep_check_programs nc wsrep_check_programs nc
tcmd="nc" tcmd='nc'
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
if nc -h 2>&1 | grep -q 'ncat'; then if nc -h 2>&1 | grep -q -F 'ncat'; then
wsrep_log_info "Using Ncat as streamer" wsrep_log_info "Using Ncat as streamer"
tcmd="$tcmd -l" tcmd="$tcmd -l"
elif nc -h 2>&1 | grep -qw -- '-d'; then elif nc -h 2>&1 | grep -qw -F -- '-d'; then
wsrep_log_info "Using Debian netcat as streamer" wsrep_log_info "Using Debian netcat as streamer"
tcmd="$tcmd -dl" tcmd="$tcmd -dl"
if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then if [ $WSREP_SST_OPT_HOST_IPv6 -eq 1 ]; then
@@ -259,14 +256,14 @@ get_transfer()
# transfer and cause the command to timeout. # transfer and cause the command to timeout.
# Older versions of netcat did not need this flag and will # Older versions of netcat did not need this flag and will
# return an error if the flag is used. # return an error if the flag is used.
if nc -h 2>&1 | grep -qw -- '-N'; then if nc -h 2>&1 | grep -qw -F -- '-N'; then
tcmd="$tcmd -N" tcmd="$tcmd -N"
wsrep_log_info "Using nc -N" wsrep_log_info "Using nc -N"
fi fi
# netcat doesn't understand [] around IPv6 address # netcat doesn't understand [] around IPv6 address
if nc -h 2>&1 | grep -q ncat; then if nc -h 2>&1 | grep -q -F 'ncat'; then
wsrep_log_info "Using Ncat as streamer" wsrep_log_info "Using Ncat as streamer"
elif nc -h 2>&1 | grep -qw -- '-d'; then elif nc -h 2>&1 | grep -qw -F -- '-d'; then
wsrep_log_info "Using Debian netcat as streamer" wsrep_log_info "Using Debian netcat as streamer"
else else
wsrep_log_info "Using traditional netcat as streamer" wsrep_log_info "Using traditional netcat as streamer"
@@ -326,7 +323,8 @@ get_transfer()
if [ "${sockopt#*,dhparam=}" != "$sockopt" ]; then if [ "${sockopt#*,dhparam=}" != "$sockopt" ]; then
if [ -z "$ssl_dhparams" ]; then if [ -z "$ssl_dhparams" ]; then
# Determine the socat version # Determine the socat version
SOCAT_VERSION=$(socat -V 2>&1 | grep -m1 -oe '[0-9]\.[0-9][\.0-9]*') SOCAT_VERSION=$(socat -V 2>&1 | \
grep -m1 -owE '[0-9]+(\.[0-9]+)+' | head -n1)
if [ -z "$SOCAT_VERSION" ]; then if [ -z "$SOCAT_VERSION" ]; then
wsrep_log_error "******** FATAL ERROR ******************" wsrep_log_error "******** FATAL ERROR ******************"
wsrep_log_error "* Cannot determine the socat version. *" wsrep_log_error "* Cannot determine the socat version. *"
@@ -456,7 +454,7 @@ adjust_progress()
fi fi
elif [ -z "$progress" -a -n "$rlimit" ]; then elif [ -z "$progress" -a -n "$rlimit" ]; then
# When rlimit is non-zero # When rlimit is non-zero
pcmd="pv -q" pcmd='pv -q'
fi fi
if [ -n "$rlimit" -a "$WSREP_SST_OPT_ROLE" = 'donor' ]; then if [ -n "$rlimit" -a "$WSREP_SST_OPT_ROLE" = 'donor' ]; then
@@ -476,6 +474,15 @@ read_cnf()
tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \ tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \
tr [:lower:] [:upper:]) tr [:lower:] [:upper:])
case "$tmode" in
'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED')
;;
*)
wsrep_log_error "Unrecognized ssl-mode option: '$tmode'"
exit 22 # EINVAL
;;
esac
if [ $encrypt -eq 0 -o $encrypt -ge 2 ]; then if [ $encrypt -eq 0 -o $encrypt -ge 2 ]; then
if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then
check_server_ssl_config check_server_ssl_config
@@ -583,8 +590,14 @@ get_stream()
sig_joiner_cleanup() sig_joiner_cleanup()
{ {
local estatus=$?
if [ $estatus -ne 0 ]; then
wsrep_log_error "Cleanup after exit with status: $estatus"
fi
wsrep_log_error "Removing $MAGIC_FILE file due to signal" wsrep_log_error "Removing $MAGIC_FILE file due to signal"
[ "$(pwd)" != "$OLD_PWD" ] && cd "$OLD_PWD"
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
exit $estatus
} }
cleanup_at_exit() cleanup_at_exit()
@@ -595,6 +608,8 @@ cleanup_at_exit()
wsrep_log_error "Cleanup after exit with status: $estatus" wsrep_log_error "Cleanup after exit with status: $estatus"
fi fi
[ "$(pwd)" != "$OLD_PWD" ] && cd "$OLD_PWD"
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
wsrep_log_info "Removing the sst_in_progress file" wsrep_log_info "Removing the sst_in_progress file"
wsrep_cleanup_progress_file wsrep_cleanup_progress_file
@@ -624,7 +639,7 @@ cleanup_at_exit()
fi fi
# Final cleanup # Final cleanup
pgid=$(ps -o pgid= $$ 2>/dev/null | grep -o '[0-9]*' || :) pgid=$(ps -o pgid= $$ 2>/dev/null | grep -o -E '[0-9]*' || :)
# This means no setsid done in mysqld. # This means no setsid done in mysqld.
# We don't want to kill mysqld here otherwise. # We don't want to kill mysqld here otherwise.
@@ -661,16 +676,13 @@ setup_ports()
# #
wait_for_listen() wait_for_listen()
{ {
local PORT="$1"
local ADDR="$2"
local MODULE="$3"
for i in {1..150}; do for i in {1..150}; do
if check_port "" "$PORT" 'socat|nc'; then if check_port "" "$SST_PORT" 'socat|nc'; then
break break
fi fi
sleep 0.2 sleep 0.2
done done
echo "ready $ADDR/$MODULE//$sst_ver" echo "ready $ADDR:$SST_PORT/$MODULE/$lsn/$sst_ver"
} }
check_extra() check_extra()
@@ -715,7 +727,7 @@ recv_joiner()
local ltcmd="$tcmd" local ltcmd="$tcmd"
if [ $tmt -gt 0 ]; then if [ $tmt -gt 0 ]; then
if [ -n "$(commandex timeout)" ]; then if [ -n "$(commandex timeout)" ]; then
if timeout --help | grep -qw -- '-k'; then if timeout --help | grep -qw -F -- '-k'; then
ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd" ltcmd="timeout -k $(( tmt+10 )) $tmt $tcmd"
else else
ltcmd="timeout -s9 $tmt $tcmd" ltcmd="timeout -s9 $tmt $tcmd"
@@ -727,7 +739,7 @@ recv_joiner()
set +e set +e
if [ $wait -ne 0 ]; then if [ $wait -ne 0 ]; then
wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" & wait_for_listen &
fi fi
timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
@@ -761,7 +773,7 @@ recv_joiner()
# check donor supplied secret # check donor supplied secret
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | \ SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | \
cut -d ' ' -f 2) cut -d ' ' -f2)
if [ "$SECRET" != "$MY_SECRET" ]; then if [ "$SECRET" != "$MY_SECRET" ]; then
wsrep_log_error "Donor does not know my secret!" wsrep_log_error "Donor does not know my secret!"
wsrep_log_info "Donor: '$SECRET', my: '$MY_SECRET'" wsrep_log_info "Donor: '$SECRET', my: '$MY_SECRET'"
@@ -815,7 +827,9 @@ monitor_process()
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
if [ "$WSREP_SST_OPT_ROLE" != 'joiner' -a "$WSREP_SST_OPT_ROLE" != 'donor' ]; then if [ "$WSREP_SST_OPT_ROLE" != 'joiner' -a \
"$WSREP_SST_OPT_ROLE" != 'donor' ]
then
wsrep_log_error "Invalid role '$WSREP_SST_OPT_ROLE'" wsrep_log_error "Invalid role '$WSREP_SST_OPT_ROLE'"
exit 22 exit 22
fi fi
@@ -823,25 +837,17 @@ fi
read_cnf read_cnf
setup_ports setup_ports
if "$BACKUP_BIN" --help 2>/dev/null | grep -qw -- '--version-check'; then if "$BACKUP_BIN" --help 2>/dev/null | grep -qw -F -- '--version-check'; then
disver=' --no-version-check' disver=' --no-version-check'
fi 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)" OLD_PWD="$(pwd)"
cd "$WSREP_SST_OPT_DATA" if [ -n "$DATA" -a "$DATA" != '.' ]; then
if [ -n "$INNODB_DATA_HOME_DIR" ]; then [ ! -d "$DATA" ] && mkdir -p "$DATA"
# handle both relative and absolute paths cd "$DATA"
[ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR"
cd "$INNODB_DATA_HOME_DIR"
fi fi
INNODB_DATA_HOME_DIR=$(pwd -P) DATA_DIR="$(pwd)"
cd "$OLD_PWD" cd "$OLD_PWD"
@@ -869,7 +875,7 @@ if [ $ssyslog -eq 1 ]; then
else else
if [ $sstlogarchive -eq 1 ] if [ $sstlogarchive -eq 1 ]
then then
ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S.%N") ARCHIVETIMESTAMP=$(date '+%Y.%m.%d-%H.%M.%S.%N')
if [ -n "$sstlogarchivedir" ]; then if [ -n "$sstlogarchivedir" ]; then
if [ ! -d "$sstlogarchivedir" ]; then if [ ! -d "$sstlogarchivedir" ]; then
@@ -929,7 +935,7 @@ setup_commands()
recovery=" --innodb-force-recovery=$INNODB_FORCE_RECOVERY" recovery=" --innodb-force-recovery=$INNODB_FORCE_RECOVERY"
fi fi
INNOAPPLY="$BACKUP_BIN --prepare$disver$recovery${iapts:+ }$iapts$INNOEXTRA --target-dir='$DATA' --datadir='$DATA'$mysqld_args $INNOAPPLY" INNOAPPLY="$BACKUP_BIN --prepare$disver$recovery${iapts:+ }$iapts$INNOEXTRA --target-dir='$DATA' --datadir='$DATA'$mysqld_args $INNOAPPLY"
INNOMOVE="$BACKUP_BIN$WSREP_SST_OPT_CONF --move-back$disver${impts:+ }$impts --force-non-empty-directories --target-dir='$DATA' --datadir='${TDATA:-$DATA}' $INNOMOVE" INNOMOVE="$BACKUP_BIN$WSREP_SST_OPT_CONF --move-back$disver${impts:+ }$impts$INNOEXTRA --force-non-empty-directories --target-dir='$DATA' --datadir='${TDATA:-$DATA}' $INNOMOVE"
INNOBACKUP="$BACKUP_BIN$WSREP_SST_OPT_CONF --backup$disver${iopts:+ }$iopts$tmpopts$INNOEXTRA --galera-info --stream=$sfmt --target-dir='$itmpdir' --datadir='$DATA'$mysqld_args $INNOBACKUP" INNOBACKUP="$BACKUP_BIN$WSREP_SST_OPT_CONF --backup$disver${iopts:+ }$iopts$tmpopts$INNOEXTRA --galera-info --stream=$sfmt --target-dir='$itmpdir' --datadir='$DATA'$mysqld_args $INNOBACKUP"
} }
@@ -1052,6 +1058,11 @@ then
iopts="--parallel=$backup_threads${iopts:+ }$iopts" iopts="--parallel=$backup_threads${iopts:+ }$iopts"
fi fi
max_binlogs=$(parse_cnf "$encgroups" 'sst-max-binlogs')
if [ -n "$max_binlogs" ]; then
iopts="--sst-max-binlogs=$max_binlogs${iopts:+ }$iopts"
fi
setup_commands setup_commands
set +e set +e
timeit "$stagemsg-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" timeit "$stagemsg-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
@@ -1096,6 +1107,7 @@ then
echo "done $WSREP_SST_OPT_GTID" echo "done $WSREP_SST_OPT_GTID"
wsrep_log_info "Total time on donor: $totime seconds" wsrep_log_info "Total time on donor: $totime seconds"
wsrep_log_info "mariabackup SST/IST completed on donor"
elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
then then
@@ -1103,22 +1115,53 @@ then
wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
[ -n "$SST_PROGRESS_FILE" ] && touch "$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_DATA_HOME_DIR environment
# variable is not set, try to get it from the my.cnf:
if [ -z "$INNODB_DATA_HOME_DIR" ]; then
INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir')
INNODB_DATA_HOME_DIR=$(trim_dir "$INNODB_DATA_HOME_DIR")
fi
if [ -n "$INNODB_DATA_HOME_DIR" -a "$INNODB_DATA_HOME_DIR" != '.' ]; then
# handle both relative and absolute paths:
cd "$DATA"
[ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR"
cd "$INNODB_DATA_HOME_DIR"
ib_home_dir="$(pwd)"
cd "$OLD_PWD"
fi
# if no command line argument and INNODB_LOG_GROUP_HOME is not set, # if no command line argument and INNODB_LOG_GROUP_HOME is not set,
# try to get it from my.cnf: # then try to get it from the my.cnf:
if [ -z "$INNODB_LOG_GROUP_HOME" ]; then if [ -z "$INNODB_LOG_GROUP_HOME" ]; then
INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir') INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir')
INNODB_LOG_GROUP_HOME=$(trim_dir "$INNODB_LOG_GROUP_HOME")
fi fi
ib_log_dir="$INNODB_LOG_GROUP_HOME" if [ -n "$INNODB_LOG_GROUP_HOME" -a "$INNODB_LOG_GROUP_HOME" != '.' ]; then
# handle both relative and absolute paths:
cd "$DATA"
[ ! -d "$INNODB_LOG_GROUP_HOME" ] && mkdir -p "$INNODB_LOG_GROUP_HOME"
cd "$INNODB_LOG_GROUP_HOME"
ib_log_dir="$(pwd)"
cd "$OLD_PWD"
fi
# if no command line argument then try to get it from my.cnf: # if no command line argument and INNODB_UNDO_DIR is not set,
# then try to get it from the my.cnf:
if [ -z "$INNODB_UNDO_DIR" ]; then if [ -z "$INNODB_UNDO_DIR" ]; then
INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory') INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory')
INNODB_UNDO_DIR=$(trim_dir "$INNODB_UNDO_DIR")
fi fi
ib_undo_dir="$INNODB_UNDO_DIR" if [ -n "$INNODB_UNDO_DIR" -a "$INNODB_UNDO_DIR" != '.' ]; then
# handle both relative and absolute paths:
cd "$DATA"
[ ! -d "$INNODB_UNDO_DIR" ] && mkdir -p "$INNODB_UNDO_DIR"
cd "$INNODB_UNDO_DIR"
ib_undo_dir="$(pwd)"
cd "$OLD_PWD"
fi
if [ -n "$backup_threads" ]; then if [ -n "$backup_threads" ]; then
impts="--parallel=$backup_threads${impts:+ }$impts" impts="--parallel=$backup_threads${impts:+ }$impts"
@@ -1142,16 +1185,15 @@ then
stagemsg='Joiner-Recv' stagemsg='Joiner-Recv'
MODULE="xtrabackup_sst" MODULE="${WSREP_SST_OPT_MODULE:-xtrabackup_sst}"
[ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE"
# May need xtrabackup_checkpoints later on # May need xtrabackup_checkpoints later on
[ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary"
[ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" [ -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" ADDR="$WSREP_SST_OPT_HOST"
if [ "${tmode#VERIFY}" != "$tmode" ]; then if [ "${tmode#VERIFY}" != "$tmode" ]; then
# backward-incompatible behavior: # backward-incompatible behavior:
@@ -1165,7 +1207,7 @@ then
exit 42 exit 42
fi fi
CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \ CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \
tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ tr ',' '\n' | grep -F 'CN =' | cut -d '=' -f2 | sed s/^\ // | \
sed s/\ %//) sed s/\ %//)
fi fi
MY_SECRET="$(wsrep_gen_secret)" MY_SECRET="$(wsrep_gen_secret)"
@@ -1219,6 +1261,36 @@ then
jpid=$! jpid=$!
wsrep_log_info "Proceeding with SST" wsrep_log_info "Proceeding with SST"
get_binlog
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG")
binlog_base=$(basename "$WSREP_SST_OPT_BINLOG")
binlog_index="$WSREP_SST_OPT_BINLOG_INDEX"
cd "$DATA"
wsrep_log_info "Cleaning the old binary logs"
# If there is a file with binlogs state, delete it:
[ -f "$binlog_base.state" ] && rm -fv "$binlog_base.state" 1>&2
# Clean up the old binlog files and index:
if [ -f "$binlog_index" ]; then
while read bin_file || [ -n "$bin_file" ]; do
rm -fv "$bin_file" 1>&2 || :
done < "$binlog_index"
rm -fv "$binlog_index" 1>&2
fi
if [ -n "$binlog_dir" -a "$binlog_dir" != '.' -a \
-d "$binlog_dir" ]
then
cd "$binlog_dir"
if [ "$(pwd)" != "$DATA_DIR" ]; then
wsrep_log_info \
"Cleaning the binlog directory '$binlog_dir' as well"
fi
fi
rm -fv "$binlog_base".[0-9]* 1>&2 || :
cd "$OLD_PWD"
fi
wsrep_log_info \ wsrep_log_info \
"Cleaning the existing datadir and innodb-data/log directories" "Cleaning the existing datadir and innodb-data/log directories"
if [ "$OS" = 'FreeBSD' ]; then if [ "$OS" = 'FreeBSD' ]; then
@@ -1235,20 +1307,6 @@ then
-o -exec rm -rfv {} 1>&2 \+ -o -exec rm -rfv {} 1>&2 \+
fi fi
get_binlog
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG")
if [ -d "$binlog_dir" ]; 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 \+ || :
[ -f "$WSREP_SST_OPT_BINLOG_INDEX" ] && \
rm -fv "$WSREP_SST_OPT_BINLOG_INDEX" 1>&2 \+
cd "$OLD_PWD"
fi
fi
TDATA="$DATA" TDATA="$DATA"
DATA="$DATA/.sst" DATA="$DATA/.sst"
@@ -1282,11 +1340,13 @@ then
dcmd="xargs -n 2 qpress -dT$nproc" dcmd="xargs -n 2 qpress -dT$nproc"
if [ -n "$progress" ] && pv --help | grep -qw -- '--line-mode'; then if [ -n "$progress" ] && \
pv --help | grep -qw -F -- '--line-mode'
then
count=$(find "$DATA" -type f -name '*.qp' | wc -l) count=$(find "$DATA" -type f -name '*.qp' | wc -l)
count=$(( count*2 )) count=$(( count*2 ))
pvopts="-f -s $count -l -N Decompression" pvopts="-f -s $count -l -N Decompression"
if pv --help | grep -qw -- '-F'; then if pv --help | grep -qw -F -- '-F'; then
pvopts="$pvopts -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'" pvopts="$pvopts -F '%N => Rate:%r Elapsed:%t %e Progress: [%b/$count]'"
fi fi
pcmd="pv $pvopts" pcmd="pv $pvopts"
@@ -1296,8 +1356,9 @@ then
# Decompress the qpress files # Decompress the qpress files
wsrep_log_info "Decompression with $nproc threads" wsrep_log_info "Decompression with $nproc threads"
timeit "Joiner-Decompression" \ timeit 'Joiner-Decompression' \
"find '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | $dcmd" "find '$DATA' -type f -name '*.qp' -printf '%p\n%h\n' | \
$dcmd"
extcode=$? extcode=$?
if [ $extcode -eq 0 ]; then if [ $extcode -eq 0 ]; then
@@ -1314,25 +1375,9 @@ then
fi fi
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 || :
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" wsrep_log_info "Preparing the backup at $DATA"
setup_commands setup_commands
timeit "mariabackup prepare stage" "$INNOAPPLY" timeit 'mariabackup prepare stage' "$INNOAPPLY"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
wsrep_log_error "mariabackup apply finished with errors." \ wsrep_log_error "mariabackup apply finished with errors." \
@@ -1340,10 +1385,43 @@ then
exit 22 exit 22
fi fi
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
cd "$DATA"
binlogs=""
if [ -f 'xtrabackup_binlog_info' ]; then
NL=$'\n'
while read bin_string || [ -n "$bin_string" ]; do
bin_file=$(echo "$bin_string" | cut -f1)
if [ -f "$bin_file" ]; then
binlogs="$binlogs${binlogs:+$NL}$bin_file"
fi
done < 'xtrabackup_binlog_info'
else
binlogs=$(ls -d -1 "$binlog_base".[0-9]* 2>/dev/null || :)
fi
cd "$DATA_DIR"
if [ -n "$binlog_dir" -a "$binlog_dir" != '.' ]; then
[ ! -d "$binlog_dir" ] && mkdir -p "$binlog_dir"
fi
index_dir=$(dirname "$binlog_index");
if [ -n "$index_dir" -a "$index_dir" != '.' ]; then
[ ! -d "$index_dir" ] && mkdir -p "$index_dir"
fi
if [ -n "$binlogs" ]; then
wsrep_log_info "Moving binary logs to $binlog_dir"
echo "$binlogs" | \
while read bin_file || [ -n "$bin_file" ]; do
mv "$DATA/$bin_file" "$binlog_dir"
echo "$binlog_dir${binlog_dir:+/}$bin_file" >> "$binlog_index"
done
fi
cd "$OLD_PWD"
fi
MAGIC_FILE="$TDATA/$INFO_FILE" MAGIC_FILE="$TDATA/$INFO_FILE"
wsrep_log_info "Moving the backup to $TDATA" wsrep_log_info "Moving the backup to $TDATA"
timeit "mariabackup move stage" "$INNOMOVE" timeit 'mariabackup move stage' "$INNOMOVE"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
wsrep_log_info "Move successful, removing $DATA" wsrep_log_info "Move successful, removing $DATA"
rm -rf "$DATA" rm -rf "$DATA"
@@ -1370,6 +1448,7 @@ then
cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id cat "$MAGIC_FILE" # Output : UUID:seqno wsrep_gtid_domain_id
wsrep_log_info "Total time on joiner: $totime seconds" wsrep_log_info "Total time on joiner: $totime seconds"
wsrep_log_info "mariabackup SST/IST completed on joiner"
fi fi
exit 0 exit 0

View File

@@ -3,7 +3,7 @@
set -ue set -ue
# Copyright (C) 2009-2015 Codership Oy # Copyright (C) 2009-2015 Codership Oy
# Copyright (C) 2017-2021 MariaDB # Copyright (C) 2017-2022 MariaDB
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@@ -40,8 +40,7 @@ then
fi fi
# Check client version # Check client version
if ! $MYSQL_CLIENT --version | grep 'Distrib 10\.[1-9]' >/dev/null if ! $MYSQL_CLIENT --version | grep -q -E 'Distrib 10\.[1-9]'; then
then
$MYSQL_CLIENT --version >&2 $MYSQL_CLIENT --version >&2
wsrep_log_error "this operation requires MySQL client version 10.1 or newer" wsrep_log_error "this operation requires MySQL client version 10.1 or newer"
exit $EINVAL exit $EINVAL
@@ -95,7 +94,7 @@ DROP PREPARE stmt;"
SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';" SET_START_POSITION="SET GLOBAL wsrep_start_position='$WSREP_SST_OPT_GTID';"
SET_WSREP_GTID_DOMAIN_ID="" SET_WSREP_GTID_DOMAIN_ID=""
if [ -n $WSREP_SST_OPT_GTID_DOMAIN_ID ]; then if [ -n "$WSREP_SST_OPT_GTID_DOMAIN_ID" ]; then
SET_WSREP_GTID_DOMAIN_ID=" SET_WSREP_GTID_DOMAIN_ID="
SET @val = (SELECT GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME = 'WSREP_GTID_STRICT_MODE' AND GLOBAL_VALUE > 0); SET @val = (SELECT GLOBAL_VALUE FROM INFORMATION_SCHEMA.SYSTEM_VARIABLES WHERE VARIABLE_NAME = 'WSREP_GTID_STRICT_MODE' AND GLOBAL_VALUE > 0);
SET @stmt = IF (@val IS NOT NULL, 'SET GLOBAL WSREP_GTID_DOMAIN_ID=$WSREP_SST_OPT_GTID_DOMAIN_ID', 'SET @dummy = 0'); SET @stmt = IF (@val IS NOT NULL, 'SET GLOBAL WSREP_GTID_DOMAIN_ID=$WSREP_SST_OPT_GTID_DOMAIN_ID', 'SET @dummy = 0');

View File

@@ -2,7 +2,7 @@
set -ue set -ue
# Copyright (C) 2017-2021 MariaDB # Copyright (C) 2017-2022 MariaDB
# Copyright (C) 2010-2014 Codership Oy # Copyright (C) 2010-2014 Codership Oy
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@@ -36,6 +36,8 @@ cleanup_joiner()
{ {
local failure=0 local failure=0
[ "$(pwd)" != "$OLD_PWD" ] && cd "$OLD_PWD"
wsrep_log_info "Joiner cleanup: rsync PID=$RSYNC_REAL_PID," \ wsrep_log_info "Joiner cleanup: rsync PID=$RSYNC_REAL_PID," \
"stunnel PID=$STUNNEL_REAL_PID" "stunnel PID=$STUNNEL_REAL_PID"
@@ -58,6 +60,7 @@ cleanup_joiner()
if [ $failure -eq 0 ]; then if [ $failure -eq 0 ]; then
if cleanup_pid $RSYNC_REAL_PID "$RSYNC_PID" "$RSYNC_CONF"; then if cleanup_pid $RSYNC_REAL_PID "$RSYNC_PID" "$RSYNC_CONF"; then
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
[ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE"
else else
wsrep_log_warning "rsync cleanup failed." wsrep_log_warning "rsync cleanup failed."
fi fi
@@ -140,66 +143,77 @@ STUNNEL_PID="$WSREP_SST_OPT_DATA/stunnel.pid"
MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete"
BINLOG_TAR_FILE="$WSREP_SST_OPT_DATA/wsrep_sst_binlog.tar"
BINLOG_N_FILES=1
get_binlog get_binlog
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
BINLOG_DIRNAME=$(dirname "$WSREP_SST_OPT_BINLOG") binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG")
BINLOG_FILENAME=$(basename "$WSREP_SST_OPT_BINLOG") binlog_base=$(basename "$WSREP_SST_OPT_BINLOG")
fi
# 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 fi
OLD_PWD="$(pwd)" OLD_PWD="$(pwd)"
WSREP_LOG_DIR="$INNODB_LOG_GROUP_HOME" DATA="$WSREP_SST_OPT_DATA"
if [ -n "$DATA" -a "$DATA" != '.' ]; then
cd "$WSREP_SST_OPT_DATA" [ ! -d "$DATA" ] && mkdir -p "$DATA"
if [ -n "$WSREP_LOG_DIR" ]; then cd "$DATA"
# handle both relative and absolute paths
[ ! -d "$WSREP_LOG_DIR" ] && mkdir -p "$WSREP_LOG_DIR"
cd "$WSREP_LOG_DIR"
fi fi
WSREP_LOG_DIR=$(pwd -P) DATA_DIR="$(pwd)"
cd "$OLD_PWD" cd "$OLD_PWD"
# if no command line argument and INNODB_DATA_HOME_DIR environment variable BINLOG_TAR_FILE="$DATA_DIR/wsrep_sst_binlog.tar"
# is not set, try to get it from my.cnf:
ib_log_dir="$DATA_DIR"
ib_home_dir="$DATA_DIR"
ib_undo_dir="$DATA_DIR"
# if no command line argument and INNODB_LOG_GROUP_HOME is not set,
# then try to get it from the my.cnf:
if [ -z "$INNODB_LOG_GROUP_HOME" ]; then
INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir')
INNODB_LOG_GROUP_HOME=$(trim_dir "$INNODB_LOG_GROUP_HOME")
fi
if [ -n "$INNODB_LOG_GROUP_HOME" -a "$INNODB_LOG_GROUP_HOME" != '.' ]; then
# handle both relative and absolute paths:
cd "$DATA"
[ ! -d "$INNODB_LOG_GROUP_HOME" ] && mkdir -p "$INNODB_LOG_GROUP_HOME"
cd "$INNODB_LOG_GROUP_HOME"
ib_log_dir="$(pwd)"
cd "$OLD_PWD"
fi
# if no command line argument and INNODB_DATA_HOME_DIR environment
# variable is not set, try to get it from the my.cnf:
if [ -z "$INNODB_DATA_HOME_DIR" ]; then if [ -z "$INNODB_DATA_HOME_DIR" ]; then
INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir') INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir')
INNODB_DATA_HOME_DIR=$(trim_dir "$INNODB_DATA_HOME_DIR")
fi fi
cd "$WSREP_SST_OPT_DATA" if [ -n "$INNODB_DATA_HOME_DIR" -a "$INNODB_DATA_HOME_DIR" != '.' ]; then
if [ -n "$INNODB_DATA_HOME_DIR" ]; then # handle both relative and absolute paths:
# handle both relative and absolute paths cd "$DATA"
[ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR" [ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR"
cd "$INNODB_DATA_HOME_DIR" cd "$INNODB_DATA_HOME_DIR"
ib_home_dir="$(pwd)"
cd "$OLD_PWD"
fi fi
INNODB_DATA_HOME_DIR=$(pwd -P)
cd "$OLD_PWD" # if no command line argument and INNODB_UNDO_DIR is not set,
# then try to get it from the my.cnf:
# if no command line argument then try to get it from my.cnf:
if [ -z "$INNODB_UNDO_DIR" ]; then if [ -z "$INNODB_UNDO_DIR" ]; then
INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory') INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory')
INNODB_UNDO_DIR=$(trim_dir "$INNODB_UNDO_DIR")
fi fi
cd "$WSREP_SST_OPT_DATA" if [ -n "$INNODB_UNDO_DIR" -a "$INNODB_UNDO_DIR" != '.' ]; then
if [ -n "$INNODB_UNDO_DIR" ]; then # handle both relative and absolute paths:
# handle both relative and absolute paths cd "$DATA"
[ ! -d "$INNODB_UNDO_DIR" ] && mkdir -p "$INNODB_UNDO_DIR" [ ! -d "$INNODB_UNDO_DIR" ] && mkdir -p "$INNODB_UNDO_DIR"
cd "$INNODB_UNDO_DIR" cd "$INNODB_UNDO_DIR"
ib_undo_dir="$(pwd)"
cd "$OLD_PWD"
fi fi
INNODB_UNDO_DIR=$(pwd -P)
cd "$OLD_PWD"
encgroups='--mysqld|sst' encgroups='--mysqld|sst'
@@ -224,6 +238,15 @@ if [ -z "$SSLMODE" ]; then
elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then
SSLMODE='REQUIRED' SSLMODE='REQUIRED'
fi fi
else
case "$SSLMODE" in
'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED')
;;
*)
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
exit 22 # EINVAL
;;
esac
fi fi
if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then
@@ -248,18 +271,11 @@ VERIFY_OPT=""
CHECK_OPT="" CHECK_OPT=""
CHECK_OPT_LOCAL="" CHECK_OPT_LOCAL=""
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then
case "$SSLMODE" in if [ "$SSLMODE" = 'VERIFY_IDENTITY' ]; then
'VERIFY_IDENTITY')
VERIFY_OPT='verifyPeer = yes' VERIFY_OPT='verifyPeer = yes'
;; else
'VERIFY_CA')
VERIFY_OPT='verifyChain = yes' VERIFY_OPT='verifyChain = yes'
;; fi
*)
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
exit 22 # EINVAL
;;
esac
if [ -z "$SSTCA$SSTCAP" ]; then if [ -z "$SSTCA$SSTCAP" ]; then
wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path" wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path"
exit 22 # EINVAL exit 22 # EINVAL
@@ -276,7 +292,7 @@ if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then
CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST" CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST"
fi fi
if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
CHECK_OPT_LOCAL="checkHost = localhost" CHECK_OPT_LOCAL='checkHost = localhost'
fi fi
fi fi
fi fi
@@ -293,14 +309,59 @@ if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then
fi fi
fi fi
readonly SECRET_TAG="secret" readonly SECRET_TAG='secret'
if [ "$WSREP_SST_OPT_ROLE" = 'donor' ] SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid"
then
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" # give some time for previous SST to complete:
[ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE" check_round=0
[ -f "$STUNNEL_PID" ] && rm -f "$STUNNEL_PID" while check_pid "$SST_PID" 0; do
wsrep_log_info "Previous SST is not completed, waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 20 ]; then
wsrep_log_error "previous SST script still running."
exit 114 # EALREADY
fi
sleep 1
done
echo $$ > "$SST_PID"
# give some time for stunnel from the previous SST to complete:
check_round=0
while check_pid "$STUNNEL_PID" 1 "$STUNNEL_CONF"; do
wsrep_log_info "Lingering stunnel daemon found at startup," \
"waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "stunnel daemon still running."
exit 114 # EALREADY
fi
sleep 1
done
MODULE="${WSREP_SST_OPT_MODULE:-rsync_sst}"
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
# give some time for rsync from the previous SST to complete:
check_round=0
while check_pid "$RSYNC_PID" 1 "$RSYNC_CONF"; do
wsrep_log_info "Lingering rsync daemon found at startup," \
"waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "rsync daemon still running."
exit 114 # EALREADY
fi
sleep 1
done
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
[ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE"
if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then
if [ -n "$STUNNEL" ] if [ -n "$STUNNEL" ]
then then
@@ -319,8 +380,6 @@ ${VERIFY_OPT}
${CHECK_OPT} ${CHECK_OPT}
${CHECK_OPT_LOCAL} ${CHECK_OPT_LOCAL}
EOF EOF
else
[ -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF"
fi fi
RC=0 RC=0
@@ -333,7 +392,7 @@ EOF
[ -f "$FLUSHED" ] && rm -f "$FLUSHED" [ -f "$FLUSHED" ] && rm -f "$FLUSHED"
[ -f "$ERROR" ] && rm -f "$ERROR" [ -f "$ERROR" ] && rm -f "$ERROR"
echo "flush tables" echo 'flush tables'
# Wait for : # Wait for :
# (a) Tables to be flushed, AND # (a) Tables to be flushed, AND
@@ -357,32 +416,100 @@ EOF
sync sync
if [ -n "$WSREP_SST_OPT_BINLOG" -a -d "${BINLOG_DIRNAME:-}" ] if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
then # Change the directory to binlog base (if possible):
# Prepare binlog files cd "$DATA"
cd "$BINLOG_DIRNAME" # Let's check the existence of the file with the index:
if [ -f "$WSREP_SST_OPT_BINLOG_INDEX" ]; then
binlog_files_full=$(tail -n $BINLOG_N_FILES \ # Let's read the binlog index:
"$WSREP_SST_OPT_BINLOG_INDEX") max_binlogs=$(parse_cnf "$encgroups" 'sst-max-binlogs')
binlog_files="" if [ -n "$max_binlogs" ]; then
for file in $binlog_files_full; do binlog_files=""
binlog_file=$(basename "$file") if [ $max_binlogs -gt 0 ]; then
binlog_files="$binlog_files${binlog_files:+ }'$binlog_file'" binlog_files=$(tail -n $max_binlogs \
done "$WSREP_SST_OPT_BINLOG_INDEX")
fi
if [ -n "$binlog_files" ]; then else
wsrep_log_info "Preparing binlog files for transfer:" binlog_files=$(cat "$WSREP_SST_OPT_BINLOG_INDEX")
eval tar -cvf "'$BINLOG_TAR_FILE'" $binlog_files >&2 fi
if [ -n "$binlog_files" ]; then
# Preparing binlog files for transfer:
wsrep_log_info "Preparing binlog files for transfer:"
tar_type=0
if tar --help | grep -qw -F -- '--transform'; then
tar_type=1
elif tar --version | grep -q -E '^bsdtar\>'; then
tar_type=2
fi
if [ $tar_type -ne 2 ]; then
if [ -n "$BASH_VERSION" ]; then
printf '%s' "$binlog_files" >&2
else
echo "$binlog_files" >&2
fi
fi
if [ $tar_type -ne 0 ]; then
# Preparing list of the binlog file names:
echo "$binlog_files" | {
binlogs=""
while read bin_file || [ -n "$bin_file" ]; do
[ ! -f "$bin_file" ] && continue
if [ -n "$BASH_VERSION" ]; then
first="${bin_file:0:1}"
else
first=$(echo "$bin_file" | cut -c1)
fi
if [ "$first" = '-' -o "$first" = '@' ]; then
bin_file="./$bin_file"
fi
binlogs="$binlogs${binlogs:+ }'$bin_file'"
done
if [ -n "$binlogs" ]; then
if [ $tar_type -eq 1 ]; then
tar_options="--transform='s/^.*\///g'"
else
# bsdtar handles backslash incorrectly:
tar_options="-s '?^.*/??g'"
fi
eval tar -P $tar_options \
-cvf "'$BINLOG_TAR_FILE'" $binlogs >&2
fi
}
else
tar_options='-cvf'
echo "$binlog_files" | \
while read bin_file || [ -n "$bin_file" ]; do
[ ! -f "$bin_file" ] && continue
bin_dir=$(dirname "$bin_file")
bin_base=$(basename "$bin_file")
if [ -n "$BASH_VERSION" ]; then
first="${bin_base:0:1}"
else
first=$(echo "$bin_base" | cut -c1)
fi
if [ "$first" = '-' -o "$first" = '@' ]; then
bin_base="./$bin_base"
fi
if [ -n "$bin_dir" -a "$bin_dir" != '.' ]; then
tar $tar_options "$BINLOG_TAR_FILE" \
-C "$bin_dir" "$bin_base" >&2
else
tar $tar_options "$BINLOG_TAR_FILE" \
"$bin_base" >&2
fi
tar_options='-rvf'
done
fi
fi
fi fi
cd "$OLD_PWD" cd "$OLD_PWD"
fi fi
# Use deltaxfer only for WAN # Use deltaxfer only for WAN:
inv=$(basename "$0") inv=$(basename "$0")
WHOLE_FILE_OPT="" WHOLE_FILE_OPT=""
if [ "${inv%wsrep_sst_rsync_wan*}" = "$inv" ]; then if [ "${inv%wsrep_sst_rsync_wan*}" = "$inv" ]; then
WHOLE_FILE_OPT="--whole-file" WHOLE_FILE_OPT='--whole-file'
fi fi
# Old filter - include everything except selected # Old filter - include everything except selected
@@ -399,9 +526,9 @@ FILTER="-f '- /lost+found'
-f '- /.pid' -f '- /.pid'
-f '- /.conf' -f '- /.conf'
-f '+ /wsrep_sst_binlog.tar' -f '+ /wsrep_sst_binlog.tar'
-f '- $INNODB_DATA_HOME_DIR/ib_lru_dump' -f '- $ib_home_dir/ib_lru_dump'
-f '- $INNODB_DATA_HOME_DIR/ibdata*' -f '- $ib_home_dir/ibdata*'
-f '+ $INNODB_UNDO_DIR/undo*' -f '+ $ib_undo_dir/undo*'
-f '+ /*/' -f '+ /*/'
-f '- /*'" -f '- /*'"
@@ -435,7 +562,7 @@ FILTER="-f '- /lost+found'
--owner --group --perms --links --specials \ --owner --group --perms --links --specials \
--ignore-times --inplace --dirs --delete --quiet \ --ignore-times --inplace --dirs --delete --quiet \
$WHOLE_FILE_OPT -f '+ /ibdata*' -f '+ /ib_lru_dump' \ $WHOLE_FILE_OPT -f '+ /ibdata*' -f '+ /ib_lru_dump' \
-f '- **' "$INNODB_DATA_HOME_DIR/" \ -f '- **' "$ib_home_dir/" \
"rsync://$WSREP_SST_OPT_ADDR-data_dir" >&2 || RC=$? "rsync://$WSREP_SST_OPT_ADDR-data_dir" >&2 || RC=$?
if [ $RC -ne 0 ]; then if [ $RC -ne 0 ]; then
@@ -448,7 +575,7 @@ FILTER="-f '- /lost+found'
--owner --group --perms --links --specials \ --owner --group --perms --links --specials \
--ignore-times --inplace --dirs --delete --quiet \ --ignore-times --inplace --dirs --delete --quiet \
$WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' \ $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' \
-f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ -f '+ /aria_log_control' -f '- **' "$ib_log_dir/" \
"rsync://$WSREP_SST_OPT_ADDR-log_dir" >&2 || RC=$? "rsync://$WSREP_SST_OPT_ADDR-log_dir" >&2 || RC=$?
if [ $RC -ne 0 ]; then if [ $RC -ne 0 ]; then
@@ -459,7 +586,7 @@ FILTER="-f '- /lost+found'
# then, we parallelize the transfer of database directories, # then, we parallelize the transfer of database directories,
# use '.' so that path concatenation works: # use '.' so that path concatenation works:
cd "$WSREP_SST_OPT_DATA" cd "$DATA"
backup_threads=$(parse_cnf '--mysqld|sst' 'backup-threads') backup_threads=$(parse_cnf '--mysqld|sst' 'backup-threads')
if [ -z "$backup_threads" ]; then if [ -z "$backup_threads" ]; then
@@ -518,68 +645,21 @@ FILTER="-f '- /lost+found'
[ -f "$STUNNEL_PID" ] && rm -f "$STUNNEL_PID" [ -f "$STUNNEL_PID" ] && rm -f "$STUNNEL_PID"
fi fi
[ -f "$SST_PID" ] && rm -f "$SST_PID"
wsrep_log_info "rsync SST/IST completed on donor"
elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
then then
check_sockets_utils check_sockets_utils
SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid" ADDR="$WSREP_SST_OPT_HOST"
# give some time for previous SST to complete:
check_round=0
while check_pid "$SST_PID" 0 'wsrep_sst_'; do
wsrep_log_info "previous SST is not completed, waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "previous SST script still running."
exit 114 # EALREADY
fi
sleep 1
done
echo $$ > "$SST_PID"
# give some time for stunnel from the previous SST to complete:
check_round=0
while check_pid "$STUNNEL_PID" 1; do
wsrep_log_info "Lingering stunnel daemon found at startup," \
"waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "stunnel daemon already running."
exit 114 # EALREADY
fi
sleep 1
done
MODULE="rsync_sst"
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
# give some time for rsync from the previous SST to complete:
check_round=0
while check_pid "$RSYNC_PID" 1; do
wsrep_log_info "Lingering rsync daemon found at startup," \
"waiting for it to exit"
check_round=$(( check_round + 1 ))
if [ $check_round -eq 10 ]; then
wsrep_log_error "rsync daemon already running."
exit 114 # EALREADY
fi
sleep 1
done
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
[ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE"
[ -z "$STUNNEL" -a -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF"
ADDR="$WSREP_SST_OPT_ADDR"
RSYNC_PORT="$WSREP_SST_OPT_PORT" RSYNC_PORT="$WSREP_SST_OPT_PORT"
RSYNC_ADDR="$WSREP_SST_OPT_HOST" RSYNC_ADDR="$WSREP_SST_OPT_HOST"
RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED" RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED"
trap "exit 32" HUP PIPE trap 'exit 32' HUP PIPE
trap "exit 3" INT TERM ABRT trap 'exit 3' INT TERM ABRT
trap cleanup_joiner EXIT trap cleanup_joiner EXIT
touch "$SST_PROGRESS_FILE" touch "$SST_PROGRESS_FILE"
@@ -600,13 +680,11 @@ $SILENT
path = $WSREP_SST_OPT_DATA path = $WSREP_SST_OPT_DATA
exclude = .zfs exclude = .zfs
[$MODULE-log_dir] [$MODULE-log_dir]
path = $WSREP_LOG_DIR path = $ib_log_dir
[$MODULE-data_dir] [$MODULE-data_dir]
path = $INNODB_DATA_HOME_DIR path = $ib_home_dir
EOF EOF
# rm -rf "$DATA/ib_logfile"* # we don't want old logs around
# If the IP is local, listen only on it: # If the IP is local, listen only on it:
if is_local_ip "$RSYNC_ADDR_UNESCAPED" if is_local_ip "$RSYNC_ADDR_UNESCAPED"
then then
@@ -617,7 +695,7 @@ EOF
RSYNC_EXTRA_ARGS="" RSYNC_EXTRA_ARGS=""
STUNNEL_ACCEPT="$RSYNC_PORT" STUNNEL_ACCEPT="$RSYNC_PORT"
# Overwrite address with all: # Overwrite address with all:
RSYNC_ADDR="*" RSYNC_ADDR='*'
fi fi
if [ -z "$STUNNEL" ]; then if [ -z "$STUNNEL" ]; then
@@ -675,11 +753,10 @@ EOF
TRANSFER_PID="$STUNNEL_PID" TRANSFER_PID="$STUNNEL_PID"
fi fi
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ] if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then
then # backward-incompatible behavior # backward-incompatible behavior:
CN="" CN=""
if [ -n "$SSTCERT" ] if [ -n "$SSTCERT" ]; then
then
# find out my Common Name # find out my Common Name
get_openssl get_openssl
if [ -z "$OPENSSL_BINARY" ]; then if [ -z "$OPENSSL_BINARY" ]; then
@@ -688,7 +765,7 @@ EOF
exit 42 exit 42
fi fi
CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$SSTCERT" | \ CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$SSTCERT" | \
tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ tr ',' '\n' | grep -F 'CN =' | cut -d '=' -f2 | sed s/^\ // | \
sed s/\ %//) sed s/\ %//)
fi fi
MY_SECRET="$(wsrep_gen_secret)" MY_SECRET="$(wsrep_gen_secret)"
@@ -696,7 +773,6 @@ EOF
ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST" ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST"
else else
MY_SECRET="" # for check down in recv_joiner() MY_SECRET="" # for check down in recv_joiner()
ADDR="$WSREP_SST_OPT_HOST"
fi fi
until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \ until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \
@@ -725,16 +801,53 @@ EOF
exit 32 exit 32
fi fi
if [ -r "$MAGIC_FILE" ]; then
if [ -n "$MY_SECRET" ]; then
# Check donor supplied secret:
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | \
cut -d ' ' -f2)
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
fi
else
# This message should cause joiner to abort:
wsrep_log_info "rsync process ended without creating magic file"
echo "rsync process ended without creating '$MAGIC_FILE'"
exit 32
fi
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
if [ -f "$BINLOG_TAR_FILE" ]; then binlog_tar_present=0
cd "$BINLOG_DIRNAME" [ -f "$BINLOG_TAR_FILE" ] && binlog_tar_present=1
# If it is SST (not an IST) or tar with binlogs is present
# among the transferred files, then we need to remove the
# old binlogs:
if [ $WSREP_SST_OPT_BYPASS -eq 0 -o $binlog_tar_present -ne 0 ]; then
cd "$DATA"
# Clean up the old binlog files and index:
binlog_index="$WSREP_SST_OPT_BINLOG_INDEX" binlog_index="$WSREP_SST_OPT_BINLOG_INDEX"
if [ -f "$binlog_index" ]; then
# Clean up old binlog files first while read bin_file || [ -n "$bin_file" ]; do
rm -f "$BINLOG_FILENAME".[0-9]* rm -f "$bin_file" || :
[ -f "$binlog_index" ] && rm -f "$binlog_index" done < "$binlog_index"
rm -f "$binlog_index"
fi
binlog_cd=0
# Change the directory to binlog base (if possible):
if [ -n "$binlog_dir" -a "$binlog_dir" != '.' -a \
-d "$binlog_dir" ]
then
binlog_cd=1
cd "$binlog_dir"
fi
# Clean up unindexed binlog files:
rm -f "$binlog_base".[0-9]* || :
[ $binlog_cd -ne 0 ] && cd "$DATA_DIR"
fi
if [ $binlog_tar_present -ne 0 ]; then
# Create a temporary file: # Create a temporary file:
tmpdir=$(parse_cnf '--mysqld|sst' 'tmpdir') tmpdir=$(parse_cnf '--mysqld|sst' 'tmpdir')
if [ -z "$tmpdir" ]; then if [ -z "$tmpdir" ]; then
@@ -744,46 +857,52 @@ EOF
else else
tmpfile=$(TMPDIR="$tmpdir"; mktemp) tmpfile=$(TMPDIR="$tmpdir"; mktemp)
fi fi
index_dir=$(dirname "$binlog_index");
if [ -n "$index_dir" -a "$index_dir" != '.' ]; then
[ ! -d "$index_dir" ] && mkdir -p "$index_dir"
fi
binlog_cd=0
if [ -n "$binlog_dir" -a "$binlog_dir" != '.' ]; then
[ ! -d "$binlog_dir" ] && mkdir -p "$binlog_dir"
binlog_cd=1
cd "$binlog_dir"
fi
# Extracting binlog files:
wsrep_log_info "Extracting binlog files:" wsrep_log_info "Extracting binlog files:"
if ! tar -xvf "$BINLOG_TAR_FILE" > "$tmpfile"; then RC=0
wsrep_log_error "Error unpacking tar file with binlog files" if tar --version | grep -q -E '^bsdtar\>'; then
tar -tf "$BINLOG_TAR_FILE" > "$tmpfile" && \
tar -xvf "$BINLOG_TAR_FILE" > /dev/null || RC=$?
else
tar -xvf "$BINLOG_TAR_FILE" > "$tmpfile" && \
cat "$tmpfile" >&2 || RC=$?
fi
if [ $RC -ne 0 ]; then
rm -f "$tmpfile" rm -f "$tmpfile"
wsrep_log_error "Error unpacking tar file with binlog files"
exit 32 exit 32
fi fi
# Rebuild binlog index: # Rebuild binlog index:
while read bin_file; do [ $binlog_cd -ne 0 ] && cd "$DATA_DIR"
echo "$BINLOG_DIRNAME/$bin_file" >> "$binlog_index" while read bin_file || [ -n "$bin_file" ]; do
echo "$binlog_dir${binlog_dir:+/}$bin_file" >> "$binlog_index"
done < "$tmpfile" done < "$tmpfile"
rm -f "$tmpfile" rm -f "$tmpfile"
cd "$OLD_PWD" cd "$OLD_PWD"
fi fi
fi fi
if [ -r "$MAGIC_FILE" ]; then if [ -n "$MY_SECRET" ]; then
if [ -n "$MY_SECRET" ]; then # remove secret from the magic file, and output
# check donor supplied secret # the UUID:seqno & wsrep_gtid_domain_id:
SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | \ grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE"
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, and output
# the UUID:seqno & wsrep_gtid_domain_id:
grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE"
else
# Output the UUID:seqno and wsrep_gtid_domain_id:
cat "$MAGIC_FILE"
fi
else else
# this message should cause joiner to abort # Output the UUID:seqno and wsrep_gtid_domain_id:
echo "rsync process ended without creating '$MAGIC_FILE'" cat "$MAGIC_FILE"
fi fi
wsrep_log_info "rsync SST/IST completed on joiner"
# wsrep_cleanup_progress_file # wsrep_cleanup_progress_file
# cleanup_joiner # cleanup_joiner
else else

View File

@@ -2808,12 +2808,9 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
{ {
/* The argument list of the top-level AND may change after fix fields. */ /* The argument list of the top-level AND may change after fix fields. */
and_args= ((Item_cond*) join_arg->conds)->argument_list(); and_args= ((Item_cond*) join_arg->conds)->argument_list();
List_iterator<Item_equal> li(join_arg->cond_equal->current_level); ((Item_cond_and *) (join_arg->conds))->m_cond_equal=
Item_equal *elem; *join_arg->cond_equal;
while ((elem= li++)) and_args->append((List<Item> *)&join_arg->cond_equal->current_level);
{
and_args->push_back(elem, thd->mem_root);
}
} }
} }

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. /* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2021, MariaDB Corporation. Copyright (c) 2009, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -24531,20 +24531,22 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
return 1; return 1;
} }
if (!(*order->item)->with_sum_func())
continue;
/* /*
UNION queries cannot be used with an aggregate function in UNION queries cannot be used with an aggregate function in
an ORDER BY clause an ORDER BY clause
*/ */
if (for_union) if (for_union &&
((*order->item)->with_sum_func() ||
(*order->item)->with_window_func))
{ {
my_error(ER_AGGREGATE_ORDER_FOR_UNION, MYF(0), number); my_error(ER_AGGREGATE_ORDER_FOR_UNION, MYF(0), number);
return 1; return 1;
} }
if (!(*order->item)->with_sum_func())
continue;
if (from_window_spec && (*order->item)->type() != Item::SUM_FUNC_ITEM) if (from_window_spec && (*order->item)->type() != Item::SUM_FUNC_ITEM)
(*order->item)->split_sum_func(thd, ref_pointer_array, (*order->item)->split_sum_func(thd, ref_pointer_array,
all_fields, SPLIT_SUM_SELECT); all_fields, SPLIT_SUM_SELECT);

View File

@@ -2751,7 +2751,7 @@ innobase_trx_init(
while holding lock_sys.mutex, by lock_rec_enqueue_waiting(), while holding lock_sys.mutex, by lock_rec_enqueue_waiting(),
will not end up acquiring LOCK_global_system_variables in will not end up acquiring LOCK_global_system_variables in
intern_sys_var_ptr(). */ intern_sys_var_ptr(). */
THDVAR(thd, lock_wait_timeout); (void) THDVAR(thd, lock_wait_timeout);
trx->check_foreigns = !thd_test_options( trx->check_foreigns = !thd_test_options(
thd, OPTION_NO_FOREIGN_KEY_CHECKS); thd, OPTION_NO_FOREIGN_KEY_CHECKS);
@@ -15979,7 +15979,7 @@ struct ShowStatus {
}; };
/** Order by m_waits, in descending order. */ /** Order by m_waits, in descending order. */
struct OrderByWaits: public std::binary_function<Value, Value, bool> struct OrderByWaits
{ {
/** @return true if rhs < lhs */ /** @return true if rhs < lhs */
bool operator()( bool operator()(

View File

@@ -6711,6 +6711,9 @@ static ST_FIELD_INFO innodb_sys_tablespaces_fields_info[]=
END_OF_ST_FIELD_INFO END_OF_ST_FIELD_INFO
}; };
extern size_t os_file_get_fs_block_size(const char *path);
/**********************************************************************//** /**********************************************************************//**
Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information
collected by scanning SYS_TABLESPACESS table. collected by scanning SYS_TABLESPACESS table.
@@ -6775,11 +6778,10 @@ i_s_dict_fill_sys_tablespaces(
OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store( OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
fil_space_t::physical_size(cflags), true)); fil_space_t::physical_size(cflags), true));
os_file_stat_t stat; size_t fs_block_size = 0;
os_file_size_t file; os_file_size_t file;
memset(&file, 0xff, sizeof(file)); memset(&file, 0xff, sizeof(file));
memset(&stat, 0x0, sizeof(stat));
if (fil_space_t* s = fil_space_acquire_silent(space)) { if (fil_space_t* s = fil_space_acquire_silent(space)) {
const char *filepath = s->chain.start const char *filepath = s->chain.start
@@ -6789,36 +6791,19 @@ i_s_dict_fill_sys_tablespaces(
} }
file = os_file_get_size(filepath); file = os_file_get_size(filepath);
fs_block_size= os_file_get_fs_block_size(filepath);
/* Get the file system (or Volume) block size. */
switch (dberr_t err = os_file_get_status(filepath, &stat,
false, false)) {
case DB_FAIL:
ib::warn()
<< "File '" << filepath << "', failed to get "
<< "stats";
break;
case DB_SUCCESS:
case DB_NOT_FOUND:
break;
default:
ib::error() << "File '" << filepath << "' " << err;
break;
}
file_done: file_done:
s->release(); s->release();
} }
if (file.m_total_size == static_cast<os_offset_t>(~0)) { if (file.m_total_size == static_cast<os_offset_t>(~0)) {
stat.block_size = 0; fs_block_size = 0;
file.m_total_size = 0; file.m_total_size = 0;
file.m_alloc_size = 0; file.m_alloc_size = 0;
} }
OK(fields[SYS_TABLESPACES_FS_BLOCK_SIZE]->store(stat.block_size, true)); OK(fields[SYS_TABLESPACES_FS_BLOCK_SIZE]->store(fs_block_size, true));
OK(fields[SYS_TABLESPACES_FILE_SIZE]->store(file.m_total_size, true)); OK(fields[SYS_TABLESPACES_FILE_SIZE]->store(file.m_total_size, true));

View File

@@ -2,7 +2,7 @@
Copyright (c) 1995, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2019, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2021, MariaDB Corporation. Copyright (c) 2013, 2022, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are by Percona Inc.. Those modifications are
@@ -4351,48 +4351,6 @@ os_file_get_status_win32(
CloseHandle(fh); CloseHandle(fh);
} }
} }
stat_info->block_size = 0;
/* What follows, is calculation of FS block size, which is not important
(it is just shown in I_S innodb tables). The error to calculate it will be ignored.*/
char volname[MAX_PATH];
BOOL result = GetVolumePathName(path, volname, MAX_PATH);
static bool warned_once = false;
if (!result) {
if (!warned_once) {
ib::warn()
<< "os_file_get_status_win32: "
<< "Failed to get the volume path name for: "
<< path
<< "- OS error number " << GetLastError();
warned_once = true;
}
return(DB_SUCCESS);
}
DWORD sectorsPerCluster;
DWORD bytesPerSector;
DWORD numberOfFreeClusters;
DWORD totalNumberOfClusters;
result = GetDiskFreeSpace(
(LPCSTR) volname,
&sectorsPerCluster,
&bytesPerSector,
&numberOfFreeClusters,
&totalNumberOfClusters);
if (!result) {
if (!warned_once) {
ib::warn()
<< "GetDiskFreeSpace(" << volname << ",...) "
<< "failed "
<< "- OS error number " << GetLastError();
warned_once = true;
}
return(DB_SUCCESS);
}
stat_info->block_size = bytesPerSector * sectorsPerCluster;
} else { } else {
stat_info->type = OS_FILE_TYPE_UNKNOWN; stat_info->type = OS_FILE_TYPE_UNKNOWN;
} }
@@ -5284,6 +5242,35 @@ IORequest::punch_hole(os_file_t fh, os_offset_t off, ulint len)
return (err); return (err);
} }
/*
Get file system block size, by path.
This is expensive on Windows, and not very useful in general,
(only shown in some I_S table), so we keep that out of usual
stat.
*/
size_t os_file_get_fs_block_size(const char *path)
{
#ifdef _WIN32
char volname[MAX_PATH];
if (!GetVolumePathName(path, volname, MAX_PATH))
return 0;
DWORD sectorsPerCluster;
DWORD bytesPerSector;
DWORD numberOfFreeClusters;
DWORD totalNumberOfClusters;
if (GetDiskFreeSpace(volname, &sectorsPerCluster, &bytesPerSector,
&numberOfFreeClusters, &totalNumberOfClusters))
return ((size_t) bytesPerSector) * sectorsPerCluster;
#else
os_file_stat_t info;
if (os_file_get_status(path, &info, false, false) == DB_SUCCESS)
return info.block_size;
#endif
return 0;
}
/** This function returns information about the specified file /** This function returns information about the specified file
@param[in] path pathname of the file @param[in] path pathname of the file
@param[out] stat_info information of a file in a directory @param[out] stat_info information of a file in a directory

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2022, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -101,10 +101,6 @@ struct LatchDebug {
/** Comparator for the ThreadMap. */ /** Comparator for the ThreadMap. */
struct os_thread_id_less struct os_thread_id_less
: public std::binary_function<
os_thread_id_t,
os_thread_id_t,
bool>
{ {
/** @return true if lhs < rhs */ /** @return true if lhs < rhs */
bool operator()( bool operator()(
@@ -390,10 +386,6 @@ private:
private: private:
/** Comparator for the Levels . */ /** Comparator for the Levels . */
struct latch_level_less struct latch_level_less
: public std::binary_function<
latch_level_t,
latch_level_t,
bool>
{ {
/** @return true if lhs < rhs */ /** @return true if lhs < rhs */
bool operator()( bool operator()(