List:Commits« Previous MessageNext Message »
From:He Zhenxing Date:August 31 2009 7:37am
Subject:Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3028)
Bug#42829
View as plain text  
Hi Luis,

Patch approved!

Luis Soares wrote:
> #At file:///home/lsoares/Workspace/mysql-server/bugfix/42829/mysql-5.1-bug39934/
> based on revid:luis.soares@stripped
> 
>  3028 Luis Soares	2009-07-23
>       BUG#42829: binlogging enabled for all schemas regardless of
>       binlog-db-db / binlog-ignore-db
>             
>       InnoDB will return an error if statement based replication is
>       used along with transaction isolation level READ-COMMITTED (or
>       weaker), even if the statement in question is filtered out
>       according to the binlog-do-db rules set. In this case, an error
>       should not be raised.
>             
>       This patch addresses this issue by extending the existing check
>       in external_lock to take into account binlog filtering rules
>       before deciding to print an error. After BUG 39934 is fixed,
>       decide_logging_format takes into account filtering rules for
>       SBL. Thence, there is no need to change decide_logging_format as
>       part of this bugfix.
>      @ mysql-test/suite/binlog/r/binlog_stm_do_db.result
>         Result file.
>      @ mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
>         Server option to filter all databases except the one with the
>         name 'b42829'.
>      @ mysql-test/suite/binlog/t/binlog_stm_do_db.test
>         Test case for statement based logging. This format triggered
>         the bug reported.
>      @ sql/sql_class.cc
>         Added the thd_binlog_filter_ok to INNODB_COMPATIBILITY_HOOKS set.
>      @ storage/innobase/handler/ha_innodb.cc
>         Extended check in external_lock to take into consideration the
>         filtering when deciding to throw an error.
>      @ storage/innobase/handler/ha_innodb.h
>         Added declaration of new hook.
> 
>     added:
>       mysql-test/suite/binlog/r/binlog_stm_do_db.result
>       mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt
>       mysql-test/suite/binlog/t/binlog_stm_do_db.test
>     modified:
>       sql/sql_class.cc
>       storage/innobase/handler/ha_innodb.cc
>       storage/innobase/handler/ha_innodb.h
> === added file 'mysql-test/suite/binlog/r/binlog_stm_do_db.result'
> --- a/mysql-test/suite/binlog/r/binlog_stm_do_db.result	1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/r/binlog_stm_do_db.result	2009-07-23 12:59:25 +0000
> @@ -0,0 +1,42 @@
> +SET @old_isolation_level= @@session.tx_isolation;
> +SET @@session.tx_isolation= 'READ-COMMITTED';
> +CREATE DATABASE b42829;
> +use b42829;
> +CREATE TABLE t1 (x int, y int) engine=InnoDB;
> +CREATE TABLE t2 (x int, y int) engine=InnoDB;
> +CREATE DATABASE b42829_filtered;
> +use b42829_filtered;
> +CREATE TABLE t1 (x int, y int) engine=InnoDB;
> +CREATE TABLE t2 (x int, y int) engine=InnoDB;
> +SET @@session.sql_log_bin= 0;
> +INSERT INTO b42829_filtered.t1 VALUES (100,100);
> +INSERT INTO b42829.t1 VALUES (100,100);
> +SET @@session.sql_log_bin= 1;
> +### assertion: the inserts will not raise log error because
> +###            binlog-do-db is filtering used database
> +INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
> +INSERT INTO t1 SELECT * FROM t2;
> +### assertion: assert that despite updating a not filtered
> +###            database this wont trigger an error as the
> +###            used database is the filtered one.
> +UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2;
> +use b42829;
> +### assertion: the statements *will* raise log error because
> +###            binlog-do-db is not filtering  used database 
> +BEGIN;
> +INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
> +ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT =
> STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is
> limited to row-logging when transaction isolation level is READ COMMITTED or READ
> UNCOMMITTED.
> +UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2;
> +ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT =
> STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is
> limited to row-logging when transaction isolation level is READ COMMITTED or READ
> UNCOMMITTED.
> +INSERT INTO t1 SELECT * FROM t2;
> +ERROR HY000: Cannot execute statement: binlogging impossible since BINLOG_FORMAT =
> STATEMENT and at least one table uses a storage engine limited to row-logging. InnoDB is
> limited to row-logging when transaction isolation level is READ COMMITTED or READ
> UNCOMMITTED.
> +COMMIT;
> +### assertion: filtered events did not make into the binlog
> +show binlog events from <binlog_start>;
> +Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> +master-bin.000001	#	Query	#	#	CREATE DATABASE b42829
> +master-bin.000001	#	Query	#	#	use `b42829`; CREATE TABLE t1 (x int, y int)
> engine=InnoDB
> +master-bin.000001	#	Query	#	#	use `b42829`; CREATE TABLE t2 (x int, y int)
> engine=InnoDB
> +DROP DATABASE b42829;
> +DROP DATABASE b42829_filtered;
> +SET @@session.tx_isolation= @old_isolation_level;
> 
> === added file 'mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt'
> --- a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt	1970-01-01 00:00:00
> +0000
> +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt	2009-07-23 12:59:25
> +0000
> @@ -0,0 +1 @@
> +--binlog-do-db=b42829
> 
> === added file 'mysql-test/suite/binlog/t/binlog_stm_do_db.test'
> --- a/mysql-test/suite/binlog/t/binlog_stm_do_db.test	1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test	2009-07-23 12:59:25 +0000
> @@ -0,0 +1,90 @@
> +# BUG#42829: binlogging enabled for all schemas regardless of
> +# binlog-db-db / binlog-ignore-db
> +#
> +# WHAT
> +# ====
> +#
> +#  We want to test whether filtered events from binlog will cause
> +#  raising an error mentioning that statement is unable to be logged or
> +#  not, when:
> +#
> +#   1. isolation level READ-COMMITTED; AND
> +#
> +#   2. using InnoDB engine; AND
> +#
> +#   3. using SBL (in which case InnoDB will only allow RBL).
> +#
> +# HOW
> +# ===
> +#
> +#  The test is implemented as follows:
> +#
> +#     i) set tx_isolation to read-committed.
> +#
> +#    ii) create two databases (one filtered other not - using
> +#        binlog-do-db)
> +#
> +#   iii) Create statements that are to be filtered on filtered db
> +#
> +#       - At this point, before fix, an error would be raised
> +#
> +#    iv) do the same thing for not the filtered database and check
> +#        that events throw an error:
> +#
> +#      - Error: ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
> +#
> +
> +-- source include/have_log_bin.inc
> +-- source include/have_innodb.inc
> +-- source include/have_binlog_format_statement.inc
> +
> +SET @old_isolation_level= @@session.tx_isolation;
> +SET @@session.tx_isolation= 'READ-COMMITTED';
> +
> +-- let $engine= InnoDB
> +-- let $filtered= b42829_filtered
> +-- let $not_filtered= b42829
> +
> +-- eval CREATE DATABASE $not_filtered
> +-- eval use $not_filtered
> +-- eval CREATE TABLE t1 (x int, y int) engine=$engine
> +-- eval CREATE TABLE t2 (x int, y int) engine=$engine
> +
> +-- eval CREATE DATABASE $filtered
> +-- eval use $filtered
> +-- eval CREATE TABLE t1 (x int, y int) engine=$engine
> +-- eval CREATE TABLE t2 (x int, y int) engine=$engine
> +
> +SET @@session.sql_log_bin= 0;
> +-- eval INSERT INTO $filtered.t1 VALUES (100,100)
> +-- eval INSERT INTO $not_filtered.t1 VALUES (100,100)
> +SET @@session.sql_log_bin= 1;
> +
> +-- echo ### assertion: the inserts will not raise log error because
> +-- echo ###            binlog-do-db is filtering used database
> +INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
> +INSERT INTO t1 SELECT * FROM t2;
> +
> +-- echo ### assertion: assert that despite updating a not filtered
> +-- echo ###            database this wont trigger an error as the
> +-- echo ###            used database is the filtered one.
> +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
> +
> +-- eval use $not_filtered
> +-- echo ### assertion: the statements *will* raise log error because
> +-- echo ###            binlog-do-db is not filtering  used database 
> +BEGIN;
> +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
> +INSERT INTO t2 VALUES (1,2), (1,3), (1,4);
> +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
> +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2
> +-- error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
> +INSERT INTO t1 SELECT * FROM t2;
> +COMMIT;
> +
> +-- echo ### assertion: filtered events did not make into the binlog
> +source include/show_binlog_events.inc;
> +
> +-- eval DROP DATABASE $not_filtered
> +-- eval DROP DATABASE $filtered
> +SET @@session.tx_isolation= @old_isolation_level;
> \ No newline at end of file
> 
> === modified file 'sql/sql_class.cc'
> --- a/sql/sql_class.cc	2009-07-23 10:38:03 +0000
> +++ b/sql/sql_class.cc	2009-07-23 12:59:25 +0000
> @@ -43,6 +43,7 @@
>  
>  #include "sp_rcontext.h"
>  #include "sp_cache.h"
> +#include "rpl_filter.h"
>  
>  /*
>    The following is used to initialise Table_ident with a internal
> @@ -2915,6 +2916,11 @@ extern "C" void thd_mark_transaction_to_
>  {
>    mark_transaction_to_rollback(thd, all);
>  }
> +
> +extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd)
> +{
> +  return binlog_filter->db_ok(thd->db);
> +}
>  #endif // INNODB_COMPATIBILITY_HOOKS */
>  
>  /****************************************************************************
> 
> === modified file 'storage/innobase/handler/ha_innodb.cc'
> --- a/storage/innobase/handler/ha_innodb.cc	2009-07-23 10:38:03 +0000
> +++ b/storage/innobase/handler/ha_innodb.cc	2009-07-23 12:59:25 +0000
> @@ -6860,7 +6860,8 @@ ha_innobase::external_lock(
>  	*/
>  	if (lock_type == F_WRLCK &&
>  	    !(table_flags() & HA_BINLOG_STMT_CAPABLE) &&
> -	    thd_binlog_format(thd) == BINLOG_FORMAT_STMT) {
> +	    thd_binlog_format(thd) == BINLOG_FORMAT_STMT &&
> +            thd_binlog_filter_ok(thd) != 0) {
>  		/* The error may be suppressed by test cases, by setting
>  		the no_innodb_binlog_errors debug symbol. */
>  		if (DBUG_EVALUATE_IF("no_innodb_binlog_errors", 0, 1)) {
> 
> === modified file 'storage/innobase/handler/ha_innodb.h'
> --- a/storage/innobase/handler/ha_innodb.h	2009-04-24 11:28:46 +0000
> +++ b/storage/innobase/handler/ha_innodb.h	2009-07-23 12:59:25 +0000
> @@ -252,4 +252,11 @@ int thd_binlog_format(const MYSQL_THD th
>    @param  all   TRUE <=> rollback main transaction.
>  */
>  void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
> +
> +/**
> +  Check if binary logging is filtered for thread's current db.
> +  @param  thd   Thread handle
> +  @retval 1 the query is not filtered, 0 otherwise.
> +*/
> +bool thd_binlog_filter_ok(const MYSQL_THD thd);
>  }
> 

Thread
bzr commit into mysql-5.1-bugteam branch (luis.soares:3028) Bug#42829Luis Soares23 Jul
  • Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3028)Bug#42829He Zhenxing31 Aug