List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:September 23 2009 2:31am
Subject:bzr commit into mysql-5.1-bugteam branch (alfranio.correia:3117)
Bug#47287
View as plain text  
#At file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-47287/mysql-5.1-bugteam/ based on revid:joro@stripped

 3117 Alfranio Correia	2009-09-23
      BUG#47287 RBR: replication diff on basic case with txn- and non-txn tables in a statement
      
      Let
        - T be a transactional table and N non-transactional table.
        - B be begin, C commit and R rollback.
        - M be a mixed statement, i.e. a statement that updates both T and N.
        - M* be a mixed statement that fails while updating either T or N.
      
      This patch restore the behavior presented in 5.1.37 for rows either produced in
      the RBR or MIXED modes, when a M* statement that happened early in a transaction
      had their changes written to the binary log outside the boundaries of the
      transaction and wrapped in a BEGIN/ROLLBACK. This was done to keep the slave
      consistent with with the master as the rollback would keep the changes on N and
      undo them on T. In particular, we do what follows:
      
        . B M* T C would log - B M* R B T C.
      
      Note that, we are not preserving history from the master as we are introducing a
      rollback that never happened. However, this seems to be more acceptable than
      making the slave diverge. We do not fix the following case:
      
        . B T M* C would log B T M* C.
      
      The slave will diverge as the changes on T tables that originated from the M
      statement are rolled back on the master but not on the slave. Unfortunately, we
      cannot simply rollback the transaction as this would undo any uncommitted
      changes on T tables.
      
      SBR is not considered in this patch because a failing statement is written to
      the binary along with the error code and a slave executes and then rolls back
      the statement when it has an associated error code, thus undoing the effects
      on T. In RBR and MBR, a full-fledged fix will be pushed after the WL 2687.

    added:
      mysql-test/extra/binlog_tests/binlog_failure_mixing_engines.test
      mysql-test/suite/binlog/r/binlog_mixed_failure_mixing_engines.result
      mysql-test/suite/binlog/r/binlog_row_failure_mixing_engines.result
      mysql-test/suite/binlog/t/binlog_mixed_failure_mixing_engines.test
      mysql-test/suite/binlog/t/binlog_row_failure_mixing_engines.test
    modified:
      sql/log.cc
=== added file 'mysql-test/extra/binlog_tests/binlog_failure_mixing_engines.test'
--- a/mysql-test/extra/binlog_tests/binlog_failure_mixing_engines.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/extra/binlog_tests/binlog_failure_mixing_engines.test	2009-09-23 02:31:54 +0000
@@ -0,0 +1,105 @@
+################################################################################
+# Let 
+#   - T be a transactional table and N non-transactional table.
+#   - B be begin, C commit and R rollback.
+#   - M be a mixed statement, i.e. a statement that updates both T and N. 
+#   - M* be a mixed statement that fails while updating either T or N.
+#
+# In this test case, when changes are logged as rows either in the RBR or MIXED
+# modes, we check if a M* statement that happens early in a transaction is
+# written to the binary log outside the boundaries of the transaction and
+# wrapped in a BEGIN/ROLLBACK. This is done to keep the slave consistent with
+# with the master as the rollback will keep the changes on N and undo them on
+# T. In particular, we expect the following behavior:
+#
+#  1. B M* T C would log - B M* R B T C.
+#  2. B T M* C would log B T M* C.
+#
+# SBR is not considered in this test because a failing statement is written to
+# the binary along with the error code and a slave executes and then rolls back
+# the statement when it has an associated error code, thus undoing the effects
+# on T.
+#
+# Note that, in the first case, we are not preserving history from the master as
+# we are introducing a rollback that never happened. However, this seems to be
+# more acceptable than making the slave diverge. In the second case, the slave
+# will diverge as the changes on T tables that originated from the M statement
+# are rolled back on the master but not on the slave. Unfortunately, we cannot 
+# simply rollback the transaction as this would undo any uncommitted changes 
+# on T tables.
+#
+# Such issues do not happen in SBR. In RBR and MBR, a fix will be pushed after
+# the WL 2687.
+################################################################################
+
+
+--echo ###################################################################################
+--echo #                                   CONFIGURATION
+--echo ###################################################################################
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+
+DELIMITER |;
+
+CREATE TRIGGER tr_i_tt_1_to_nt_1 BEFORE INSERT ON tt_1 FOR EACH ROW
+BEGIN
+  INSERT INTO nt_1 VALUES (NEW.a, NEW.b);
+END|
+
+CREATE TRIGGER tr_i_nt_2_to_tt_2 BEFORE INSERT ON nt_2 FOR EACH ROW
+BEGIN
+  INSERT INTO tt_2 VALUES (NEW.a, NEW.b);
+END|
+
+DELIMITER ;|
+
+--echo ###################################################################################
+--echo #                             CHECK HISTORY IN BINLOG
+--echo ###################################################################################
+let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
+
+
+--echo *** "B M* T C" with error in M* generates in the binlog the "B M* R B T C" entries
+INSERT INTO nt_1 VALUES ("new text 1", 1);
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES (USER(), 2), (USER(), 1);
+INSERT INTO tt_1 VALUES ("new text 3", 3), ("new text 4", 4);
+COMMIT;
+
+INSERT INTO tt_2 VALUES ("new text 5", 5);
+BEGIN;
+--error ER_DUP_ENTRY
+INSERT INTO nt_2 VALUES (USER(), 6), (USER(), 5);
+INSERT INTO tt_2 VALUES ("new text 7", 7);
+COMMIT;
+
+--echo *** "B M M* T C" with error in M* generates in the binlog the "B M M* T C" entries
+INSERT INTO nt_1 VALUES ("new text 11", 11);
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 8", 8), ("new text 9", 9);
+--error ER_DUP_ENTRY
+INSERT INTO tt_1 VALUES (USER(), 10), (USER(), 11);
+INSERT INTO tt_2 VALUES ("new text 12", 12);
+COMMIT;
+
+INSERT INTO tt_2 VALUES ("new text 16", 16);
+BEGIN;
+INSERT INTO nt_2 VALUES ("new text 13", 13), ("new text 14", 14);
+--error ER_DUP_ENTRY
+INSERT INTO nt_2 VALUES (USER(), 15), (USER(), 16);
+INSERT INTO tt_2 VALUES ("new text 17", 17);
+COMMIT;
+
+--source include/show_binlog_events.inc
+
+--echo ###################################################################################
+--echo #                                        CLEAN
+--echo ###################################################################################
+
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE nt_1;
+DROP TABLE nt_2;

=== added file 'mysql-test/suite/binlog/r/binlog_mixed_failure_mixing_engines.result'
--- a/mysql-test/suite/binlog/r/binlog_mixed_failure_mixing_engines.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/r/binlog_mixed_failure_mixing_engines.result	2009-09-23 02:31:54 +0000
@@ -0,0 +1,97 @@
+###################################################################################
+#                                   CONFIGURATION
+###################################################################################
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+CREATE TRIGGER tr_i_tt_1_to_nt_1 BEFORE INSERT ON tt_1 FOR EACH ROW
+BEGIN
+INSERT INTO nt_1 VALUES (NEW.a, NEW.b);
+END|
+CREATE TRIGGER tr_i_nt_2_to_tt_2 BEFORE INSERT ON nt_2 FOR EACH ROW
+BEGIN
+INSERT INTO tt_2 VALUES (NEW.a, NEW.b);
+END|
+###################################################################################
+#                             CHECK HISTORY IN BINLOG
+###################################################################################
+*** "B M* T C" with error in M* generates in the binlog the "B M* R B T C" entries
+INSERT INTO nt_1 VALUES ("new text 1", 1);
+BEGIN;
+INSERT INTO tt_1 VALUES (USER(), 2), (USER(), 1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text 3", 3), ("new text 4", 4);
+COMMIT;
+INSERT INTO tt_2 VALUES ("new text 5", 5);
+BEGIN;
+INSERT INTO nt_2 VALUES (USER(), 6), (USER(), 5);
+ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 7", 7);
+COMMIT;
+*** "B M M* T C" with error in M* generates in the binlog the "B M M* T C" entries
+INSERT INTO nt_1 VALUES ("new text 11", 11);
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 8", 8), ("new text 9", 9);
+INSERT INTO tt_1 VALUES (USER(), 10), (USER(), 11);
+ERROR 23000: Duplicate entry '11' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 12", 12);
+COMMIT;
+INSERT INTO tt_2 VALUES ("new text 16", 16);
+BEGIN;
+INSERT INTO nt_2 VALUES ("new text 13", 13), ("new text 14", 14);
+INSERT INTO nt_2 VALUES (USER(), 15), (USER(), 16);
+ERROR 23000: Duplicate entry '16' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 17", 17);
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO nt_1 VALUES ("new text 1", 1)
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	ROLLBACK
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_1 VALUES ("new text 3", 3), ("new text 4", 4)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_2 VALUES ("new text 5", 5)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_2)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	ROLLBACK
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_2 VALUES ("new text 7", 7)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO nt_1 VALUES ("new text 11", 11)
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_1 VALUES ("new text 8", 8), ("new text 9", 9)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_2 VALUES ("new text 12", 12)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_2 VALUES ("new text 16", 16)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO nt_2 VALUES ("new text 13", 13), ("new text 14", 14)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_2)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO tt_2 VALUES ("new text 17", 17)
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+###################################################################################
+#                                        CLEAN
+###################################################################################
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE nt_1;
+DROP TABLE nt_2;

=== added file 'mysql-test/suite/binlog/r/binlog_row_failure_mixing_engines.result'
--- a/mysql-test/suite/binlog/r/binlog_row_failure_mixing_engines.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_failure_mixing_engines.result	2009-09-23 02:31:54 +0000
@@ -0,0 +1,123 @@
+###################################################################################
+#                                   CONFIGURATION
+###################################################################################
+CREATE TABLE nt_1 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE nt_2 (a text, b int PRIMARY KEY) ENGINE = MyISAM;
+CREATE TABLE tt_1 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+CREATE TABLE tt_2 (a text, b int PRIMARY KEY) ENGINE = Innodb;
+CREATE TRIGGER tr_i_tt_1_to_nt_1 BEFORE INSERT ON tt_1 FOR EACH ROW
+BEGIN
+INSERT INTO nt_1 VALUES (NEW.a, NEW.b);
+END|
+CREATE TRIGGER tr_i_nt_2_to_tt_2 BEFORE INSERT ON nt_2 FOR EACH ROW
+BEGIN
+INSERT INTO tt_2 VALUES (NEW.a, NEW.b);
+END|
+###################################################################################
+#                             CHECK HISTORY IN BINLOG
+###################################################################################
+*** "B M* T C" with error in M* generates in the binlog the "B M* R B T C" entries
+INSERT INTO nt_1 VALUES ("new text 1", 1);
+BEGIN;
+INSERT INTO tt_1 VALUES (USER(), 2), (USER(), 1);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+INSERT INTO tt_1 VALUES ("new text 3", 3), ("new text 4", 4);
+COMMIT;
+INSERT INTO tt_2 VALUES ("new text 5", 5);
+BEGIN;
+INSERT INTO nt_2 VALUES (USER(), 6), (USER(), 5);
+ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 7", 7);
+COMMIT;
+*** "B M M* T C" with error in M* generates in the binlog the "B M M* T C" entries
+INSERT INTO nt_1 VALUES ("new text 11", 11);
+BEGIN;
+INSERT INTO tt_1 VALUES ("new text 8", 8), ("new text 9", 9);
+INSERT INTO tt_1 VALUES (USER(), 10), (USER(), 11);
+ERROR 23000: Duplicate entry '11' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 12", 12);
+COMMIT;
+INSERT INTO tt_2 VALUES ("new text 16", 16);
+BEGIN;
+INSERT INTO nt_2 VALUES ("new text 13", 13), ("new text 14", 14);
+INSERT INTO nt_2 VALUES (USER(), 15), (USER(), 16);
+ERROR 23000: Duplicate entry '16' for key 'PRIMARY'
+INSERT INTO tt_2 VALUES ("new text 17", 17);
+COMMIT;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	ROLLBACK
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_2)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	ROLLBACK
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_1)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_1)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_2)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.nt_2)
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: #
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.tt_2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+###################################################################################
+#                                        CLEAN
+###################################################################################
+DROP TABLE tt_1;
+DROP TABLE tt_2;
+DROP TABLE nt_1;
+DROP TABLE nt_2;

=== added file 'mysql-test/suite/binlog/t/binlog_mixed_failure_mixing_engines.test'
--- a/mysql-test/suite/binlog/t/binlog_mixed_failure_mixing_engines.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_mixed_failure_mixing_engines.test	2009-09-23 02:31:54 +0000
@@ -0,0 +1,4 @@
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+
+--source extra/binlog_tests/binlog_failure_mixing_engines.test

=== added file 'mysql-test/suite/binlog/t/binlog_row_failure_mixing_engines.test'
--- a/mysql-test/suite/binlog/t/binlog_row_failure_mixing_engines.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/binlog/t/binlog_row_failure_mixing_engines.test	2009-09-23 02:31:54 +0000
@@ -0,0 +1,4 @@
+--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
+
+--source extra/binlog_tests/binlog_failure_mixing_engines.test

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2009-09-11 17:06:27 +0000
+++ b/sql/log.cc	2009-09-23 02:31:54 +0000
@@ -182,7 +182,10 @@ public:
   {
     DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
     DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos));
-    delete pending();
+    if (pending())
+    {
+      delete pending();
+    }
     set_pending(0);
     reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
     trans_log.end_of_file= max_binlog_cache_size;
@@ -1539,9 +1542,10 @@ static int binlog_commit(handlerton *hto
   {
     Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, 0);
     error= binlog_end_trans(thd, trx_data, &qev, all);
-    goto end;
   }
 
+  trx_data->at_least_one_stmt = my_b_tell(&trx_data->trans_log) > 0;
+
 end:
   if (!all)
     trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit
@@ -1608,15 +1612,18 @@ static int binlog_rollback(handlerton *h
   {
    /*
       We flush the cache with a rollback, wrapped in a beging/rollback if:
-        . aborting a transcation that modified a non-transactional table or;
+        . aborting a transaction that modified a non-transactional table;
         . aborting a statement that modified both transactional and
-          non-transctional tables but which is not in the boundaries of any
-          transaction;
+          non-transactional tables but which is not in the boundaries of any
+          transaction or there was no early change;
         . the OPTION_KEEP_LOG is activate.
     */
     if ((all && thd->transaction.all.modified_non_trans_table) ||
         (!all && thd->transaction.stmt.modified_non_trans_table &&
          !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) ||
+        (!all && thd->transaction.stmt.modified_non_trans_table &&
+         !trx_data->at_least_one_stmt &&
+         thd->current_stmt_binlog_row_based) ||
         ((thd->options & OPTION_KEEP_LOG)))
     {
       Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);


Attachment: [text/bzr-bundle]
Thread
bzr commit into mysql-5.1-bugteam branch (alfranio.correia:3117)Bug#47287Alfranio Correia23 Sep