List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:June 19 2007 2:52pm
Subject:bk commit into 5.1 tree (mats:1.2556) BUG#28722
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mats. When mats does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-06-19 14:52:07+02:00, mats@stripped +3 -0
  BUG#28722 (Multi-engine statements on has_own_binlogging engine):
  WL#3931 (Multi-table statement involving self-logging engines):
  
  Adding logic to generate error if more than one engine is involved in
  the statement and at least one engine is self-logging (i.e., has the
  HA_HAS_OWN_BINLOGGING table flags set).

  mysql-test/r/binlog_multi_engine.result@stripped, 2007-06-19 14:52:02+02:00,
mats@stripped +7 -15
    Result change.

  mysql-test/t/binlog_multi_engine.test@stripped, 2007-06-19 14:52:02+02:00,
mats@stripped +7 -0
    Errors now generated for some statements due to NDB setting the
    HA_HAS_OWN_BINLOGGING flag.

  sql/sql_base.cc@stripped, 2007-06-19 14:52:02+02:00, mats@stripped +43
-14
    Computing both the intersection and union of all table flags in the
    logic to decide logging format.
    
    Calculating if there are more than one engine involved in the statement.
    For this case, we only consider engines that hold tables that data is
    written to.
    
    Adding logic to generate error if more than one engine is involved in
    the statement and at least one engine is self-logging (i.e., has the
    HA_HAS_OWN_BINLOGGING table flags set).

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	mats
# Host:	kindahl-laptop.dnsalias.net
# Root:	/home/bk/b28722-mysql-5.1-rpl

--- 1.410/sql/sql_base.cc	2007-06-19 14:52:17 +02:00
+++ 1.411/sql/sql_base.cc	2007-06-19 14:52:17 +02:00
@@ -28,6 +28,8 @@
 #include <io.h>
 #endif
 
+#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
+
 /**
   This internal handler is used to trap internally
   errors that can occur when executing open table
@@ -3996,36 +3998,47 @@
 {
   if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
   {
-    handler::Table_flags binlog_flags= ~handler::Table_flags();
+    handler::Table_flags flags_some_set= handler::Table_flags();
+    handler::Table_flags flags_all_set= ~handler::Table_flags();
+    my_bool more_than_one_engine= FALSE;
+    void* prev_ht= NULL;
     for (TABLE_LIST *table= tables; table; table= table->next_global)
+    {
       if (!table->placeholder() && table->lock_type >=
TL_WRITE_ALLOW_WRITE)
       {
-#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
-#ifndef DBUG_OFF
-        ulonglong flags= table->table->file->ha_table_flags();
+        ulonglong const flags= table->table->file->ha_table_flags();
         DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s",
                             table->table_name,
                             FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE),
                             FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE)));
-#endif
-        binlog_flags &= table->table->file->ha_table_flags();
+        if (prev_ht && prev_ht != table->table->file->ht)
+          more_than_one_engine= TRUE;
+        prev_ht= table->table->file->ht;
+        flags_all_set &= flags;
+        flags_some_set |= flags;
       }
-    binlog_flags&= HA_BINLOG_FLAGS;
-    DBUG_PRINT("info", ("binlog_flags: %s%s",
-                        FLAGSTR(binlog_flags, HA_BINLOG_STMT_CAPABLE),
-                        FLAGSTR(binlog_flags, HA_BINLOG_ROW_CAPABLE)));
+    }
+
+    DBUG_PRINT("info", ("flags_all_set: %s%s",
+                        FLAGSTR(flags_all_set, HA_BINLOG_STMT_CAPABLE),
+                        FLAGSTR(flags_all_set, HA_BINLOG_ROW_CAPABLE)));
+    DBUG_PRINT("info", ("flags_some_set: %s%s",
+                        FLAGSTR(flags_some_set, HA_BINLOG_STMT_CAPABLE),
+                        FLAGSTR(flags_some_set, HA_BINLOG_ROW_CAPABLE)));
     DBUG_PRINT("info", ("thd->variables.binlog_format: %ld",
                         thd->variables.binlog_format));
+    DBUG_PRINT("info", ("more_than_one_engine: %s",
+                        more_than_one_engine ? "TRUE" : "FALSE"));
 
     int error= 0;
-    if (binlog_flags == 0)
+    if (flags_all_set == 0)
     {
       my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
                "Statement cannot be logged to the binary log in"
                " row-based nor statement-based format");
     }
     else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
-             (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
+             (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
     {
       my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
                 "Statement-based format required for this statement,"
@@ -4033,13 +4046,29 @@
     }
     else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW ||
               thd->lex->is_stmt_unsafe()) &&
-             (binlog_flags & HA_BINLOG_ROW_CAPABLE) == 0)
+             (flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0)
     {
       my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
                 "Row-based format required for this statement,"
                 " but not allowed by this combination of engines");
     }
 
+    /*
+      If more than one engine is involved in the statement and at
+      least one is doing it's own logging (is *self-logging*), the
+      statement cannot be logged atomically, so we generate an error
+      rather than allowing the binlog to become corrupt.
+     */
+    if (more_than_one_engine &&
+        (flags_some_set & HA_HAS_OWN_BINLOGGING))
+    {
+      error= ER_BINLOG_LOGGING_IMPOSSIBLE;
+      my_error(error, MYF(0),
+               "Statement cannot be written atomically since more"
+               " than one engine involved and at least one engine"
+               " is self-logging");
+    }
+
     DBUG_PRINT("info", ("error: %d", error));
 
     if (error)
@@ -4061,7 +4090,7 @@
       here.
     */
     if (thd->lex->is_stmt_unsafe() ||
-        (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
+        (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
     {
       thd->set_current_stmt_binlog_row_based_if_mixed();
     }

--- 1.3/mysql-test/r/binlog_multi_engine.result	2007-06-19 14:52:17 +02:00
+++ 1.4/mysql-test/r/binlog_multi_engine.result	2007-06-19 14:52:17 +02:00
@@ -10,7 +10,7 @@
 UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
 ERROR HY000: Binary logging not possible. Message: Statement-based format required for
this statement, but not allowed by this combination of engines
 UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
-ERROR HY000: Binary logging not possible. Message: Statement cannot be logged to the
binary log in row-based nor statement-based format
+ERROR HY000: Binary logging not possible. Message: Statement-based format required for
this statement, but not allowed by this combination of engines
 TRUNCATE t1m;
 TRUNCATE t1b;
 TRUNCATE t1n;
@@ -20,8 +20,9 @@
 INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
 UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
 UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
+ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically
since more than one engine involved and at least one engine is self-logging
 UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
-ERROR HY000: Binary logging not possible. Message: Statement cannot be logged to the
binary log in row-based nor statement-based format
+ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically
since more than one engine involved and at least one engine is self-logging
 TRUNCATE t1m;
 TRUNCATE t1b;
 TRUNCATE t1n;
@@ -33,8 +34,9 @@
 UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
 ERROR HY000: Binary logging not possible. Message: Row-based format required for this
statement, but not allowed by this combination of engines
 UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
+ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically
since more than one engine involved and at least one engine is self-logging
 UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
-ERROR HY000: Binary logging not possible. Message: Statement cannot be logged to the
binary log in row-based nor statement-based format
+ERROR HY000: Binary logging not possible. Message: Row-based format required for this
statement, but not allowed by this combination of engines
 DROP TABLE t1m, t1b, t1n;
 show binlog events from <binlog_start>;
 Log_name	Pos	Event_type	Server_id	End_log_pos	Info
@@ -50,9 +52,6 @@
 master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t1m VALUES (1,1), (1,2), (2,1),
(2,2)
 master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t1b VALUES (1,1), (1,2), (2,1),
(2,2)
 master-bin.000001	#	Query	#	#	use `test`; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t1m)
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t1n)
-master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1m
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1b
 master-bin.000001	#	Query	#	#	BEGIN
@@ -60,23 +59,16 @@
 master-bin.000001	#	Table_map	#	#	table_id: # (mysql.ndb_apply_status)
 master-bin.000001	#	Write_rows	#	#	table_id: #
 master-bin.000001	#	Write_rows	#	#	table_id: #
-master-bin.000001	#	Write_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE t1n
 master-bin.000001	#	Table_map	#	#	table_id: # (test.t1m)
 master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t1m)
-master-bin.000001	#	Table_map	#	#	table_id: # (test.t1n)
-master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	BEGIN
 master-bin.000001	#	Table_map	#	#	table_id: # (test.t1n)
 master-bin.000001	#	Table_map	#	#	table_id: # (mysql.ndb_apply_status)
 master-bin.000001	#	Write_rows	#	#	table_id: #
 master-bin.000001	#	Write_rows	#	#	table_id: #
-master-bin.000001	#	Write_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; DROP TABLE t1m, t1b, t1n

--- 1.3/mysql-test/t/binlog_multi_engine.test	2007-06-19 14:52:17 +02:00
+++ 1.4/mysql-test/t/binlog_multi_engine.test	2007-06-19 14:52:17 +02:00
@@ -1,3 +1,8 @@
+# Test to test how logging is done depending on the capabilities of
+# the engines. Unfortunately, we don't have a good row-only logging
+# engine, and NDB does not really cut is since it is also
+# self-logging. I'm using it nevertheless.
+
 source include/have_blackhole.inc;
 source include/have_ndb.inc;
 source include/have_binlog_format_mixed_or_row.inc;
@@ -30,6 +35,7 @@
 INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2);
 
 UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
+error ER_BINLOG_LOGGING_IMPOSSIBLE;
 UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
 error ER_BINLOG_LOGGING_IMPOSSIBLE;
 UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
@@ -47,6 +53,7 @@
 
 error ER_BINLOG_LOGGING_IMPOSSIBLE;
 UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c;
+error ER_BINLOG_LOGGING_IMPOSSIBLE;
 UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f;
 error ER_BINLOG_LOGGING_IMPOSSIBLE;
 UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c;
Thread
bk commit into 5.1 tree (mats:1.2556) BUG#28722Mats Kindahl19 Jun