mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Fix for BUG#3461 "multi-table DELETE replicated despite replicate-wild-ignore-table":
In tables_ok(), when there is no table having "updating==TRUE" in the list, return that we don't replicate this statement (the slave is supposed to replicate *changes* only). In practice, the case can only happen for this statement: DELETE t FROM t,u WHERE ... ; tables_ok(t,u) will now return 0, which (check all_tables_not_ok()) will give a chance to tables_ok(t) to run. sql/slave.cc: In tables_ok(), when there is no table having "updating==TRUE" in the list, return that we don't replicate this statement (the slave is supposed to replicate *changes* only). In practice, the case can only happen for this statement: DELETE t FROM t,u WHERE ... ; tables_ok(t,u) will now return 0, which (check all_tables_not_ok()) will give a chance to tables_ok(t) to run.
This commit is contained in:
21
mysql-test/r/rpl_multi_delete2.result
Normal file
21
mysql-test/r/rpl_multi_delete2.result
Normal file
@@ -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;
|
1
mysql-test/t/rpl_multi_delete2-slave.opt
Normal file
1
mysql-test/t/rpl_multi_delete2-slave.opt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
--replicate-wild-ignore-table=test.%
|
23
mysql-test/t/rpl_multi_delete2.test
Normal file
23
mysql-test/t/rpl_multi_delete2.test
Normal file
@@ -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;
|
18
sql/slave.cc
18
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
|
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
|
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 (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
|
RETURN VALUES
|
||||||
0 should not be logged/replicated
|
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)
|
int tables_ok(THD* thd, TABLE_LIST* tables)
|
||||||
{
|
{
|
||||||
|
bool some_tables_updating= 0;
|
||||||
DBUG_ENTER("tables_ok");
|
DBUG_ENTER("tables_ok");
|
||||||
|
|
||||||
for (; tables; tables = tables->next)
|
for (; tables; tables = tables->next)
|
||||||
@@ -718,6 +728,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
|
|||||||
|
|
||||||
if (!tables->updating)
|
if (!tables->updating)
|
||||||
continue;
|
continue;
|
||||||
|
some_tables_updating= 1;
|
||||||
end= strmov(hash_key, tables->db ? tables->db : thd->db);
|
end= strmov(hash_key, tables->db ? tables->db : thd->db);
|
||||||
*end++= '.';
|
*end++= '.';
|
||||||
len= (uint) (strmov(end, tables->real_name) - hash_key);
|
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 no explicit rule found and there was a do list, do not replicate.
|
||||||
If there was no do list, go ahead
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user