MDEV-7611 mysqldump --dump-slave always starts stopped slave

Store the _SLAVE_ STATUS when pausing replicas for
`mariadb-dump --dump-slave`; 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 [IO & SQL for all multi-source connections] 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>
Reviewed-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
This commit is contained in:
ParadoxV5 2025-07-08 21:31:51 -06:00
commit b6385e00b6
4 changed files with 23 additions and 22 deletions

View file

@ -184,7 +184,7 @@ static DYNAMIC_STRING extended_row;
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 MYSQL_RES *routine_res, *routine_list_res, *slave_status_res= NULL;
#include <sslopt-vars.h>
@ -1908,6 +1908,8 @@ static void free_resources()
mysql_free_result(routine_res);
if (routine_list_res)
mysql_free_result(routine_list_res);
if (slave_status_res)
mysql_free_result(slave_status_res);
if (mysql)
{
mysql_close(mysql);
@ -6257,17 +6259,19 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
static int do_stop_slave_sql(MYSQL *mysql_con)
{
MYSQL_RES *slave;
MYSQL_ROW row;
DBUG_ASSERT(
!slave_status_res // do_stop_slave_sql() should only be called once
);
if (mysql_query_with_error_report(mysql_con, &slave,
if (mysql_query_with_error_report(mysql_con, &slave_status_res,
multi_source ?
"SHOW ALL SLAVES STATUS" :
"SHOW SLAVE STATUS"))
return(1);
/* Loop over all slaves */
while ((row= mysql_fetch_row(slave)))
while ((row= mysql_fetch_row(slave_status_res)))
{
if (row[11 + multi_source])
{
@ -6282,13 +6286,11 @@ static int do_stop_slave_sql(MYSQL *mysql_con)
if (mysql_query_with_error_report(mysql_con, 0, query))
{
mysql_free_result(slave);
return 1;
}
}
}
}
mysql_free_result(slave);
return(0);
}
@ -6412,32 +6414,35 @@ 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);
/*
do_start_slave_sql() should normally be called
sometime after do_stop_slave_sql() succeeds
*/
if (!slave_status_res)
DBUG_RETURN(error);
mysql_data_seek(slave_status_res, 0);
while ((row= mysql_fetch_row(slave)))
while ((row= mysql_fetch_row(slave_status_res)))
{
DBUG_PRINT("info", ("Connection: '%s' status: '%s'",
multi_source ? row[0] : "", row[11 + multi_source]));
if (row[11 + multi_source])
{
/* if SLAVE SQL is not running, we don't start it */
if (strcmp(row[11 + multi_source], "Yes"))
/*
If SLAVE_SQL was not running but is now,
we start it anyway to warn the unexpected state change.
*/
if (strcmp(row[11 + multi_source], "No"))
{
char query[160];
if (multi_source)
sprintf(query, "START SLAVE '%.80s'", row[0]);
sprintf(query, "START SLAVE '%.80s' SQL_THREAD", row[0]);
else
strmov(query, "START SLAVE");
strmov(query, "START SLAVE SQL_THREAD");
if (mysql_query_with_error_report(mysql_con, 0, query))
{
@ -6448,7 +6453,6 @@ static int do_start_slave_sql(MYSQL *mysql_con)
}
}
}
mysql_free_result(slave);
DBUG_RETURN(error);
}

View file

@ -5617,7 +5617,6 @@ proc
one
DROP DATABASE bug25717383;
mariadb-dump: Got error: 2005: "Unknown server host 'unknownhost'" when trying to connect
mariadb-dump: Couldn't execute 'SHOW SLAVE STATUS': 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

View file

@ -51,7 +51,6 @@ after initial slave got in sync
include/stop_slave.inc
# 3. A
include/stop_slave.inc
include/stop_slave.inc
# 4.
set statement sql_log_bin=0 for delete from mysql.gtid_slave_pos;
insert into mysql.gtid_slave_pos values (99 + 2, 1, 1, 1);

View file

@ -73,7 +73,6 @@ select @@global.gtid_slave_pos as "after initial slave got in sync";
--echo # 3. A
# Two dumps prepared to be restored in the following loop
--exec $MYSQL_DUMP_SLAVE --dump-slave --gtid mysql gtid_slave_pos > $MYSQLTEST_VARDIR/tmp/dump_2.sql
--source include/stop_slave.inc
--exec $MYSQL_DUMP_SLAVE --master-data --gtid mysql gtid_slave_pos > $MYSQLTEST_VARDIR/tmp/dump_1.sql