List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:March 8 2010 7:10pm
Subject:bzr commit into mysql-5.1-rep+2 branch (alfranio.correia:3182)
Bug#50479
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-50479/mysql-5.1-rep%2B2/ based on revid:sven.sandberg@stripped

 3182 Alfranio Correia	2010-03-08
      BUG#50479 DDL stmt on row-only/stmt-only tables generate spurious binlog_format errors
      
      In the fix of BUG#39934 in 5.1-rep+3, errors are generated when
      binlog_format=row and a statement modifies a table restricted to
      statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if
      binlog_format=statement and a statement modifies a table limited to
      row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE).
      
      However, some DDL statements that lock tables (e.g. ALTER TABLE,
      CREATE INDEX and CREATE TRIGGER) were causing spurious errors,
      although any row might be inserted into the binary log.
      
      To fix the problem, we tagged statements that may generate
      rows into the binary log and thence the warning messages are
      only printed out wen the appropriate conditions hold and rows
      might be changed.
     @ mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result
        Added test case.
     @ mysql-test/suite/binlog/t/binlog_spurious_ddl_errors-master.opt
        Added test case.
     @ mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
        Added test case.

    added:
      mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result
      mysql-test/suite/binlog/t/binlog_spurious_ddl_errors-master.opt
      mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test
    modified:
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_parse.cc
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/ha_innodb.h
      storage/innodb_plugin/handler/ha_innodb.cc
      storage/innodb_plugin/handler/ha_innodb.h
=== added file 'mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result'
--- a/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result	2010-03-08 19:09:08 +0000
@@ -0,0 +1,23 @@
+SET @old_binlog_format= @@global.binlog_format;
+INSTALL PLUGIN example SONAME 'ha_example.so';
+SET binlog_format = STATEMENT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB;
+ALTER TABLE t_row ADD COLUMN b INT;
+CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+CREATE INDEX i ON t_row(a);
+DROP TABLE t_row;
+SET binlog_format = ROW;
+CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
+ALTER TABLE t_stmt ADD COLUMN b INT;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE'
+CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+CREATE INDEX i ON t_stmt(a);
+ERROR 42000: Too many key parts specified; max 0 parts allowed
+SET binlog_format = STATEMENT;
+CREATE TABLE t_row ENGINE = InnoDB SELECT * FROM t_stmt;
+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.
+DROP TABLE t_stmt;
+UNINSTALL PLUGIN example;
+SET @@global.binlog_format = @old_binlog_format;
+SET @@session.binlog_format = @old_binlog_format;

=== added file 'mysql-test/suite/binlog/t/binlog_spurious_ddl_errors-master.opt'
--- a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors-master.opt	2010-03-08 19:09:08 +0000
@@ -0,0 +1 @@
+--innodb $EXAMPLE_PLUGIN_OPT

=== added file 'mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test'
--- a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test	2010-03-08 19:09:08 +0000
@@ -0,0 +1,62 @@
+################################################################################
+# BUG#50479:
+#
+# In the fix of BUG#39934 in 5.1-rep+3, errors are generated when
+# binlog_format=row and a statement modifies a table restricted to
+# statement-logging (ER_BINLOG_ROW_MODE_AND_STMT_ENGINE); or if
+# binlog_format=statement and a statement modifies a table limited to
+# row-logging (ER_BINLOG_STMT_MODE_AND_ROW_ENGINE).
+#
+# In this test case, we check if some DDL statements that lock tables do not
+# trigger errors as they do not generate rows events and as such are harmless
+# from the point of view of conflicts between the engine's supported logging
+# format and the value of binlog_format.
+#
+# Currently, ALTER TABLE, CREATE INDEX and CREATE TRIGGER.
+#
+# CREATE TABLE ... SELECT should generate an error because the command can
+# generate row events. In contrast, CREATE TABLE without SELECT cannot generate
+# an error.
+################################################################################
+--source include/have_innodb.inc
+--source include/have_example_plugin.inc
+--source include/have_log_bin.inc
+
+SET @old_binlog_format= @@global.binlog_format;
+
+INSTALL PLUGIN example SONAME 'ha_example.so';
+################# ER_BINLOG_STMT_MODE_AND_ROW_ENGINE #################
+SET binlog_format = STATEMENT;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+CREATE TABLE t_row (a VARCHAR(100)) ENGINE = InnoDB;
+
+ALTER TABLE t_row ADD COLUMN b INT;
+
+CREATE TRIGGER trig_row BEFORE INSERT ON t_row FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+
+CREATE INDEX i ON t_row(a);
+
+DROP TABLE t_row;
+
+################# ER_BINLOG_ROW_MODE_AND_STMT_ENGINE #################
+SET binlog_format = ROW;
+CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE t_stmt ADD COLUMN b INT;
+
+CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
+
+--error ER_TOO_MANY_KEY_PARTS
+CREATE INDEX i ON t_stmt(a);
+
+################# CREATE SELECT #################
+SET binlog_format = STATEMENT;
+--error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
+CREATE TABLE t_row ENGINE = InnoDB SELECT * FROM t_stmt;
+
+################# CLEAN UP #################
+DROP TABLE t_stmt;
+UNINSTALL PLUGIN example;
+SET @@global.binlog_format = @old_binlog_format;
+SET @@session.binlog_format = @old_binlog_format;

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-03-03 14:43:35 +0000
+++ b/sql/sql_class.cc	2010-03-08 19:09:08 +0000
@@ -3089,6 +3089,12 @@ extern "C" bool thd_binlog_filter_ok(con
 {
   return binlog_filter->db_ok(thd->db);
 }
+
+extern "C" bool thd_generates_rows(const MYSQL_THD thd)
+{
+  return ((sql_command_flags[thd->lex->sql_command] &
+          CF_CAN_GENERATE_ROW_EVENTS));
+}
 #endif // INNODB_COMPATIBILITY_HOOKS */
 
 /****************************************************************************
@@ -3647,7 +3653,9 @@ int THD::decide_logging_format(TABLE_LIS
         */
         my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0));
       }
-      else if (variables.binlog_format == BINLOG_FORMAT_ROW)
+      else if (variables.binlog_format == BINLOG_FORMAT_ROW &&
+               (sql_command_flags[lex->sql_command] &
+                CF_CAN_GENERATE_ROW_EVENTS))
       {
         /*
           2. Error: Cannot modify table that uses a storage engine
@@ -3685,7 +3693,9 @@ int THD::decide_logging_format(TABLE_LIS
           */
           my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_MODE), MYF(0));
         }
-        else if ((flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
+        else if ((flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0 &&
+                 (sql_command_flags[lex->sql_command] &
+                  CF_CAN_GENERATE_ROW_EVENTS))
         {
           /*
             5. Error: Cannot modify table that uses a storage engine

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-03-03 14:43:35 +0000
+++ b/sql/sql_class.h	2010-03-08 19:09:08 +0000
@@ -3130,6 +3130,11 @@ public:
   joins are currently prohibited in these statements.
 */
 #define CF_REEXECUTION_FRAGILE 32
+/**
+  Identifies statements that may generate row events
+  that eventually will end up in the binary log.
+*/
+#define CF_CAN_GENERATE_ROW_EVENTS 64
 
 /* Functions in sql_class.cc */
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-03-03 14:43:35 +0000
+++ b/sql/sql_parse.cc	2010-03-08 19:09:08 +0000
@@ -253,12 +253,14 @@ void init_update_queries(void)
 {
   bzero((uchar*) &sql_command_flags, sizeof(sql_command_flags));
 
-  sql_command_flags[SQLCOM_CREATE_TABLE]=   CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
+  sql_command_flags[SQLCOM_CREATE_TABLE]=   CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
+                                            CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_CREATE_INDEX]=   CF_CHANGES_DATA;
   sql_command_flags[SQLCOM_ALTER_TABLE]=    CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
   sql_command_flags[SQLCOM_TRUNCATE]=       CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND;
   sql_command_flags[SQLCOM_DROP_TABLE]=     CF_CHANGES_DATA;
-  sql_command_flags[SQLCOM_LOAD]=           CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE;
+  sql_command_flags[SQLCOM_LOAD]=           CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
+                                            CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_CREATE_DB]=      CF_CHANGES_DATA;
   sql_command_flags[SQLCOM_DROP_DB]=        CF_CHANGES_DATA;
   sql_command_flags[SQLCOM_RENAME_TABLE]=   CF_CHANGES_DATA;
@@ -270,21 +272,21 @@ void init_update_queries(void)
   sql_command_flags[SQLCOM_DROP_EVENT]=     CF_CHANGES_DATA;
 
   sql_command_flags[SQLCOM_UPDATE]=	    CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_UPDATE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_INSERT]=	    CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_INSERT_SELECT]=  CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_DELETE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
                                             CF_REEXECUTION_FRAGILE;
   sql_command_flags[SQLCOM_DELETE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_REPLACE]=        CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT |
-                                            CF_REEXECUTION_FRAGILE;
+                                            CF_REEXECUTION_FRAGILE | CF_CAN_GENERATE_ROW_EVENTS;
   sql_command_flags[SQLCOM_SELECT]=         CF_REEXECUTION_FRAGILE;
   sql_command_flags[SQLCOM_SET_OPTION]=     CF_REEXECUTION_FRAGILE;
   sql_command_flags[SQLCOM_DO]=             CF_REEXECUTION_FRAGILE;

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2010-03-03 14:43:35 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2010-03-08 19:09:08 +0000
@@ -7165,7 +7165,9 @@ ha_innobase::external_lock(
 	if (lock_type == F_WRLCK &&
 	    !(table_flags() & HA_BINLOG_STMT_CAPABLE) &&
 	    thd_binlog_format(thd) == BINLOG_FORMAT_STMT &&
-            thd_binlog_filter_ok(thd))
+            thd_binlog_filter_ok(thd)
+            && thd_generates_rows(thd)
+           )
         {
 		/* The error may be suppressed by test cases, by setting
 		the no_innodb_binlog_errors debug symbol. */

=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h	2010-01-22 09:57:02 +0000
+++ b/storage/innobase/handler/ha_innodb.h	2010-03-08 19:09:08 +0000
@@ -258,4 +258,11 @@ void thd_mark_transaction_to_rollback(MY
   @retval 1 the query is not filtered, 0 otherwise.
 */
 bool thd_binlog_filter_ok(const MYSQL_THD thd);
+/**
+  Check if the query may generate changes which
+  eventually will end up in the binary.
+  @param  thd   Thread handle
+  @retval 1 the query may generate changes, 0 otherwise.
+*/
+bool thd_generates_rows(const MYSQL_THD thd);
 }

=== modified file 'storage/innodb_plugin/handler/ha_innodb.cc'
--- a/storage/innodb_plugin/handler/ha_innodb.cc	2010-02-12 23:30:44 +0000
+++ b/storage/innodb_plugin/handler/ha_innodb.cc	2010-03-08 19:09:08 +0000
@@ -7914,6 +7914,7 @@ ha_innobase::external_lock(
 	           && !(table_flags() & HA_BINLOG_STMT_CAPABLE)
 #if MYSQL_VERSION_ID > 50140
                    && thd_binlog_filter_ok(thd)
+                   && thd_generates_rows(thd)
 #endif /* MYSQL_VERSION_ID > 50140 */
 		   )
 		{

=== modified file 'storage/innodb_plugin/handler/ha_innodb.h'
--- a/storage/innodb_plugin/handler/ha_innodb.h	2009-11-30 12:11:36 +0000
+++ b/storage/innodb_plugin/handler/ha_innodb.h	2010-03-08 19:09:08 +0000
@@ -265,6 +265,13 @@ void thd_mark_transaction_to_rollback(MY
   @retval 1 the query is not filtered, 0 otherwise.
 */
 bool thd_binlog_filter_ok(const MYSQL_THD thd);
+/**
+  Check if the query may generate changes which
+  eventually will end up in the binary.
+  @param  thd   Thread handle
+  @retval 1 the query may generate changes, 0 otherwise.
+*/
+bool thd_generates_rows(const MYSQL_THD thd);
 #endif /* MYSQL_VERSION_ID > 50140 */
 }
 


Attachment: [text/bzr-bundle]
Thread
bzr commit into mysql-5.1-rep+2 branch (alfranio.correia:3182)Bug#50479Alfranio Correia8 Mar