summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/rpl_multi_delete2.result21
-rw-r--r--mysql-test/t/rpl_multi_delete2-slave.opt1
-rw-r--r--mysql-test/t/rpl_multi_delete2.test23
-rw-r--r--sql/slave.cc18
4 files changed, 61 insertions, 2 deletions
diff --git a/mysql-test/r/rpl_multi_delete2.result b/mysql-test/r/rpl_multi_delete2.result
new file mode 100644
index 00000000000..8b6d87801fe
--- /dev/null
+++ b/mysql-test/r/rpl_multi_delete2.result
@@ -0,0 +1,21 @@
+slave stop;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+create table t1 (a int);
+create table t2 (a int);
+insert into t1 values (1);
+insert into t2 values (1);
+delete t1.* from t1, t2 where t1.a = t2.a;
+select * from t1;
+a
+select * from t2;
+a
+1
+select * from t1;
+Table 'test.t1' doesn't exist
+select * from t2;
+Table 'test.t2' doesn't exist
+drop table t1,t2;
diff --git a/mysql-test/t/rpl_multi_delete2-slave.opt b/mysql-test/t/rpl_multi_delete2-slave.opt
new file mode 100644
index 00000000000..b828d03fafb
--- /dev/null
+++ b/mysql-test/t/rpl_multi_delete2-slave.opt
@@ -0,0 +1 @@
+--replicate-wild-ignore-table=test.%
diff --git a/mysql-test/t/rpl_multi_delete2.test b/mysql-test/t/rpl_multi_delete2.test
new file mode 100644
index 00000000000..c5128833843
--- /dev/null
+++ b/mysql-test/t/rpl_multi_delete2.test
@@ -0,0 +1,23 @@
+source include/master-slave.inc;
+create table t1 (a int);
+create table t2 (a int);
+
+insert into t1 values (1);
+insert into t2 values (1);
+
+delete t1.* from t1, t2 where t1.a = t2.a;
+
+save_master_pos;
+select * from t1;
+select * from t2;
+
+connection slave;
+# BUG#3461 would cause sync to fail
+sync_with_master;
+error 1146;
+select * from t1;
+error 1146;
+select * from t2;
+
+connection master;
+drop table t1,t2;
diff --git a/sql/slave.cc b/sql/slave.cc
index e79e70e0395..0476fb83abe 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -699,7 +699,16 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
Note that changing the order of the tables in the list can lead to
different results. Note also the order of precedence of the do/ignore
rules (see code below). For that reason, users should not set conflicting
- rules because they may get unpredicted results.
+ rules because they may get unpredicted results (precedence order is
+ explained in the manual).
+ If no table of the list is marked "updating" (so far this can only happen
+ if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
+ is the tables in the FROM): then we always return 0, because there is no
+ reason we play this statement on this slave if it updates nothing. In the
+ case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
+ with tables having "updating==TRUE" (those after the DELETE), so this
+ second call will make the decision (because
+ all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
RETURN VALUES
0 should not be logged/replicated
@@ -708,6 +717,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
int tables_ok(THD* thd, TABLE_LIST* tables)
{
+ bool some_tables_updating= 0;
DBUG_ENTER("tables_ok");
for (; tables; tables = tables->next)
@@ -718,6 +728,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
if (!tables->updating)
continue;
+ some_tables_updating= 1;
end= strmov(hash_key, tables->db ? tables->db : thd->db);
*end++= '.';
len= (uint) (strmov(end, tables->real_name) - hash_key);
@@ -740,10 +751,13 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
}
/*
+ If no table was to be updated, ignore statement (no reason we play it on
+ slave, slave is supposed to replicate _changes_ only).
If no explicit rule found and there was a do list, do not replicate.
If there was no do list, go ahead
*/
- DBUG_RETURN(!do_table_inited && !wild_do_table_inited);
+ DBUG_RETURN(some_tables_updating &&
+ !do_table_inited && !wild_do_table_inited);
}