List:Commits« Previous MessageNext Message »
From:Luis Soares Date:June 1 2010 6:21pm
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-01
      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 the pending
      event ('p') bitmaps and the table ('t') the server accessed for
      the current record. If they are different, then 'p' is flushed
      and a new pending event, 'e', is created. If not, then the same
      pending event is used. However, the only bitmaps compared are
      't'->write_set against 'p'->get_cols(), which in some cases,
      means we are comparing write_sets against read_sets! In current
      versions of the server this may not be a big of a deal (as both
      read and write sets are always fully set).
      
      On the other hand, for the 6.0 codebase this is not the
      case. This means that if the table has a PK, only some columns
      will be flagged in the read_set. In these 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 is the case for 6.0 codebase, but also WL#5092
      based tree is affected because the user is given the option to
      choose whether to log partial (so not all columns will be flagged
      in the read and write set) or full rows, accentuating this
      problem.
      
      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-01 18:21:20 +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-01 18:21:20 +0000
@@ -1,5 +1,23 @@
+-- source include/have_binlog_format_row.inc
+
+#
+# BUG#46554: Unecessary Delete_rows events in 6.0-codebase may harm replication's performance
+
+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;
+## before the patch there would be 3 write row events
+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-01 18:21:20 +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-01 18:21:20 +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-01 18:21:20 +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-01 18:21:20 +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-20100601182120-a67ma5ixgfdg7nni.bundle
Thread
bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)Bug#46554Luis Soares1 Jun
  • Re: bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)Bug#46554He Zhenxing10 Jun
    • Re: bzr commit into mysql-next-mr-wl5092 branch (luis.soares:3151)Bug#46554Luís Soares14 Jun