List:Commits« Previous MessageNext Message »
From:Luis Soares Date:March 30 2010 11:19pm
Subject:bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)
Bug#49100
View as plain text  
#At file:///home/lsoares/Workspace/bzr/work/features/wl5092/mysql-5.1-rpl-wl5092/ based on revid:luis.soares@stripped

 3186 Luis Soares	2010-03-31
      BUG#49100: RBR: Unexpected behavior when AI contains no usable
                 data for slave columns
      
      RBR was not fully compliant with empty before and after
      images (BI and AI) in row events. Several faulty scenarios
      surfaced during WL#5092 implementation, especially when MINIMAL
      images were used:
      
        S1. Inserting an empty row on the master would cause slave to
            skip the event (empty AI);
      
            Expected: slave(s) shall apply the insert and fill its
            table with default values as master did.
      
        S2. Master inserts values just for columns that slave doesn't
            have (unusable AI at the slave).
      
            Expected: slave(s) shall apply the insert and fill its
            table with default values as master did for columns that
            user did not provide data.
       
        S3. Master updates columns that only it knows about (unusable
            AI at the slave) but references columns that it shares with
            the slave (usable BI at the slave). This would trigger an
            assertion on a third slave in chained replication: m -> s1
            -> s2, s2 would abort.
      
            Expected: slave s1 shall not update any row and slave s2
            shall not assert.
      
        S4. Master updates and references columns that only it knows
            about (unusable AI and BI at the slave).
      
            Expected: slave(s) shall skip the event and not update its
            tables with any value.
      
        S5. Master references columns that only it knows
            about (unusable BI at the slave) and updates columns shared
            with the slave (usable AI at the slave). Slave must stop.
      
            Expected: slave(s) shall fail with HA_ERR_END_OF_FILE.
      
      We fix S1 to S5 by relaxing some asserts that were triggered on
      when processing empty images. Additionally, on the
      Update_rows_log_event::do_exec_row we deployed a check the
      verifies if there is any value for AI. If there is not, then the
      event is skipped (neither BI nor AI is are processed).
      
      For mysqlbinlog --verbose --base64=decode-rows we print out an
      INSERT INTO t VALUES () when a write rows event contains an
      empty AI.
     @ mysql-test/suite/rpl/r/rpl_row_img.result
        Updates to result files.
     @ mysql-test/suite/rpl/t/rpl_row_img.test
        Added test cases.
     @ sql/log_event.cc
        1. Added printout for INSERT INTO ... VALUES () when AI is empty for
           Write_rows_log_events.
        2. Changed assertion from 'm_curr_row < ...' to 'm_curr_row <= ...'
        3. Calculation of estimated rows for bulk insert is now conditional,
           and dependent of whether m_curr_row < m_rows_end or not.
        4. In the Update_rows_log_event, changed it to take into consideration
           if there are any values in AI. If there are not, then skip event.
     @ sql/log_event.h
        Changed assertion to from 'm_curr_row < ...' to ' m_curr_row <= ...'
     @ sql/rpl_record.cc
        Do not unpack if master did not send any bit set in the write_set.

    modified:
      mysql-test/suite/rpl/r/rpl_row_img.result
      mysql-test/suite/rpl/t/rpl_row_img.test
      sql/log_event.cc
      sql/log_event.h
      sql/rpl_record.cc
=== modified file 'mysql-test/suite/rpl/r/rpl_row_img.result'
--- a/mysql-test/suite/rpl/r/rpl_row_img.result	2010-03-30 16:06:36 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_img.result	2010-03-30 23:19:25 +0000
@@ -24179,3 +24179,259 @@ FLUSH TABLES;
 SHOW VARIABLES LIKE 'binlog_row_image';
 Variable_name	Value
 binlog_row_image	FULL
+include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+RESET MASTER;
+RESET SLAVE;
+include/start_slave.inc
+include/start_slave.inc
+DROP TABLE IF EXISTS t1;
+CON: 'mysqld_a', IMG: 'MINIMAL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	MINIMAL
+CON: 'mysqld_b', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	MINIMAL
+CON: 'mysqld_c', IMG: 'MINIMAL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'MINIMAL';
+SET GLOBAL binlog_row_image= 'MINIMAL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	MINIMAL
+#### case #1: AI: no values logged
+CREATE TABLE t1 (c1 int DEFAULT 100);
+INSERT INTO t1 VALUES ();
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1
+100
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+100
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+100
+DROP TABLE t1;
+#### case #2: AI: not empty but slave does not have usable data for its columns (INSERT)
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, primary key(c2));
+SET SQL_LOG_BIN=1;
+INSERT INTO t1(c2) VALUES (1);
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2
+100	1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+100
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+100
+DROP TABLE t1;
+#### case #3: BI: usable columns on the slave, AI: no usable columns on the slave
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int);
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1);
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2
+1	1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c2=2 WHERE c1=1 AND c2=1;
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2
+1	2
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+1
+DROP TABLE t1;
+#### case #4: AI, BI: no usable columns on the slave (NOOP UPDATE).
+####          
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, c3 int, primary key(c2));
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1,1);
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2	c3
+1	1	1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c3=300 WHERE c2=1;
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2	c3
+1	1	300
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+1
+DROP TABLE t1;
+#### case #5: BI: no usable columns on the slave, AI: usable columns on the slave (slave must stop).
+####          
+CREATE TABLE t1 (c1 INT DEFAULT 100);
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100);
+SET SQL_LOG_BIN=1;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100, c2 INT PRIMARY KEY);
+SET SQL_LOG_BIN=1;
+INSERT INTO t1 VALUES (1,1);
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2
+1	1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	2
+SELECT * FROM t1;
+c1
+1
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	3
+SELECT * FROM t1;
+c1
+1
+UPDATE t1 SET c1=300 WHERE c2=1;
+SHOW VARIABLES LIKE 'server_id';
+Variable_name	Value
+server_id	1
+SELECT * FROM t1;
+c1	c2
+300	1
+SET SQL_LOG_BIN=0;
+call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032");
+SET SQL_LOG_BIN=1;
+### SLAVE STOPPED HAS EXPECTED!
+include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+RESET MASTER;
+RESET SLAVE;
+include/start_slave.inc
+include/start_slave.inc
+DROP TABLE IF EXISTS t1;
+CON: 'mysqld_a', IMG: 'FULL', RESTART SLAVE: 'N'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	FULL
+CON: 'mysqld_b', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	FULL
+CON: 'mysqld_c', IMG: 'FULL', RESTART SLAVE: 'Y'
+SET SESSION binlog_row_image= 'FULL';
+SET GLOBAL binlog_row_image= 'FULL';
+include/stop_slave.inc
+include/start_slave.inc
+FLUSH TABLES;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	FULL

=== modified file 'mysql-test/suite/rpl/t/rpl_row_img.test'
--- a/mysql-test/suite/rpl/t/rpl_row_img.test	2010-03-30 16:06:36 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_img.test	2010-03-30 23:19:25 +0000
@@ -1,12 +1,7 @@
 #
-# Test Description
-# ================
-#  
-#   In this file we will run tests that mix engines, indexes
-#   and blobs.
-#  
-#   See WL#5096 for details.
+# This file contains tests for WL#5096 and bug fixes. 
 #
+
 -- source include/rpl_chained_3_hosts.inc
 -- source include/have_binlog_format_row.inc
 
@@ -18,6 +13,18 @@
 -- source include/have_innodb.inc
 -- connection mysqld_a
 
+#
+# WL#5096
+#
+#   Test Description
+#   ================
+# 
+#   WL#5096 Tests.
+# 
+#   In this file we will run tests that mix engines, indexes
+#   and blobs.
+#
+
 -- echo ###################################################################
 -- echo ###################################################################
 -- echo # engines and binlog-row-image mixes                              #
@@ -41,3 +48,247 @@
 -- echo ###################################################################
 -- let $row_img_test_script= extra/rpl_tests/rpl_row_img_blobs.test
 -- source include/rpl_row_img_general_loop.inc
+
+#
+# BUG#49100: RBR: Unexpected behavior when AI contains no usable data 
+#            for slave columns
+#
+
+-- connection mysqld_c
+-- source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_b
+-- source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_a
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_c
+-- source include/start_slave.inc
+
+-- connection mysqld_b
+-- source include/start_slave.inc
+
+-- disable_warnings
+DROP TABLE IF EXISTS t1;
+-- enable_warnings
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_a
+
+-- let $row_img_set=mysqld_a:MINIMAL:N,mysqld_b:MINIMAL:Y,mysqld_c:MINIMAL:Y
+-- source include/rpl_row_img_set.inc
+
+-- echo #### case #1: AI: no values logged
+
+CREATE TABLE t1 (c1 int DEFAULT 100);
+INSERT INTO t1 VALUES ();
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+DROP TABLE t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #2: AI: not empty but slave does not have usable data for its columns (INSERT)
+
+-- connection mysqld_c
+CREATE TABLE t1 (c1 int DEFAULT 100);
+
+-- connection mysqld_b
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+
+-- connection mysqld_a
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, primary key(c2));
+SET SQL_LOG_BIN=1;
+
+INSERT INTO t1(c2) VALUES (1);
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+DROP TABLE t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #3: BI: usable columns on the slave, AI: no usable columns on the slave
+
+-- connection mysqld_c
+CREATE TABLE t1 (c1 int DEFAULT 100);
+
+-- connection mysqld_b
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+
+-- connection mysqld_a
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int);
+SET SQL_LOG_BIN=1;
+
+INSERT INTO t1 VALUES (1,1);
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+UPDATE t1 SET c2=2 WHERE c1=1 AND c2=1;
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+DROP TABLE t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #4: AI, BI: no usable columns on the slave (NOOP UPDATE).
+-- echo ####          
+
+-- connection mysqld_c
+CREATE TABLE t1 (c1 int DEFAULT 100);
+
+-- connection mysqld_b
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100);
+SET SQL_LOG_BIN=1;
+
+-- connection mysqld_a
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 int DEFAULT 100, c2 int, c3 int, primary key(c2));
+SET SQL_LOG_BIN=1;
+
+INSERT INTO t1 VALUES (1,1,1);
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+UPDATE t1 SET c3=300 WHERE c2=1;
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+DROP TABLE t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #5: BI: no usable columns on the slave, AI: usable columns on the slave (slave must stop).
+-- echo ####          
+
+-- connection mysqld_c
+CREATE TABLE t1 (c1 INT DEFAULT 100);
+
+-- connection mysqld_b
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100);
+SET SQL_LOG_BIN=1;
+
+-- connection mysqld_a
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 INT DEFAULT 100, c2 INT PRIMARY KEY);
+SET SQL_LOG_BIN=1;
+
+INSERT INTO t1 VALUES (1,1);
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source include/rpl_chained_3_hosts_sync.inc
+-- connection mysqld_b
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_c
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+
+-- connection mysqld_a
+UPDATE t1 SET c1=300 WHERE c2=1;
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- connection mysqld_b
+SET SQL_LOG_BIN=0;
+call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032");
+SET SQL_LOG_BIN=1;
+-- source include/wait_for_slave_sql_to_stop.inc
+-- let $errno=query_get_value("show slave status", Last_SQL_Errno, 1)
+if (`SELECT $errno <> 1032`)
+{
+  -- echo ### UNEXPECTED ERROR AT THE SLAVE: $errno
+  SHOW SLAVE STATUS;
+  -- die
+}
+-- echo ### SLAVE STOPPED HAS EXPECTED!
+
+## CLEAN UP
+
+-- connection mysqld_c
+-- source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_b
+-- source include/stop_slave.inc
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_a
+RESET MASTER;
+RESET SLAVE;
+
+-- connection mysqld_c
+-- source include/start_slave.inc
+
+-- connection mysqld_b
+-- source include/start_slave.inc
+
+-- connection mysqld_a
+-- disable_warnings
+DROP TABLE IF EXISTS t1;
+-- enable_warnings
+-- source include/rpl_chained_3_hosts_sync.inc
+
+-- let $row_img_set=mysqld_a:FULL:N,mysqld_b:FULL:Y,mysqld_c:FULL:Y
+-- source include/rpl_row_img_set.inc
+

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-03-04 17:00:32 +0000
+++ b/sql/log_event.cc	2010-03-30 23:19:25 +0000
@@ -1953,6 +1953,14 @@ void Rows_log_event::print_verbose(IO_CA
     return;
   }
 
+  /* If the write rows event contained no values for the AI */
+  if ((type_code == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end))
+  {
+    my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n", 
+                      map->get_db_name(), map->get_table_name());
+    goto end;
+  }
+
   for (const uchar *value= m_rows_buf; value < m_rows_end; )
   {
     size_t length;
@@ -7636,7 +7644,7 @@ int Rows_log_event::do_apply_event(Relay
 
     // row processing loop
 
-    while (error == 0 && m_curr_row < m_rows_end)
+    while (error == 0)
     {
       /* in_use can have been set to NULL in close_tables_for_reopen */
       THD* old_thd= table->in_use;
@@ -7687,7 +7695,7 @@ int Rows_log_event::do_apply_event(Relay
   
       // at this moment m_curr_row_end should be set
       DBUG_ASSERT(error || m_curr_row_end != NULL); 
-      DBUG_ASSERT(error || m_curr_row < m_curr_row_end);
+      DBUG_ASSERT(error || m_curr_row <= m_curr_row_end);
       DBUG_ASSERT(error || m_curr_row_end <= m_rows_end);
   
       m_curr_row= m_curr_row_end;
@@ -7695,6 +7703,9 @@ int Rows_log_event::do_apply_event(Relay
       if (error == 0 && !transactional_table)
         thd->transaction.all.modified_non_trans_table=
           thd->transaction.stmt.modified_non_trans_table= TRUE;
+
+      if (m_curr_row == m_rows_end)
+        break;
     } // row processing loop
 
     {/**
@@ -8695,7 +8706,11 @@ Rows_log_event::write_row(const Relay_lo
     /* this is the first row to be inserted, we estimate the rows with
        the size of the first row and use that value to initialize
        storage engine for bulk insertion */
-    ulong estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
+    DBUG_ASSERT(!(m_curr_row > m_curr_row_end));
+    ulong estimated_rows= 1;
+    if (m_curr_row < m_curr_row_end)
+      estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
+
     m_table->file->ha_start_bulk_insert(estimated_rows);
   }
   
@@ -9665,8 +9680,34 @@ int 
 Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
 {
   DBUG_ASSERT(m_table != NULL);
+  int error= 0;
+
+  /* check if update contains only values (for both BI and AI)
+     for columns that do not exist on the slave. If they do, we
+     can just unpack the rows and return (do nothing on the local 
+     table).
+
+     We can optimize and check only if there are usable values on 
+     the AI. However, if no good values on AI but we have values 
+     on BI, we will not be letting the slave thread to search the
+     SE for the row. This means that we may be loosing a bit on 
+     the safety side!
+     
+     After all, find_row is a consistency check as well.
+  */
+  if (/*!is_any_column_signaled_for_table(m_table, &m_cols) &&*/ /* BI */
+      !is_any_column_signaled_for_table(m_table, &m_cols_ai) /* AI */)
+  {
+    /* read and discard images, because they don't contain any 
+       useful information for this server table */
+    error = unpack_current_row(rli, &m_cols);
+    m_curr_row= m_curr_row_end;
+    error = error | unpack_current_row(rli, &m_cols_ai);
+
+    return error;
+  }
 
-  int error= find_row(rli); 
+  error= find_row(rli); 
   if (error)
   {
     /*

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2010-03-04 17:00:32 +0000
+++ b/sql/log_event.h	2010-03-30 23:19:25 +0000
@@ -3628,7 +3628,7 @@ protected:
     DBUG_ASSERT(m_table);
 
     bool first_row= (m_curr_row == m_rows_buf);
-    ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT);
+    ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT);
     int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, cols,
                                    &m_curr_row_end, &m_master_reclength,
                                    abort_on_warning, first_row);

=== modified file 'sql/rpl_record.cc'
--- a/sql/rpl_record.cc	2010-03-04 17:00:32 +0000
+++ b/sql/rpl_record.cc	2010-03-30 23:19:25 +0000
@@ -208,6 +208,20 @@ unpack_row(Relay_log_info const *rli,
   uchar const *null_ptr= row_data;
   uchar const *pack_ptr= row_data + master_null_byte_count;
 
+  if (bitmap_is_clear_all(cols))
+  {
+    /**
+       There was no data sent from the master, so there is 
+       nothing to unpack. In case we are unpacking an AI (for
+       update or insert purposes), we just use the default 
+       values from the slave to do the insert.
+    */
+    *row_end= pack_ptr;
+    *master_reclength= 0;
+    DBUG_RETURN(error);
+  }
+
+
   Field **const begin_ptr = table->field;
   Field **field_ptr;
   Field **const end_ptr= begin_ptr + colcnt;


Attachment: [text/bzr-bundle] bzr/luis.soares@sun.com-20100330231925-x0jd98cy789mnq60.bundle
Thread
bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Luis Soares31 Mar
  • Re: bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Alfranio Correia20 Apr
    • Re: bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Luís Soares21 Apr
      • Re: bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Luís Soares21 Apr
      • Re: bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Alfranio Correia23 Apr
        • Re: bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3186)Bug#49100Luís Soares23 Apr