Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions mysql-test/main/variables-notembedded.result
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---- Init ----
set @my_slave_net_timeout =@@global.slave_net_timeout;
set @my_slave_skip_errors =@@global.slave_skip_errors;
---- Test ----
set global slave_net_timeout=100;
set global sql_slave_skip_counter=100;
Expand Down Expand Up @@ -144,9 +145,13 @@ SELECT @@global.slave_skip_errors;
@@global.slave_skip_errors
0,3,100,137,643,1752
SET @@session.slave_skip_errors= 7;
ERROR HY000: Variable 'slave_skip_errors' is a read only variable
SET @@global.slave_skip_errors= 7;
ERROR HY000: Variable 'slave_skip_errors' is a read only variable
ERROR HY000: Variable 'slave_skip_errors' is a GLOBAL variable and should be set with SET GLOBAL
SET @@global.slave_skip_errors= "7";
SELECT @@global.slave_skip_errors;
@@global.slave_skip_errors
7
SET @@global.slave_skip_errors= "OFF";
set GLOBAL slave_skip_errors = @my_slave_skip_errors;
#
# Bug #11766769 : 59959: SMALL VALUES OF --MAX-ALLOWED-PACKET
# ARE NOT BEING HONORED
Expand Down
9 changes: 6 additions & 3 deletions mysql-test/main/variables-notembedded.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ source include/not_embedded.inc;
--echo ---- Init ----
# Backup global variables so they can be restored at end of test.
set @my_slave_net_timeout =@@global.slave_net_timeout;
set @my_slave_skip_errors =@@global.slave_skip_errors;

--echo ---- Test ----
set global slave_net_timeout=100;
Expand Down Expand Up @@ -145,10 +146,12 @@ SHOW VARIABLES like 'slave_skip_errors';
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@session.slave_skip_errors;
SELECT @@global.slave_skip_errors;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
--error ER_GLOBAL_VARIABLE
SET @@session.slave_skip_errors= 7;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@global.slave_skip_errors= 7;
SET @@global.slave_skip_errors= "7";
SELECT @@global.slave_skip_errors;
SET @@global.slave_skip_errors= "OFF";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this testing an additional path? Or just a reset?

If its just a reset, omit.

Either way, put the last line set GLOBAL slave_skip_errors = @my_slave_skip_errors; here as its relevant to this test.

Could put the first set @my_slave_skip_errors =@@global.slave_skip_errors; just prior to this test block.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it's not reset , I am saving the initial values in the beginning of the test , and resting in the end, but I will move those this block of test as you suggested

set GLOBAL slave_skip_errors = @my_slave_skip_errors;
#

--echo #
Expand Down
62 changes: 62 additions & 0 deletions mysql-test/suite/rpl/r/slave_skip_errors_writable.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# MDEV-7394 test dynamic slave_skip_errors (writable when slaves stopped)
include/master-slave.inc
[connection master]
connection slave;
STOP SLAVE;
SET GLOBAL slave_skip_errors = "1062";
START SLAVE;
SELECT @@global.slave_skip_errors;
@@global.slave_skip_errors
1062
connection master;
CREATE TABLE t1 (id INT PRIMARY KEY);
include/sync_slave_sql_with_master.inc
connection slave;
INSERT INTO t1 VALUES (2);
connection master;
INSERT INTO t1 VALUES (2);
include/sync_slave_sql_with_master.inc
connection slave;
include/check_slave_is_running.inc
START SLAVE;
Warnings:
Note 1254 Slave is already running
include/wait_for_slave_to_start.inc
SET GLOBAL slave_skip_errors = "1062";
ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first
STOP SLAVE;
SET GLOBAL slave_skip_errors = "1050,1004,1104,1146";
START SLAVE;
# erros should be showed in sorted order
SELECT @@global.slave_skip_errors;
@@global.slave_skip_errors
1004,1050,1104,1146
SET GLOBAL slave_ddl_exec_mode = STRICT;
# test that mulitiple errors are set correctly
connection slave;
include/stop_slave.inc
CREATE TABLE t2 (id INT);
include/start_slave.inc
connection master;
CREATE TABLE t2 (id INT);
INSERT INTO t1 VALUES (4);
connection slave;
connection slave;
include/check_slave_is_running.inc
connection master;
INSERT INTO t1 VALUES (3);
include/sync_slave_sql_with_master.inc
connection slave;
SELECT COUNT(*) FROM t1 WHERE id=3;
COUNT(*)
1
STOP SLAVE;
SET GLOBAL slave_skip_errors = "OFF";
START SLAVE;
connection master;
DROP TABLE t1;
DROP TABLE t2;
include/sync_slave_sql_with_master.inc
connection slave;
SET GLOBAL slave_ddl_exec_mode = DEFAULT;
include/rpl_end.inc
69 changes: 69 additions & 0 deletions mysql-test/suite/rpl/t/slave_skip_errors_writable.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
--echo # MDEV-7394 test dynamic slave_skip_errors (writable when slaves stopped)

--source include/master-slave.inc
connection slave;
STOP SLAVE;
SET GLOBAL slave_skip_errors = "1062";
START SLAVE;
SELECT @@global.slave_skip_errors;

connection master;
CREATE TABLE t1 (id INT PRIMARY KEY);
--source include/sync_slave_sql_with_master.inc

connection slave;
INSERT INTO t1 VALUES (2);

connection master;
INSERT INTO t1 VALUES (2);
--source include/sync_slave_sql_with_master.inc

connection slave;
source include/check_slave_is_running.inc;
START SLAVE;
--source include/wait_for_slave_to_start.inc
--error ER_SLAVE_MUST_STOP
SET GLOBAL slave_skip_errors = "1062";

STOP SLAVE;
SET GLOBAL slave_skip_errors = "1050,1004,1104,1146";
START SLAVE;

--echo # erros should be showed in sorted order
SELECT @@global.slave_skip_errors;

SET GLOBAL slave_ddl_exec_mode = STRICT;
--echo # test that mulitiple errors are set correctly

connection slave;
--source include/stop_slave.inc
CREATE TABLE t2 (id INT);
--source include/start_slave.inc

connection master;
CREATE TABLE t2 (id INT);
INSERT INTO t1 VALUES (4);
sync_slave_with_master;

connection slave;
source include/check_slave_is_running.inc;

connection master;
INSERT INTO t1 VALUES (3);
--source include/sync_slave_sql_with_master.inc

connection slave;
SELECT COUNT(*) FROM t1 WHERE id=3;

STOP SLAVE;
SET GLOBAL slave_skip_errors = "OFF";
START SLAVE;

connection master;
DROP TABLE t1;
DROP TABLE t2;
--source include/sync_slave_sql_with_master.inc
connection slave;
SET GLOBAL slave_ddl_exec_mode = DEFAULT;

--source include/rpl_end.inc
4 changes: 0 additions & 4 deletions mysql-test/suite/sys_vars/r/slave_skip_errors_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,3 @@ SLAVE_SKIP_ERRORS OFF
select * from information_schema.session_variables where variable_name='slave_skip_errors';
VARIABLE_NAME VARIABLE_VALUE
SLAVE_SKIP_ERRORS OFF
set global slave_skip_errors=1;
ERROR HY000: Variable 'slave_skip_errors' is a read only variable
set session slave_skip_errors=1;
ERROR HY000: Variable 'slave_skip_errors' is a read only variable
Original file line number Diff line number Diff line change
Expand Up @@ -4350,7 +4350,7 @@ NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY YES
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SLAVE_SQL_VERIFY_CHECKSUM
VARIABLE_SCOPE GLOBAL
Expand Down
7 changes: 0 additions & 7 deletions mysql-test/suite/sys_vars/t/slave_skip_errors_basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,3 @@ show session variables like 'slave_skip_errors';
select * from information_schema.global_variables where variable_name='slave_skip_errors';
select * from information_schema.session_variables where variable_name='slave_skip_errors';

#
# show that it's read-only
#
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set global slave_skip_errors=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set session slave_skip_errors=1;
55 changes: 35 additions & 20 deletions sql/slave.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ static bool wait_for_relay_log_space(Relay_log_info* rli);
static bool io_slave_killed(Master_info* mi);
static bool sql_slave_killed(rpl_group_info *rgi);
static int init_slave_thread(THD*, Master_info *, SLAVE_THD_TYPE);
static void make_slave_skip_errors_printable(void);
static void make_slave_transaction_retry_errors_printable(void);
static int safe_connect(THD* thd, MYSQL* mysql, Master_info* mi);
static int safe_reconnect(THD*, MYSQL*, Master_info*, bool);
Expand Down Expand Up @@ -809,7 +808,7 @@ int init_recovery(Master_info* mi, const char** errmsg)
Convert slave skip errors bitmap into a printable string.
*/

static void make_slave_skip_errors_printable(void)
void make_slave_skip_errors_printable(void)
{
/*
To be safe, we want 10 characters of room in the buffer for a number
Expand All @@ -829,12 +828,14 @@ static void make_slave_skip_errors_printable(void)
{
/* purecov: begin tested */
memcpy(slave_skip_error_names, STRING_WITH_LEN("OFF"));
slave_skip_error_names[3]= '\0';
/* purecov: end */
}
else if (bitmap_is_set_all(&slave_error_mask))
{
/* purecov: begin tested */
memcpy(slave_skip_error_names, STRING_WITH_LEN("ALL"));
slave_skip_error_names[3]= '\0';
/* purecov: end */
}
else
Expand Down Expand Up @@ -866,33 +867,28 @@ static void make_slave_skip_errors_printable(void)
DBUG_VOID_RETURN;
}

/*
Init function to set up array for errors that should be skipped for slave

SYNOPSIS
init_slave_skip_errors()
arg List of errors numbers to skip, separated with ','

NOTES
Called from get_options() in mysqld.cc on start-up
*/

bool init_slave_skip_errors(const char* arg)
bool init_slave_skip_errors_bitmap(const char* arg)
{
const char *p;
DBUG_ENTER("init_slave_skip_errors");

if (!arg || !*arg) // No errors defined
goto end;

if (my_bitmap_init(&slave_error_mask,0,MAX_SLAVE_ERROR))
Comment thread
Mahmoud-kh1 marked this conversation as resolved.
DBUG_RETURN(1);

if (!use_slave_mask)
{
if (my_bitmap_init(&slave_error_mask,0,MAX_SLAVE_ERROR))
DBUG_RETURN(1);
}
else
{
bitmap_clear_all(&slave_error_mask);
}

use_slave_mask= 1;
for (;my_isspace(system_charset_info,*arg);++arg)
/* empty */;
if (!system_charset_info->strnncoll((uchar*)arg,4,(const uchar*)"all",4))
{
if (strlen(arg) == 3 && !system_charset_info->strnncoll((uchar*)arg,3,(const uchar*)"all",3)) {
bitmap_set_all(&slave_error_mask);
bitmap_clear_bit(&slave_error_mask,ER_CONNECTION_KILLED);
sql_print_warning("Slave: ER_CONNECTION_KILLED (%d) is not allowed in "
Expand Down Expand Up @@ -923,10 +919,29 @@ bool init_slave_skip_errors(const char* arg)
}

end:
make_slave_skip_errors_printable();
DBUG_RETURN(0);
}
/*
Init function to set up array for errors that should be skipped for slave

SYNOPSIS
init_slave_skip_errors()
arg List of errors numbers to skip, separated with ','

NOTES
Called from get_options() in mysqld.cc on start-up
*/
bool init_slave_skip_errors(const char* arg)
{
DBUG_ENTER("init_slave_skip_errors");
if (init_slave_skip_errors_bitmap(arg))
{
DBUG_RETURN(1);
}
make_slave_skip_errors_printable();
DBUG_RETURN(0);

}
/**
Make printable version if slave_transaction_retry_errors
This is never empty as at least ER_LOCK_DEADLOCK and ER_LOCK_WAIT_TIMEOUT
Expand Down
4 changes: 4 additions & 0 deletions sql/slave.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ extern const char *relay_log_basename;
int init_slave();
int init_recovery(Master_info* mi, const char** errmsg);
bool init_slave_skip_errors(const char* arg);
bool init_slave_skip_errors_bitmap(const char* arg);
void make_slave_skip_errors_printable(void);
bool check_slave_skip_errors(sys_var *self, THD *thd, set_var *var);
bool update_slave_skip_errors(sys_var *self, THD *thd, enum_var_type type);
bool init_slave_transaction_retry_errors(const char* arg);
int register_slave_on_master(MYSQL* mysql);
int terminate_slave_threads(Master_info* mi, int thread_mask,
Expand Down
49 changes: 47 additions & 2 deletions sql/sys_vars.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6212,12 +6212,57 @@ static Sys_var_multi_source_ulonglong Sys_max_relay_log_size(
VALID_RANGE(0, 1024L*1024*1024), DEFAULT(0), BLOCK_SIZE(IO_SIZE),
ON_UPDATE(update_max_relay_log_size));

bool check_slave_skip_errors(sys_var *self, THD *thd, set_var *var)
{
return give_error_if_slave_running(0);
}

bool update_slave_skip_errors(sys_var *self, THD *thd, enum_var_type type)
{
bool err= false;
mysql_mutex_unlock(&LOCK_global_system_variables);
mysql_mutex_lock(&LOCK_active_mi);

if (give_error_if_slave_running(1))
{
my_error(ER_SLAVE_MUST_STOP, MYF(0));
err= true;
}
if (!err)
{
if (init_slave_skip_errors_bitmap(opt_slave_skip_errors))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
err= true;
}
else
{
/*
* global_update() already ran my_memdup() on the user's string and stored
* the heap pointer in opt_slave_skip_errors with ALLOCATED set.
* We must call self->cleanup() after building the bitmap to free that
* heap allocation before make_slave_skip_errors_printable() overwrites
* opt_slave_skip_errors with the static slave_skip_error_names[] buffer.
* Without this, the heap pointer is lost (leak) and ALLOCATED stays set,
* causing a crash when cleanup() later tries to free the static buffer.
*/
self->cleanup();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment explaining why we need to manually call self->cleanup()

make_slave_skip_errors_printable();
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of the lines in this file have whitespace at the end. Please look at your changes with git show to see this, and remove lines with such whitespace.


mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_global_system_variables);
return err;
}
static Sys_var_charptr Sys_slave_skip_errors(
"slave_skip_errors", "Tells the slave thread to continue "
"replication when a query event returns an error from the "
"provided list",
READ_ONLY GLOBAL_VAR(opt_slave_skip_errors), CMD_LINE(REQUIRED_ARG),
DEFAULT(0));
GLOBAL_VAR(opt_slave_skip_errors), CMD_LINE(REQUIRED_ARG),
DEFAULT(NULL), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_slave_skip_errors),
ON_UPDATE(update_slave_skip_errors));

static Sys_var_on_access_global<Sys_var_ulonglong,
PRIV_SET_SYSTEM_GLOBAL_VAR_READ_BINLOG_SPEED_LIMIT>
Expand Down
Loading