Skip to content

Commit b793517

Browse files
author
Neha Kumari
committed
Bug #24753281: REQUEST FOR SLAVE_SKIP_ERRORS = ER_INCONSISTENT_ERROR
Problem: -------- Replication applier thread returns 3002, ER_INCONSISTENT_ERROR, when there's difference between expected error number and actual error number on slave. So when ER_INCONSISTENT_ERROR is passed as an input to slave-skip-errors, the replication should continue despite having different expected error and actual error on slave. But in current code, the slave is not able to ignore ER_INCONSISTENT_ERROR. Fix: ---- Check if ER_INCONSISTENT_ERROR is passed in the list of errors to be skipped. If yes then do not throw error, just log this info with the mention of actual and expected error as a note in the slave's error log.
1 parent 061d482 commit b793517

File tree

4 files changed

+127
-7
lines changed

4 files changed

+127
-7
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
include/master-slave.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection master]
6+
call mtr.add_suppression("Query caused different errors on master and slave."
7+
" Error on master:");
8+
CREATE TABLE t1(s INT, UNIQUE(s)) ENGINE=MyISAM;
9+
SET SESSION sql_log_bin= 0;
10+
INSERT INTO t1 VALUES(10);
11+
SET SESSION sql_log_bin= 1;
12+
INSERT INTO t1 VALUES (5),(10);
13+
ERROR 23000: Duplicate entry '10' for key 's'
14+
DROP TABLE t1;
15+
CREATE TABLE t2(s INT);
16+
INSERT INTO t2 VALUES(10);
17+
include/sync_slave_sql_with_master.inc
18+
include/diff_tables.inc [master:t2,slave:t2]
19+
[connection master]
20+
DROP TABLE t2;
21+
include/sync_slave_sql_with_master.inc
22+
include/stop_slave.inc
23+
RESET SLAVE;
24+
include/assert_grep.inc [Found the expected information about the ER_INCONSISTENT_ERROR being skipped.]
25+
include/rpl_end.inc
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--slave-skip-errors=3002
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#
2+
# === Purpose ===
3+
# This test script verifies that in a replication environment,
4+
# when we have different errors on master and slave side, and if
5+
# we have ER_INCONSISTENT_ERROR specified in the slave_skip_errors
6+
# list the replication should not stop with error ER_INCONSISTENT_ERROR.
7+
#
8+
# === Implementation ===
9+
#1. Create a table using MyISAM storage engine.
10+
#
11+
#2. Insert a row with binary logging off, this is done to be able to
12+
# generate error in the next query while trying to store a duplicate
13+
# value in a column which accepts only unique value.
14+
#
15+
#3. As the bin logging was off for the first transaction the slave will only
16+
# apply the second insert statement (the one which caused error on master).
17+
# And should have thrown 'ER_INCONSISTENT_ERROR' error as the expected
18+
# error(ER_DUP_ENTRY) is different from the actual error(No error).
19+
#
20+
#4. Now as we have passed ER_INCONSISTENT_ERROR to --slave-skip-errors in the
21+
# .opt file the slave will not throw any error and the replication should
22+
# continue.
23+
#
24+
#5. Test if replication is working fine by taking diff of tables on master
25+
# and slave.
26+
# === Related bugs and worklogs ===
27+
#
28+
# Bug#24753281: REQUEST FOR SLAVE_SKIP_ERRORS = ER_INCONSISTENT_ERROR
29+
30+
--source include/have_binlog_format_statement.inc
31+
--source include/not_mts_slave_parallel_workers.inc
32+
--source include/have_myisam.inc
33+
--source include/master-slave.inc
34+
35+
call mtr.add_suppression("Query caused different errors on master and slave."
36+
" Error on master:");
37+
# We have to use only MyISAM storage engine and not InnDB here, because using
38+
# MyISAM will ensure that the second insert statement is written to binary log
39+
# with the error, whereas using InnoDB the insert will just throw
40+
# error(ER_DUP_ENTRY) and it won't be written to binary log.
41+
CREATE TABLE t1(s INT, UNIQUE(s)) ENGINE=MyISAM;
42+
43+
SET SESSION sql_log_bin= 0;
44+
INSERT INTO t1 VALUES(10);
45+
SET SESSION sql_log_bin= 1;
46+
47+
# We are inserting duplicate value for a column which only accepts unique value.
48+
# On MyISAM we will log this statement along with the error it is throwing.
49+
--error ER_DUP_ENTRY
50+
INSERT INTO t1 VALUES (5),(10);
51+
DROP TABLE t1;
52+
53+
CREATE TABLE t2(s INT);
54+
INSERT INTO t2 VALUES(10);
55+
56+
--source include/sync_slave_sql_with_master.inc
57+
58+
# Show that replication is working fine.
59+
--let $diff_tables=master:t2,slave:t2
60+
--source include/diff_tables.inc
61+
62+
--source include/rpl_connection_master.inc
63+
DROP TABLE t2;
64+
65+
--source include/sync_slave_sql_with_master.inc
66+
--source include/stop_slave.inc
67+
RESET SLAVE;
68+
--let $rpl_only_running_threads= 1
69+
70+
--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err
71+
--let $assert_only_after= CURRENT_TEST: rpl.rpl_inconsistent_error
72+
--let $assert_count= 1
73+
--let $assert_select= actual error and expected error on slave are different .* The expected error was .* 1062. The actual error .*
74+
75+
--let $assert_text= Found the expected information about the ER_INCONSISTENT_ERROR being skipped.
76+
--source include/assert_grep.inc
77+
--source include/rpl_end.inc

sql/log_event.cc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4719,13 +4719,30 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
47194719
!ignored_error_code(actual_error) &&
47204720
!ignored_error_code(expected_error))
47214721
{
4722-
rli->report(ERROR_LEVEL, ER_INCONSISTENT_ERROR, ER(ER_INCONSISTENT_ERROR),
4723-
ER_THD(thd, expected_error), expected_error,
4724-
(actual_error ?
4725-
thd->get_stmt_da()->message_text() :
4726-
"no error"),
4727-
actual_error, print_slave_db_safe(db), query_arg);
4728-
thd->is_slave_error= 1;
4722+
if (!ignored_error_code(ER_INCONSISTENT_ERROR))
4723+
{
4724+
rli->report(ERROR_LEVEL, ER_INCONSISTENT_ERROR,
4725+
ER(ER_INCONSISTENT_ERROR),
4726+
ER_THD(thd, expected_error), expected_error,
4727+
(actual_error ?
4728+
thd->get_stmt_da()->message_text() :
4729+
"no error"),
4730+
actual_error, print_slave_db_safe(db), query_arg);
4731+
thd->is_slave_error= 1;
4732+
}
4733+
else
4734+
{
4735+
rli->report(INFORMATION_LEVEL, actual_error,
4736+
"The actual error and expected error on slave are"
4737+
" different that will result in ER_INCONSISTENT_ERROR but"
4738+
" that is passed as an argument to slave_skip_errors so no"
4739+
" error is thrown. "
4740+
"The expected error was %s with, Error_code: %d. "
4741+
"The actual error is %s with ",
4742+
ER(expected_error), expected_error,
4743+
thd->get_stmt_da()->message_text());
4744+
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
4745+
}
47294746
}
47304747
/*
47314748
If we get the same error code as expected and it is not a concurrency

0 commit comments

Comments
 (0)