List:Commits« Previous MessageNext Message »
From:Luis Soares Date:March 29 2010 6:31pm
Subject:bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3183)
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

 3183 Luis Soares	2010-03-29
      BUG#49100: RBR: Unexpected behavior when AI contains no usable data 
                 for slave columns
      
      This is a (pretty complete) sketch of a patch for this bug
      built on top of:
      
        - mysql-5.1-rpl-wl5092 (for server changes)
          luis.soares@stripped
      
        - WL#5096 tests (for test case facilities)
          http://lists.mysql.com/commits/104427 (needs this cset on
          top of revision aforementioned for mysql-5.1-rpl-wl5092).

    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-26 11:09:50 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_img.result	2010-03-29 18:31:30 +0000
@@ -24083,3 +24083,163 @@ 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: empty write set in both master and slave
+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: not empty write set, 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: not empty write set, but slave does not have usable data
+####          for its columns (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);
+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;
+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-26 11:09:50 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_img.test	2010-03-29 18:31:30 +0000
@@ -1,12 +1,15 @@
 #
+# This file contains tests for WL#5096 and bug fixes. 
+#
 # Test Description
 # ================
-#  
+# 
+#   WL#5096 Tests.
+# 
 #   In this file we will run tests that mix engines, indexes
 #   and blobs.
-#  
-#   See WL#5096 for details.
 #
+
 -- source suite/rpl/include/rpl_chained_3_hosts.inc
 -- source include/have_binlog_format_row.inc
 
@@ -41,3 +44,133 @@
 -- echo ###################################################################
 -- let $row_img_test_script= extra/rpl_tests/rpl_row_img_blobs.test
 -- source suite/rpl/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 suite/rpl/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 suite/rpl/include/rpl_row_img_set.inc
+
+-- echo #### case #1: empty write set in both master and slave
+
+CREATE TABLE t1 (c1 int DEFAULT 100);
+INSERT INTO t1 VALUES ();
+SHOW VARIABLES LIKE 'server_id';
+SELECT * FROM t1;
+-- source suite/rpl/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 suite/rpl/include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #2: not empty write set, but slave does not have usable data
+-- echo ####          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 suite/rpl/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 suite/rpl/include/rpl_chained_3_hosts_sync.inc
+
+-- echo #### case #3: not empty write set, but slave does not have usable data
+-- echo ####          for its columns (UPDATE)
+
+-- 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 suite/rpl/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 suite/rpl/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 suite/rpl/include/rpl_chained_3_hosts_sync.inc
+
+-- let $row_img_set=mysqld_a:FULL:N,mysqld_b:FULL:Y,mysqld_c:FULL:Y
+-- source suite/rpl/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-29 18:31:30 +0000
@@ -7636,7 +7636,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 +7687,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 +7695,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 +8698,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);
   }
   

=== 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-29 18:31:30 +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-29 18:31:30 +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-20100329183130-0pxspka854bw5z11.bundle
Thread
bzr commit into mysql-5.1-rpl-wl5092 branch (luis.soares:3183)Bug#49100Luis Soares29 Mar