BUG#31583 (5.1-telco-6.1 -> 5.1.22. Slave returns Error in unknown event):

In the patch for BUG#21842, the code for handling old rows events were
refactored.  There were a bug in the refactored code (possibly introduced
after the patch for BUG#21842) that caused caused the refactored old events
to read a columns bitmap after image even though there is no such bitmap
for old events. As a result, the reading got out of sync, and started reading
invalid data.

This patch removes all trace of the after image column bitmap from the refactored
old events and removes functions that are no longer needed because they are empty. 
parent 60880ec8
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE TABLE t1 ( a INT, b INT DEFAULT -3 );
INSERT INTO t1 VALUES (1, DEFAULT);
UPDATE t1 SET a = 3;
SELECT * FROM t1 ORDER BY a;
a b
3 -3
SELECT * FROM t1 ORDER BY a;
a b
3 -3
#
# BUG#31583: 5.1-telco-6.1 -> 5.1.22. Slave returns Error in unknown event
# This is a problem for any update statement replicating from an old
# server to a new server. The bug consisted of a new slave trying to
# read two column bitmaps, but there is only one available in the old
# format.
# This test case should be executed replicating from an old server to
# a new server, so make sure you have one handy.
source include/master-slave.inc;
CREATE TABLE t1 ( a INT, b INT DEFAULT -3 );
INSERT INTO t1 VALUES (1, DEFAULT);
UPDATE t1 SET a = 3;
SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
SELECT * FROM t1 ORDER BY a;
...@@ -490,6 +490,9 @@ const char* Log_event::get_type_str() ...@@ -490,6 +490,9 @@ const char* Log_event::get_type_str()
case USER_VAR_EVENT: return "User var"; case USER_VAR_EVENT: return "User var";
case FORMAT_DESCRIPTION_EVENT: return "Format_desc"; case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
case TABLE_MAP_EVENT: return "Table_map"; case TABLE_MAP_EVENT: return "Table_map";
case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old";
case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old";
case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old";
case WRITE_ROWS_EVENT: return "Write_rows"; case WRITE_ROWS_EVENT: return "Write_rows";
case UPDATE_ROWS_EVENT: return "Update_rows"; case UPDATE_ROWS_EVENT: return "Update_rows";
case DELETE_ROWS_EVENT: return "Delete_rows"; case DELETE_ROWS_EVENT: return "Delete_rows";
...@@ -1015,6 +1018,8 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, ...@@ -1015,6 +1018,8 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
DBUG_ENTER("Log_event::read_log_event(char*,...)"); DBUG_ENTER("Log_event::read_log_event(char*,...)");
DBUG_ASSERT(description_event != 0); DBUG_ASSERT(description_event != 0);
DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version)); DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version));
DBUG_DUMP("data", (unsigned char*) buf, event_len);
/* Check the integrity */ /* Check the integrity */
if (event_len < EVENT_LEN_OFFSET || if (event_len < EVENT_LEN_OFFSET ||
buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT || buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT ||
......
...@@ -1317,6 +1317,7 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len, ...@@ -1317,6 +1317,7 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len,
post_header_len)); post_header_len));
const char *post_start= buf + common_header_len; const char *post_start= buf + common_header_len;
DBUG_DUMP("post_header", (uchar*) post_start, post_header_len);
post_start+= RW_MAPID_OFFSET; post_start+= RW_MAPID_OFFSET;
if (post_header_len == 6) if (post_header_len == 6)
{ {
...@@ -1358,38 +1359,11 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len, ...@@ -1358,38 +1359,11 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */
if (event_type == PRE_GA_UPDATE_ROWS_EVENT)
{
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
/* if bitmap_init fails, caught in is_valid() */
if (likely(!bitmap_init(&m_cols_ai,
m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
m_width,
false)))
{
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8);
create_last_word_mask(&m_cols_ai);
ptr_after_width+= (m_width + 7) / 8;
DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
no_bytes_in_map(&m_cols_ai));
}
else
{
// Needed because bitmap_init() does not set it to null on failure
m_cols_ai.bitmap= 0;
DBUG_VOID_RETURN;
}
}
const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;
size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf);
DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu", DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu",
m_table_id, m_flags, m_width, (ulong) data_size)); m_table_id, m_flags, m_width, (ulong) data_size));
DBUG_DUMP("rows_data", (uchar*) ptr_rows_data, data_size);
m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME)); m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
if (likely((bool)m_rows_buf)) if (likely((bool)m_rows_buf))
...@@ -1419,22 +1393,16 @@ Old_rows_log_event::~Old_rows_log_event() ...@@ -1419,22 +1393,16 @@ Old_rows_log_event::~Old_rows_log_event()
int Old_rows_log_event::get_data_size() int Old_rows_log_event::get_data_size()
{ {
int const type_code= get_type_code();
uchar buf[sizeof(m_width)+1]; uchar buf[sizeof(m_width)+1];
uchar *end= net_store_length(buf, (m_width + 7) / 8); uchar *end= net_store_length(buf, (m_width + 7) / 8);
DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
return 6 + no_bytes_in_map(&m_cols) + (end - buf) + return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
(type_code == PRE_GA_UPDATE_ROWS_EVENT ? no_bytes_in_map(&m_cols_ai) : 0) +
(m_rows_cur - m_rows_buf);); (m_rows_cur - m_rows_buf););
int data_size= ROWS_HEADER_LEN; int data_size= ROWS_HEADER_LEN;
data_size+= no_bytes_in_map(&m_cols); data_size+= no_bytes_in_map(&m_cols);
data_size+= end - buf; data_size+= end - buf;
if (type_code == PRE_GA_UPDATE_ROWS_EVENT)
data_size+= no_bytes_in_map(&m_cols_ai);
data_size+= (m_rows_cur - m_rows_buf); data_size+= (m_rows_cur - m_rows_buf);
return data_size; return data_size;
} }
...@@ -2011,16 +1979,6 @@ bool Old_rows_log_event::write_data_body(IO_CACHE*file) ...@@ -2011,16 +1979,6 @@ bool Old_rows_log_event::write_data_body(IO_CACHE*file)
DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap, res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap,
no_bytes_in_map(&m_cols)); no_bytes_in_map(&m_cols));
/*
TODO[refactor write]: Remove the "down cast" here (and elsewhere).
*/
if (get_type_code() == PRE_GA_UPDATE_ROWS_EVENT)
{
DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
no_bytes_in_map(&m_cols_ai));
res= res || my_b_safe_write(file, (uchar*) m_cols_ai.bitmap,
no_bytes_in_map(&m_cols_ai));
}
DBUG_DUMP("rows", m_rows_buf, data_size); DBUG_DUMP("rows", m_rows_buf, data_size);
res= res || my_b_safe_write(file, m_rows_buf, (size_t) data_size); res= res || my_b_safe_write(file, m_rows_buf, (size_t) data_size);
...@@ -2831,38 +2789,10 @@ Update_rows_log_event_old::Update_rows_log_event_old(THD *thd_arg, ...@@ -2831,38 +2789,10 @@ Update_rows_log_event_old::Update_rows_log_event_old(THD *thd_arg,
// This constructor should not be reached. // This constructor should not be reached.
assert(0); assert(0);
init(cols);
}
void Update_rows_log_event_old::init(MY_BITMAP const *cols)
{
/* if bitmap_init fails, caught in is_valid() */
if (likely(!bitmap_init(&m_cols_ai,
m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
m_width,
false)))
{
/* Cols can be zero if this is a dummy binrows event */
if (likely(cols != NULL))
{
memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols));
create_last_word_mask(&m_cols_ai);
}
}
} }
#endif /* !defined(MYSQL_CLIENT) */ #endif /* !defined(MYSQL_CLIENT) */
Update_rows_log_event_old::~Update_rows_log_event_old()
{
if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
m_cols_ai.bitmap= 0; // so no my_free in bitmap_free
bitmap_free(&m_cols_ai); // To pair with bitmap_init().
}
/* /*
Constructor used by slave to read the event from the binary log. Constructor used by slave to read the event from the binary log.
*/ */
......
...@@ -175,14 +175,6 @@ protected: ...@@ -175,14 +175,6 @@ protected:
ulong m_table_id; /* Table ID */ ulong m_table_id; /* Table ID */
MY_BITMAP m_cols; /* Bitmap denoting columns available */ MY_BITMAP m_cols; /* Bitmap denoting columns available */
ulong m_width; /* The width of the columns bitmap */ ulong m_width; /* The width of the columns bitmap */
/*
Bitmap for columns available in the after image, if present. These
fields are only available for Update_rows events. Observe that the
width of both the before image COLS vector and the after image
COLS vector is the same: the number of columns of the table on the
master.
*/
MY_BITMAP m_cols_ai;
ulong m_master_reclength; /* Length of record on master side */ ulong m_master_reclength; /* Length of record on master side */
...@@ -442,12 +434,8 @@ public: ...@@ -442,12 +434,8 @@ public:
Update_rows_log_event_old(THD*, TABLE*, ulong table_id, Update_rows_log_event_old(THD*, TABLE*, ulong table_id,
MY_BITMAP const *cols, MY_BITMAP const *cols,
bool is_transactional); bool is_transactional);
void init(MY_BITMAP const *cols);
#endif #endif
virtual ~Update_rows_log_event_old();
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
Update_rows_log_event_old(const char *buf, uint event_len, Update_rows_log_event_old(const char *buf, uint event_len,
const Format_description_log_event *description_event); const Format_description_log_event *description_event);
...@@ -466,11 +454,6 @@ public: ...@@ -466,11 +454,6 @@ public:
} }
#endif #endif
virtual bool is_valid() const
{
return Old_rows_log_event::is_valid() && m_cols_ai.bitmap;
}
protected: protected:
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
void print(FILE *file, PRINT_EVENT_INFO *print_event_info); void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment