summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2015-05-29 17:19:53 +0300
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2015-06-22 10:35:48 +0300
commitd1634c66ea85a7388ac54799613feb30e8733848 (patch)
treea9fee95a6fc87b96c27f303fe9119d9b3904dd51
parent563e35ad27ac315548e47b40c72b5ec2e4bc9250 (diff)
downloadmariadb-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.cc21
-rw-r--r--sql/log_event.h9
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/rpl_record.cc10
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/table.cc2
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");