#At file:///home/lsoares/Workspace/bzr/work/bugfixing/46110/mysql-next-mr-bugfixing/ based on revid:marc.alff@stripped
3309 Luis Soares 2010-09-30
BUG#46110: --replicate-wild-do-table invalidates
--replicate-do-db matching rule
When using --replicate-do-db and --replicate-ignore-db with
--replicate-wild-do-table, some database level statements, eg
DROP DATABASE or CREATE DATABASE, might not be replayed even if
the DATABASE name was inline with the rules set in
--replicate-do-db and/or --replicate-ignore-db. The following
example would not replicate correctly:
SLAVE, configured with:
--replicate-do-db=dbx --replicate-wild-do-table=db%.t1
MASTER, dba issues:
MASTER> CREATE DATABASE dbx;
Although, at first sight, there is nothing in the filter rules
that might prevent this statement to be replayed, the slave would
not execute it. In fact, "replicate-wild-do-table=db%.t1"
invalidates the "OK" from "replicate-do-db=dbx", making the event
to be skipped/filtered out.
We fix this, by making --replicate-do/ignore-db rules take
precedence over replicate-wild-do-table for *database* level
statements only:
- CREATE/DROP/ALTER DATABASE ...
As such, when replicating such statements, we only look into
replicate-wild-do-table if and only if replicate-do/ignore-db
rules are void. Otherwise, --replicate-do/ignore-db rules
dictate the fate of the statement: either filtered out or
executed.
added:
mysql-test/suite/rpl/r/rpl_filter_database.result
mysql-test/suite/rpl/t/rpl_filter_database-slave.opt
mysql-test/suite/rpl/t/rpl_filter_database.test
modified:
sql/sql_parse.cc
=== added file 'mysql-test/suite/rpl/r/rpl_filter_database.result'
--- a/mysql-test/suite/rpl/r/rpl_filter_database.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_filter_database.result 2010-09-30 07:47:11 +0000
@@ -0,0 +1,6 @@
+stop slave;
+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;
+start slave;
=== added file 'mysql-test/suite/rpl/t/rpl_filter_database-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_filter_database-slave.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_filter_database-slave.opt 2010-09-30 07:47:11 +0000
@@ -0,0 +1 @@
+--replicate-do-db=dbx --replicate-wild-do-table=db%.t1
=== added file 'mysql-test/suite/rpl/t/rpl_filter_database.test'
--- a/mysql-test/suite/rpl/t/rpl_filter_database.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_filter_database.test 2010-09-30 07:47:11 +0000
@@ -0,0 +1,100 @@
+#
+# BUG#46110: --replicate-wild-do-table invalidates
+# --replicate-do-db matching rule
+#
+# In this test we check the following three database level
+# statements, which should be replicated with the given
+# set of filtering rules at the slave:
+# --replicate-do-db=dbx --replicate-wild-do-table=db%.t1
+#
+# Before this bug was fixed, replicate-wild-do-table would
+# invalidate such database level statements.
+#
+# The following assertions work like this:
+# 1. CREATE DATABASE
+# - Issue create database on master
+# - check if the database is listed on slave's I_S.schemata
+# 2. ALTER DATABASE
+# - Issue alter database (changing default charset) on
+# master
+# - check (using I_S.schemata) that default charset is
+# changed as well for the slave's database
+# 3. DROP DATABASE
+# - Issue drop database on master.
+# - check that the slave will also drop its own database.
+#
+# If any of the assertions doesn't hold we abort the test and
+# dump debug information.
+
+-- source include/master-slave.inc
+
+## Checking CREATE DATABASE
+
+-- disable_query_log
+CREATE DATABASE dbx DEFAULT CHARACTER SET=latin1;
+-- enable_query_log
+
+if (!`SELECT count(*) = 1 FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Database 'dbx' not listed on information_schema.SCHEMATA.
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+-- sync_slave_with_master
+
+if (!`SELECT count(*) = 1 FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Database 'dbx' not listed on information_schema.SCHEMATA.
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+## Checking ALTER DATABASE
+
+-- connection master
+
+-- disable_query_log
+ALTER DATABASE dbx DEFAULT CHARACTER SET=latin5;
+-- enable_query_log
+
+if (!`SELECT DEFAULT_CHARACTER_SET_NAME='latin5' FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Unexpected default character set for table 'dbx'
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+-- sync_slave_with_master
+
+if (!`SELECT DEFAULT_CHARACTER_SET_NAME='latin5' FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Unexpected default character set for table 'dbx'
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+## Checking DROP DATABASE
+
+-- connection master
+-- disable_query_log
+DROP DATABASE dbx;
+-- enable_query_log
+
+if (!`SELECT count(*) = 0 FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Database 'dbx' is still listed on information_schema.SCHEMATA.
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+-- sync_slave_with_master
+
+if (!`SELECT count(*) = 0 FROM information_schema.SCHEMATA WHERE schema_name = 'dbx'`)
+{
+ -- echo $CONNECTION_NAME : Database 'dbx' is still listed on information_schema.SCHEMATA.
+ -- source include/show_rpl_debug_info.inc
+ -- die
+}
+
+-- source include/master-slave-end.inc
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-09-01 22:59:33 +0000
+++ b/sql/sql_parse.cc 2010-09-30 07:47:11 +0000
@@ -170,6 +170,42 @@ inline bool all_tables_not_ok(THD *thd,
return rpl_filter->is_on() && tables && !thd->spcont &&
!rpl_filter->tables_ok(thd->db, tables);
}
+
+/**
+ Checks whether the event for the given database, db, should
+ be ignored or not. This is done by checking whether there are
+ active rules in ignore_db or in do_db containers. If there
+ are, then check if there is a match, if not then check the
+ wild_do rules.
+
+ NOTE: This means that when using this function replicate-do-db
+ and replicate-ignore-db take precedence over wild do
+ rules.
+
+ @param thd Thread handle.
+ @param db Database name used while evaluating the filtering
+ rules.
+
+*/
+inline bool db_stmt_db_ok(THD *thd, char* db)
+{
+ DBUG_ENTER("db_stmt_db_ok");
+
+ if (!thd->slave_thread)
+ DBUG_RETURN(TRUE);
+
+ /*
+ No filters exist in ignore/do_db ? Then, just check
+ wild_do_table filtering. Otherwise, check the do_db
+ rules.
+ */
+ bool db_ok= (rpl_filter->get_do_db()->is_empty() &&
+ rpl_filter->get_ignore_db()->is_empty()) ?
+ rpl_filter->db_ok_with_wild_table(db) :
+ rpl_filter->db_ok(db);
+
+ DBUG_RETURN(db_ok);
+}
#endif
@@ -3284,9 +3320,7 @@ end_with_restore_list:
above was not called. So we have to check rules again here.
*/
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
- (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str)))
+ if (!db_stmt_db_ok(thd, lex->name.str))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
@@ -3313,9 +3347,7 @@ end_with_restore_list:
above was not called. So we have to check rules again here.
*/
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
- (!rpl_filter->db_ok(lex->name.str) ||
- !rpl_filter->db_ok_with_wild_table(lex->name.str)))
+ if (!db_stmt_db_ok(thd, lex->name.str))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
@@ -3330,9 +3362,7 @@ end_with_restore_list:
{
LEX_STRING *db= & lex->name;
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
- (!rpl_filter->db_ok(db->str) ||
- !rpl_filter->db_ok_with_wild_table(db->str)))
+ if (!db_stmt_db_ok(thd, lex->name.str))
{
res= 1;
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
@@ -3373,9 +3403,7 @@ end_with_restore_list:
above was not called. So we have to check rules again here.
*/
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
- (!rpl_filter->db_ok(db->str) ||
- !rpl_filter->db_ok_with_wild_table(db->str)))
+ if (!db_stmt_db_ok(thd, lex->name.str))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
Attachment: [text/bzr-bundle] bzr/luis.soares@oracle.com-20100930074711-fhb5eo6w7uudb8t8.bundle
| Thread |
|---|
| • bzr commit into mysql-next-mr-bugfixing branch (luis.soares:3309) Bug#46110 | Luis Soares | 30 Sep |