summaryrefslogtreecommitdiff
path: root/sql/log_event.h
diff options
context:
space:
mode:
authorunknown <mats@kindahl-laptop.dnsalias.net>2007-10-20 18:19:55 +0200
committerunknown <mats@kindahl-laptop.dnsalias.net>2007-10-20 18:19:55 +0200
commit0b1c0f3173cd14181ece774cdbbf68dddedf35a7 (patch)
tree67b8c0cdc0b3f7505963dd948bda591a8175e8e0 /sql/log_event.h
parent3f284594be3988a8e24d579444033f3884b8ead5 (diff)
downloadmariadb-git-0b1c0f3173cd14181ece774cdbbf68dddedf35a7.tar.gz
Bug#31702 (Missing row on slave causes assertion failure under row-based replication):
When replicating an update pair (before image, after image) under row-based replication, and the before image is not found on the slave, the after image was not discared, and was hence read as a before image for the next row. Eventually, this lead to an after image being read outside the block of rows in the event, causing an assertion to fire. This patch fixes this by reading the after image in the event that the row was not found on the slave, adds some extra debug assertion to catch future errors earlier, and also adds a few non-debug checks to prevent reading outside the block of the event. include/my_base.h: Adding error code HA_ERR_CORRUPT_EVENT. mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result: Result change. mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test: Adding test to try to use row-based replication to replicate an update of a row that doesn't exist on the slave. We should get an apropriate error and the slave should stop. sql/log_event.cc: Adding debug printouts. Adding code to Update_rows_log_event::do_exec_row() so that the after image is read (and ignored) in the event of an error in finding the row. This is necessary so that the second pair of images is read correctly for the next update pair. Changing logic for ignoring errors to not include update events, since a "key not found" error or a "record changed" error is not idempotent for updates, just for deletes and inserts. sql/log_event.h: Adding debug assertions to check that row reading is within the events block of rows.
Diffstat (limited to 'sql/log_event.h')
-rw-r--r--sql/log_event.h24
1 files changed, 22 insertions, 2 deletions
diff --git a/sql/log_event.h b/sql/log_event.h
index 05d4c70042f..226ebc02712 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -37,6 +37,23 @@
#include "rpl_reporting.h"
#endif
+/**
+ Either assert or return an error.
+
+ In debug build, the condition will be checked, but in non-debug
+ builds, the error code given will be returned instead.
+
+ @param COND Condition to check
+ @param ERRNO Error number to return in non-debug builds
+*/
+#ifdef DBUG_OFF
+#define ASSERT_OR_RETURN_ERROR(COND, ERRNO) \
+ do { if (!(COND)) return ERRNO; } while (0)
+#else
+#define ASSERT_OR_RETURN_ERROR(COND, ERRNO) \
+ DBUG_ASSERT(COND)
+#endif
+
#define LOG_READ_EOF -1
#define LOG_READ_BOGUS -2
#define LOG_READ_IO -3
@@ -2316,8 +2333,11 @@ protected:
int unpack_current_row(const Relay_log_info *const rli)
{
DBUG_ASSERT(m_table);
- return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
- &m_curr_row_end, &m_master_reclength);
+ ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT);
+ int const result= ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols,
+ &m_curr_row_end, &m_master_reclength);
+ ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
+ return result;
}
#endif