[Commits] 7d1cb6f1ea9: MDEV-14605 Changes to "ON UPDATE CURRENT_TIMESTAMP" fields are not

andrei.elkin at pp.inet.fi andrei.elkin at pp.inet.fi
Mon Jan 21 18:22:28 EET 2019


revision-id: 7d1cb6f1ea99bc58bf45c3aa22edb8e25230257b (mariadb-10.1.37-63-g7d1cb6f1ea9)
parent(s): c1aae370879490dc0a3cd63c5b1010fa21b1f62c
author: Andrei Elkin
committer: Andrei Elkin
timestamp: 2019-01-21 18:19:00 +0200
message:

MDEV-14605 Changes to "ON UPDATE CURRENT_TIMESTAMP" fields are not
           always logged properly with binlog_row_image=MINIMAL

There are two issues fixed in this commit.
The first is an observation of a multi-table UPDATE binlogged
in row-format in binlog_row_image=MINIMAL mode. While the UPDATE aims
at a table with an ON-UPDATE attribute its binlog after-image misses
to record also installed default value.
The reason for that turns out missed marking of default-capable fields
in TABLE::write_set.

This is fixed to mark such fields similarly to 10.2's MDEV-10134 patch (db7edfed17efe6)
that introduced it. The marking affects 93d1e5ce0b841bed's TABLE:rpl_write_set
though and thus does not intervene (in 10.1) with MDEV-10134 agenda.

The 2nd issue is extra columns in in binlog_row_image=MINIMAL before-image
while merely a packed primary key is enough. The test main.mysqlbinlog_row_minimal
always had a wrong result recorded.
This is fixed to invoke a function that intended for read_set
possible filtering and which is called (supposed to) in all type of MDL, UPDATE
including; the test results have gotten corrected.

---
 mysql-test/r/mysqlbinlog_row_minimal.result | 45 ++++++++++++++---------------
 sql/sql_class.cc                            | 23 +++++++++++++--
 sql/table.cc                                |  6 ++--
 sql/table.h                                 |  6 +++-
 4 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/mysql-test/r/mysqlbinlog_row_minimal.result b/mysql-test/r/mysqlbinlog_row_minimal.result
index 6ffaeeafc53..a0f2e0cefbb 100644
--- a/mysql-test/r/mysqlbinlog_row_minimal.result
+++ b/mysql-test/r/mysqlbinlog_row_minimal.result
@@ -214,39 +214,36 @@ BEGIN
 # at 1997
 #<date> server id 1  end_log_pos 2049 	Table_map: `test`.`t2` mapped to number 31
 # at 2049
-#<date> server id 1  end_log_pos 2119 	Update_rows: table id 31 flags: STMT_END_F
+#<date> server id 1  end_log_pos 2111 	Update_rows: table id 31 flags: STMT_END_F
 ### UPDATE `test`.`t2`
 ### WHERE
 ###   @1=10 /* INT meta=0 nullable=0 is_null=0 */
-###   @5=4 /* INT meta=0 nullable=1 is_null=0 */
 ### SET
 ###   @5=5 /* INT meta=0 nullable=1 is_null=0 */
 ### UPDATE `test`.`t2`
 ### WHERE
 ###   @1=11 /* INT meta=0 nullable=0 is_null=0 */
-###   @5=4 /* INT meta=0 nullable=1 is_null=0 */
 ### SET
 ###   @5=5 /* INT meta=0 nullable=1 is_null=0 */
 ### UPDATE `test`.`t2`
 ### WHERE
 ###   @1=12 /* INT meta=0 nullable=0 is_null=0 */
-###   @5=NULL /* INT meta=0 nullable=1 is_null=1 */
 ### SET
 ###   @5=5 /* INT meta=0 nullable=1 is_null=0 */
-# at 2119
-#<date> server id 1  end_log_pos 2188 	Query	thread_id=4	exec_time=x	error_code=0
+# at 2111
+#<date> server id 1  end_log_pos 2180 	Query	thread_id=4	exec_time=x	error_code=0
 SET TIMESTAMP=X/*!*/;
 COMMIT
 /*!*/;
-# at 2188
-#<date> server id 1  end_log_pos 2226 	GTID 0-1-9
+# at 2180
+#<date> server id 1  end_log_pos 2218 	GTID 0-1-9
 /*!100001 SET @@session.gtid_seq_no=9*//*!*/;
 BEGIN
 /*!*/;
-# at 2226
-#<date> server id 1  end_log_pos 2278 	Table_map: `test`.`t1` mapped to number 30
-# at 2278
-#<date> server id 1  end_log_pos 2328 	Delete_rows: table id 30 flags: STMT_END_F
+# at 2218
+#<date> server id 1  end_log_pos 2270 	Table_map: `test`.`t1` mapped to number 30
+# at 2270
+#<date> server id 1  end_log_pos 2320 	Delete_rows: table id 30 flags: STMT_END_F
 ### DELETE FROM `test`.`t1`
 ### WHERE
 ###   @1=10 /* INT meta=0 nullable=0 is_null=0 */
@@ -259,20 +256,20 @@ BEGIN
 ### DELETE FROM `test`.`t1`
 ### WHERE
 ###   @1=13 /* INT meta=0 nullable=0 is_null=0 */
-# at 2328
-#<date> server id 1  end_log_pos 2397 	Query	thread_id=4	exec_time=x	error_code=0
+# at 2320
+#<date> server id 1  end_log_pos 2389 	Query	thread_id=4	exec_time=x	error_code=0
 SET TIMESTAMP=X/*!*/;
 COMMIT
 /*!*/;
-# at 2397
-#<date> server id 1  end_log_pos 2435 	GTID 0-1-10
+# at 2389
+#<date> server id 1  end_log_pos 2427 	GTID 0-1-10
 /*!100001 SET @@session.gtid_seq_no=10*//*!*/;
 BEGIN
 /*!*/;
-# at 2435
-#<date> server id 1  end_log_pos 2487 	Table_map: `test`.`t2` mapped to number 31
-# at 2487
-#<date> server id 1  end_log_pos 2537 	Delete_rows: table id 31 flags: STMT_END_F
+# at 2427
+#<date> server id 1  end_log_pos 2479 	Table_map: `test`.`t2` mapped to number 31
+# at 2479
+#<date> server id 1  end_log_pos 2529 	Delete_rows: table id 31 flags: STMT_END_F
 ### DELETE FROM `test`.`t2`
 ### WHERE
 ###   @1=10 /* INT meta=0 nullable=0 is_null=0 */
@@ -285,13 +282,13 @@ BEGIN
 ### DELETE FROM `test`.`t2`
 ### WHERE
 ###   @1=13 /* INT meta=0 nullable=0 is_null=0 */
-# at 2537
-#<date> server id 1  end_log_pos 2606 	Query	thread_id=4	exec_time=x	error_code=0
+# at 2529
+#<date> server id 1  end_log_pos 2598 	Query	thread_id=4	exec_time=x	error_code=0
 SET TIMESTAMP=X/*!*/;
 COMMIT
 /*!*/;
-# at 2606
-#<date> server id 1  end_log_pos 2650 	Rotate to master-bin.000002  pos: 4
+# at 2598
+#<date> server id 1  end_log_pos 2642 	Rotate to master-bin.000002  pos: 4
 DELIMITER ;
 # End of log file
 ROLLBACK /* added by mysqlbinlog */;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 8424b4477c3..0971d4fdaaa 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -6390,6 +6390,22 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
   DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
             ((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
 
+  /**
+    Save a reference to the original read bitmaps
+    We will need this to restore the bitmaps at the end as
+    binlog_prepare_row_images() may change table->read_set.
+    table->read_set is used by pack_row and deep in
+    binlog_prepare_pending_events().
+  */
+  MY_BITMAP *old_read_set= table->read_set;
+
+  /**
+     This will remove spurious fields required during execution but
+     not needed for binlogging. This is done according to the:
+     binlog-row-image option.
+   */
+  binlog_prepare_row_images(table);
+
   size_t const before_maxlen = max_row_length(table, before_record);
   size_t const after_maxlen  = max_row_length(table, after_record);
 
@@ -6401,9 +6417,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
   uchar *after_row= row_data.slot(1);
 
   size_t const before_size= pack_row(table, table->read_set, before_row,
-                                        before_record);
+                                     before_record);
   size_t const after_size= pack_row(table, table->rpl_write_set, after_row,
-                                       after_record);
+                                    after_record);
 
   /* Ensure that all events in a GTID group are in the same cache */
   if (variables.option_bits & OPTION_GTID_BEGIN)
@@ -6431,6 +6447,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
   int error=  ev->add_row_data(before_row, before_size) ||
               ev->add_row_data(after_row, after_size);
 
+  /* restore read set for the rest of execution */
+  table->column_bitmaps_set_no_signal(old_read_set,
+                                      table->write_set);
   return error;
 
 }
diff --git a/sql/table.cc b/sql/table.cc
index ca06eee077c..31f0d255847 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6137,6 +6137,8 @@ void TABLE::mark_columns_per_binlog_row_image()
         mark_columns_used_by_index_no_reset(s->primary_key, read_set);
         /* Only write columns that have changed */
         rpl_write_set= write_set;
+        if (default_field)
+          mark_default_fields_for_write(rpl_write_set);
         break;
 
       default:
@@ -6283,7 +6285,7 @@ bool TABLE::has_default_function(bool is_update)
   Add all fields that have a default function to the table write set.
 */
 
-void TABLE::mark_default_fields_for_write()
+void TABLE::mark_default_fields_for_write(MY_BITMAP* bset)
 {
   Field **dfield_ptr, *dfield;
   enum_sql_command cmd= in_use->lex->sql_command;
@@ -6294,7 +6296,7 @@ void TABLE::mark_default_fields_for_write()
          dfield->has_insert_default_function()) ||
         ((sql_command_flags[cmd] & CF_UPDATES_DATA) &&
          dfield->has_update_default_function()))
-      bitmap_set_bit(write_set, dfield->field_index);
+      bitmap_set_bit(bset, dfield->field_index);
   }
 }
 
diff --git a/sql/table.h b/sql/table.h
index ca32234579f..d57eeb559a1 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1353,7 +1353,11 @@ struct TABLE
   void mark_columns_per_binlog_row_image(void);
   bool mark_virtual_col(Field *field);
   void mark_virtual_columns_for_write(bool insert_fl);
-  void mark_default_fields_for_write();
+  void mark_default_fields_for_write(MY_BITMAP* bset);
+  inline void mark_default_fields_for_write()
+  {
+    mark_default_fields_for_write(write_set);
+  }
   bool has_default_function(bool is_update);
   inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
                                  MY_BITMAP *write_set_arg)


More information about the commits mailing list