diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2015-05-29 17:19:53 +0300 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2015-06-22 10:35:48 +0300 |
commit | d1634c66ea85a7388ac54799613feb30e8733848 (patch) | |
tree | a9fee95a6fc87b96c27f303fe9119d9b3904dd51 | |
parent | 563e35ad27ac315548e47b40c72b5ec2e4bc9250 (diff) | |
download | mariadb-git-d1634c66ea85a7388ac54799613feb30e8733848.tar.gz |
[MDEV-6877] Change replication event loop to account for empty eventsbb-10.1-binlog_row_image
When writing rows with a minimal row image, it is possible to receive
empty events. In that case m_curr_row and m_rows_end are the same,
however the event implies an insert into the table with the default
values associated for that table.
-rw-r--r-- | sql/log_event.cc | 21 | ||||
-rw-r--r-- | sql/log_event.h | 9 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/rpl_record.cc | 10 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/table.cc | 2 |
6 files changed, 31 insertions, 14 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index c86c59ebd5b..be54181a8ef 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9901,7 +9901,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) rgi->set_row_stmt_start_timestamp(); THD_STAGE_INFO(thd, stage_executing); - while (error == 0 && m_curr_row < m_rows_end) + do { /* in_use can have been set to NULL in close_tables_for_reopen */ THD* old_thd= table->in_use; @@ -9949,18 +9949,14 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) if (!m_curr_row_end && !error) error= unpack_current_row(rgi); - - // 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_end <= m_rows_end); - + m_curr_row= m_curr_row_end; if (error == 0 && !transactional_table) thd->transaction.all.modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table= TRUE; } // row processing loop + while (error == 0 && (m_curr_row != m_rows_end)); /* Restore the sql_mode after the rows event is processed. @@ -11389,7 +11385,16 @@ Rows_log_event::write_row(rpl_group_info *rgi, 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); + /* 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 */ + DBUG_ASSERT(!(m_curr_row > m_curr_row_end)); + ulong estimated_rows= 0; + if (m_curr_row < m_curr_row_end) + estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row); + else if (m_curr_row == m_curr_row_end) + estimated_rows= 1; + table->file->ha_start_bulk_insert(estimated_rows); } diff --git a/sql/log_event.h b/sql/log_event.h index d602c704828..95b68e627ff 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -4409,20 +4409,23 @@ protected: int find_row(rpl_group_info *); int write_row(rpl_group_info *, const bool); - // Unpack the current row into m_table->record[0] + // Unpack the current row into m_table->record[0], but with + // a different columns bitmap. int unpack_current_row(rpl_group_info *rgi, MY_BITMAP const *cols) { DBUG_ASSERT(m_table); - 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); return ::unpack_row(rgi, m_table, m_width, m_curr_row, cols, &m_curr_row_end, &m_master_reclength, m_rows_end); } + + // Unpack the current row into m_table->record[0] int unpack_current_row(rpl_group_info *rgi) { DBUG_ASSERT(m_table); - 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); return ::unpack_row(rgi, m_table, m_width, m_curr_row, &m_cols, &m_curr_row_end, &m_master_reclength, m_rows_end); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 50f6984a646..85dbb4a935b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7550,7 +7550,6 @@ struct my_option my_long_options[]= MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"), MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"), MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"), - MYSQL_TO_BE_IMPLEMENTED_OPTION("binlog-row-image"), MYSQL_TO_BE_IMPLEMENTED_OPTION("explicit-defaults-for-timestamp"), MYSQL_COMPATIBILITY_OPTION("master-info-repository"), MYSQL_COMPATIBILITY_OPTION("relay-log-info-repository"), diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 8c694602c74..feab97fd589 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -209,6 +209,16 @@ unpack_row(rpl_group_info *rgi, Field **field_ptr; Field **const end_ptr= begin_ptr + colcnt; + if (bitmap_is_clear_all(cols)) + { + /** + There was no data sent from the master, so there is + nothing to unpack. + */ + *current_row_end= pack_ptr; + *master_reclength= 0; + DBUG_RETURN(error); + } DBUG_ASSERT(null_ptr < row_data + master_null_byte_count); // Mask to mask out the correct bit among the null bits diff --git a/sql/sql_class.h b/sql/sql_class.h index b422b0b7319..5744c9826b6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2130,7 +2130,7 @@ public: const uchar *buf); int binlog_update_row(TABLE* table, bool is_transactional, const uchar *old_data, const uchar *new_data); - void binlog_prepare_row_images(TABLE* table); + static void binlog_prepare_row_images(TABLE* table); void set_server_id(uint32 sid) { variables.server_id = sid; } diff --git a/sql/table.cc b/sql/table.cc index 7a1248b4144..9df5b05c04d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5975,7 +5975,7 @@ void TABLE::mark_columns_needed_for_insert() the read_set at binlogging time (for those cases that we only want to log a PK and we needed other fields for execution). - */ +*/ void TABLE::mark_columns_per_binlog_row_image() { DBUG_ENTER("mark_columns_per_binlog_row_image"); |