Skip to content

Commit

Permalink
MDEV-7611 mysqldump --dump-slave always starts stopped slave
Browse files Browse the repository at this point in the history
When pausing replicas for `mariadb-dump --dump-slave`, store the names
of replicas paused in a dynamically-`malloc`ed buffer; use that (instead
of a new SHOW _SLAVE_ STATUS) to resume replicas when the program ends.

When making a dump with --dump-slave option, upon completion mysqldump
starts slave threads even if they were not stopped by mysqldump itself.
This behavior breaks delayed/manually synchronized
slaves which have not to be running all the time.
⸺ MDEV-7611

Co-authored-by: Max Samoilenko <maxim.samoilenko@gmail.com>
  • Loading branch information
ParadoxV5 and Max Samoilenko committed Jan 21, 2025
1 parent 0b1b622 commit fbffda8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 33 deletions.
64 changes: 32 additions & 32 deletions client/mysqldump.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ static DYNAMIC_STRING dynamic_where;
static MYSQL_RES *get_table_name_result= NULL;
static MEM_ROOT glob_root;
static MYSQL_RES *routine_res, *routine_list_res;

static size_t n_stopped_replicas= 0;
static char (*stopped_replicas)[NAME_CHAR_LEN]= NULL;

#include <sslopt-vars.h>
FILE *md_result_file= 0;
Expand Down Expand Up @@ -1854,6 +1855,7 @@ static void free_resources()
mysql_close(mysql);
mysql= 0;
}
my_free(stopped_replicas);
my_free(order_by);
my_free(opt_password);
my_free(current_host);
Expand Down Expand Up @@ -6097,12 +6099,22 @@ static int do_stop_slave_sql(MYSQL *mysql_con)
{
MYSQL_RES *slave;
MYSQL_ROW row;
// do_stop_slave_sql() should only be called once
DBUG_ASSERT(!stopped_replicas);

if (mysql_query_with_error_report(mysql_con, &slave,
multi_source ?
"SHOW ALL SLAVES STATUS" :
"SHOW SLAVE STATUS"))
return(1);
stopped_replicas= my_malloc(PSI_NOT_INSTRUMENTED,
slave->row_count*NAME_CHAR_LEN + 1, MYF(MY_WME));
if (!stopped_replicas)
{
mysql_free_result(slave);
fputs("Error: Not enough memory to store current replica status\n", stderr);
return 1;
}

/* Loop over all slaves */
while ((row= mysql_fetch_row(slave)))
Expand All @@ -6123,6 +6135,8 @@ static int do_stop_slave_sql(MYSQL *mysql_con)
mysql_free_result(slave);
return 1;
}
strmov(stopped_replicas[n_stopped_replicas++],
multi_source ? row[0] : "");
}
}
}
Expand Down Expand Up @@ -6250,43 +6264,29 @@ static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid,

static int do_start_slave_sql(MYSQL *mysql_con)
{
MYSQL_RES *slave;
MYSQL_ROW row;
int error= 0;
DBUG_ENTER("do_start_slave_sql");

/* We need to check if the slave sql is stopped in the first place */
if (mysql_query_with_error_report(mysql_con, &slave,
multi_source ?
"SHOW ALL SLAVES STATUS" :
"SHOW SLAVE STATUS"))
DBUG_RETURN(1);

while ((row= mysql_fetch_row(slave)))
for (; n_stopped_replicas--;)
{
DBUG_PRINT("info", ("Connection: '%s' status: '%s'",
multi_source ? row[0] : "", row[11 + multi_source]));
if (row[11 + multi_source])
/*
do_start_slave_sql() should only be called
sometime after do_stop_slave_sql() suceeds
*/
char* stopped_replica= stopped_replicas[n_stopped_replicas];
char query[sizeof("START SLAVE ''") + NAME_CHAR_LEN];
DBUG_PRINT("info", ("Connection: '%.*s'", NAME_CHAR_LEN, stopped_replica));
// if SLAVE SQL is running, start it anyway to warn unexpected state change
if (multi_source)
sprintf(query, "START SLAVE '%.*s'", NAME_CHAR_LEN, stopped_replica);

if (mysql_query_with_error_report(mysql_con, 0,
multi_source ? query : "START SLAVE"))
{
/* if SLAVE SQL is not running, we don't start it */
if (strcmp(row[11 + multi_source], "Yes"))
{
char query[160];
if (multi_source)
sprintf(query, "START SLAVE '%.80s'", row[0]);
else
strmov(query, "START SLAVE");

if (mysql_query_with_error_report(mysql_con, 0, query))
{
fprintf(stderr, "%s: Error: Unable to start slave '%s'\n",
my_progname_short, multi_source ? row[0] : "");
error= 1;
}
}
fprintf(stderr, "%s: Error: Unable to start slave '%.*s'\n",
my_progname_short, NAME_CHAR_LEN, stopped_replica);
error= 1;
}
}
mysql_free_result(slave);
DBUG_RETURN(error);
}

Expand Down
1 change: 0 additions & 1 deletion mysql-test/main/mysqldump.result
Original file line number Diff line number Diff line change
Expand Up @@ -5497,7 +5497,6 @@ proc
one
DROP DATABASE bug25717383;
mariadb-dump: Got error: 2005: "Unknown MySQL server host 'unknownhost'" when trying to connect
mariadb-dump: Couldn't execute 'SHOW SLAVE STATUS': MySQL server has gone away (2006)
Usage: mariadb-dump [OPTIONS] database [tables]
OR mariadb-dump [OPTIONS] --databases DB1 [DB2 DB3...]
OR mariadb-dump [OPTIONS] --all-databases
Expand Down

0 comments on commit fbffda8

Please sign in to comment.