List:Commits« Previous MessageNext Message »
From:Luis Soares Date:June 14 2010 12:55am
Subject:bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)
Bug#46554
View as plain text  
#At file:///home/lsoares/Workspace/bzr/work/bugfixing/46554/mysql-next-mr-wl5092/ based on revid:luis.soares@stripped

 3151 Luis Soares	2010-06-14
      BUG#46554: RBR: pending rows event can be flushed too soon
      sometimes.
      
      While packing a record into an rows event, the server performs
      several checks to see if a new rows event is needed. Among the
      conditions checked, there's one that deals with bitmaps from the
      pending event ('p') and the table ('t') that the server accessed
      for the current record. If they are different, then 'p' is
      flushed and a new pending event, 'np', is created. If not, then
      'p' is used. However, the only bitmaps compared are
      't'->write_set against 'p'->get_cols(), which in some cases,
      means we are comparing bitmaps related to write_sets (the ones
      from 't') against bitmaps related to read_sets (the ones from
      'p')!  In current versions of the server this issue is masked (as
      both read and write sets are always fully set).
      
      On the other hand, for 6.0 codebase this was not the case
      because if the table has a PK, only some columns will be flagged
      in the read_set. In such cases the write_set and the read_set
      will most likely not match causing the pending to be flushed.
      Additionally, the write_set is meaningless for delete events and
      the read_set is meaningless for write events! So comparison must
      take into account the type of the event to choose what bitmap to
      take from the table to make the comparison.
      
      As stated, this was the case for 6.0 codebase, but also for trees
      patched with WL#5092, because the user is given the option
      to choose whether to log partial (not all columns will be flagged
      in the read and write set) or full rows. If the user chooses to
      log partial rows, the problem may surface.
      
      Finally, This seems to be in fact a regression introduced by
      patch for BUG#33055 plus a post-merge fix that is related:
       - sp1r-mkindahl@stripped
      
      Since BUG#33055 was backported to WL#5092 tree, this regression
      tagged along.
      
      To fix this problem, we deploy a member function in
      Rows_log_event that is used to perform the correct comparison of
      the pending and table bitmaps.
     @ mysql-test/suite/binlog/t/binlog_row_binlog.test
        Added test case from the bug report.
     @ mysql-test/suite/perfschema/r/binlog_mix.result
        Removing spurious events from the result file.
     @ mysql-test/suite/perfschema/r/binlog_row.result
        Removing spurious events from the result file.
     @ sql/log_event.h
        1. Added utility member function to compare read and write bitmaps.
        2. Added get_cols_ai accessor for m_cols_ai.
     @ sql/sql_class.cc
        Replaced bitmap check with the proper call to the newly introduced
        member function that compares bitmaps according to the event type.

    modified:
      mysql-test/suite/binlog/r/binlog_row_binlog.result
      mysql-test/suite/binlog/t/binlog_row_binlog.test
      mysql-test/suite/perfschema/r/binlog_mix.result
      mysql-test/suite/perfschema/r/binlog_row.result
      sql/log_event.h
      sql/sql_class.cc
=== modified file 'mysql-test/suite/binlog/r/binlog_row_binlog.result'
--- a/mysql-test/suite/binlog/r/binlog_row_binlog.result	2010-04-20 09:10:43 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result	2010-06-14 00:55:41 +0000
@@ -1,3 +1,25 @@
+SELECT @@session.binlog_row_image INTO @saved_binlog_row_image;
+SET binlog_row_image= MINIMAL;
+SHOW VARIABLES LIKE 'binlog_row_image';
+Variable_name	Value
+binlog_row_image	MINIMAL
+RESET MASTER;
+CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(100)) ENGINE=Innodb;
+INSERT INTO t1 VALUES (1,'a'), (2,'b'), (3, 'c');
+DELETE FROM t1;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(100)) ENGINE=Innodb
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t1)
+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.t1)
+master-bin.000001	#	Delete_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+DROP TABLE t1;
+SET binlog_row_image= @saved_binlog_row_image;
 drop table if exists t1, t2;
 reset master;
 create table t1 (a int) engine=innodb;

=== modified file 'mysql-test/suite/binlog/t/binlog_row_binlog.test'
--- a/mysql-test/suite/binlog/t/binlog_row_binlog.test	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/binlog/t/binlog_row_binlog.test	2010-06-14 00:55:41 +0000
@@ -1,5 +1,22 @@
+-- source include/have_binlog_format_row.inc
+
+#
+# BUG#46554: RBR: pending rows event can be flushed too soon sometimes.
+
+SELECT @@session.binlog_row_image INTO @saved_binlog_row_image;
+SET binlog_row_image= MINIMAL;
+SHOW VARIABLES LIKE 'binlog_row_image';
+RESET MASTER;
+CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(100)) ENGINE=Innodb;
+INSERT INTO t1 VALUES (1,'a'), (2,'b'), (3, 'c');
+## before the patch there would be 3 delete row events
+DELETE FROM t1;
+-- source include/show_binlog_events.inc
+DROP TABLE t1;
+
+SET binlog_row_image= @saved_binlog_row_image;
+
 # This is a wrapper for binlog.test so that the same test case can be used 
 # For both statement and row based bin logs 9/19/2005 [jbm]
 
--- source include/have_binlog_format_row.inc
 -- source extra/binlog_tests/binlog.test

=== modified file 'mysql-test/suite/perfschema/r/binlog_mix.result'
--- a/mysql-test/suite/perfschema/r/binlog_mix.result	2010-05-26 09:29:59 +0000
+++ b/mysql-test/suite/perfschema/r/binlog_mix.result	2010-06-14 00:55:41 +0000
@@ -25,18 +25,6 @@ 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: # (performance_schema.SETUP_INSTRUMENTS)
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
 master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; drop table if exists test.t1
@@ -55,17 +43,5 @@ master-bin.000001	#	Query	#	#	use `test`
 master-bin.000001	#	Query	#	#	use `test`; drop table test.t2
 master-bin.000001	#	Query	#	#	BEGIN
 master-bin.000001	#	Table_map	#	#	table_id: # (performance_schema.SETUP_INSTRUMENTS)
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
 master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT

=== modified file 'mysql-test/suite/perfschema/r/binlog_row.result'
--- a/mysql-test/suite/perfschema/r/binlog_row.result	2010-05-26 09:29:59 +0000
+++ b/mysql-test/suite/perfschema/r/binlog_row.result	2010-06-14 00:55:41 +0000
@@ -25,18 +25,6 @@ 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: # (performance_schema.SETUP_INSTRUMENTS)
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
 master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT
 master-bin.000001	#	Query	#	#	use `test`; drop table if exists test.t1
@@ -55,17 +43,5 @@ master-bin.000001	#	Query	#	#	use `test`
 master-bin.000001	#	Query	#	#	use `test`; drop table test.t2
 master-bin.000001	#	Query	#	#	BEGIN
 master-bin.000001	#	Table_map	#	#	table_id: # (performance_schema.SETUP_INSTRUMENTS)
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
-master-bin.000001	#	Update_rows	#	#	table_id: #
 master-bin.000001	#	Update_rows	#	#	table_id: # flags: STMT_END_F
 master-bin.000001	#	Query	#	#	COMMIT

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2010-05-26 13:36:29 +0000
+++ b/sql/log_event.h	2010-06-14 00:55:41 +0000
@@ -3544,9 +3544,58 @@ public:
   virtual int get_data_size();
 
   MY_BITMAP const *get_cols() const { return &m_cols; }
+  MY_BITMAP const *get_cols_ai() const { return &m_cols_ai; }
   size_t get_width() const          { return m_width; }
   ulong get_table_id() const        { return m_table_id; }
 
+#if defined(MYSQL_SERVER)
+  /*
+    This member function compares the table's read/write_set
+    with this event's m_cols and m_cols_ai. Comparison takes 
+    into account what type of rows event is this: Delete, Write or
+    Update, therefore it uses the correct m_cols[_ai] according
+    to the event type code.
+
+    Note that this member function should only be called for the
+    following events:
+    - Delete_rows_log_event
+    - Wrirte_rows_log_event
+    - Update_rows_log_event
+
+    @param[IN] table The table to compare this events bitmaps 
+                     against.
+
+    @return TRUE if sets match, FALSE otherwise. (following 
+                 bitmap_cmp return logic).
+
+   */
+  virtual bool read_write_bitmaps_cmp(TABLE *table)
+  {
+    bool res= FALSE;
+
+    switch (get_type_code())
+    {
+      case DELETE_ROWS_EVENT:
+        res= bitmap_cmp(get_cols(), table->read_set);
+        break;
+      case UPDATE_ROWS_EVENT:
+        res= (bitmap_cmp(get_cols(), table->read_set) &&
+              bitmap_cmp(get_cols_ai(), table->write_set));
+        break;
+      case WRITE_ROWS_EVENT:
+        res= bitmap_cmp(get_cols(), table->write_set);
+        break;
+      default:
+        /* 
+          We should just compare bitmaps for Delete, Write
+          or Update rows events.
+        */
+        DBUG_ASSERT(0);
+    }
+    return res;
+  }
+#endif
+
 #ifdef MYSQL_SERVER
   virtual bool write_data_header(IO_CACHE *file);
   virtual bool write_data_body(IO_CACHE *file);

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-05-19 21:35:03 +0000
+++ b/sql/sql_class.cc	2010-06-14 00:55:41 +0000
@@ -4034,7 +4034,7 @@ THD::binlog_prepare_pending_rows_event(T
       pending->get_table_id() != table->s->table_map_id ||
       pending->get_type_code() != type_code || 
       pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
-      !bitmap_cmp(pending->get_cols(), table->write_set)) 
+      pending->read_write_bitmaps_cmp(table) == FALSE)
   {
     /* Create a new RowsEventT... */
     Rows_log_event* const


Attachment: [text/bzr-bundle] bzr/luis.soares@sun.com-20100614005541-76n8gd2gnd3v8uhy.bundle
Thread
bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)Bug#46554Luis Soares14 Jun
  • Re: bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)Bug#46554He Zhenxing14 Jun