Commit eca01720 authored by mats@kindahl-laptop.dnsalias.net's avatar mats@kindahl-laptop.dnsalias.net
Browse files

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
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
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
+21 −0
Original line number Diff line number Diff line
#
# 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;
+5 −0
Original line number Diff line number Diff line
@@ -490,6 +490,9 @@ const char* Log_event::get_type_str()
  case USER_VAR_EVENT: return "User var";
  case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
  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 UPDATE_ROWS_EVENT: return "Update_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,
  DBUG_ENTER("Log_event::read_log_event(char*,...)");
  DBUG_ASSERT(description_event != 0);
  DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version));
  DBUG_DUMP("data", (unsigned char*) buf, event_len);

  /* Check the integrity */
  if (event_len < EVENT_LEN_OFFSET ||
      buf[EVENT_TYPE_OFFSET] >= ENUM_END_EVENT ||
+3 −73
Original line number Diff line number Diff line
@@ -1317,6 +1317,7 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len,
		      post_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;
  if (post_header_len == 6)
  {
@@ -1358,38 +1359,11 @@ Old_rows_log_event::Old_rows_log_event(const char *buf, uint event_len,
    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;

  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",
                     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));
  if (likely((bool)m_rows_buf))
@@ -1419,22 +1393,16 @@ Old_rows_log_event::~Old_rows_log_event()

int Old_rows_log_event::get_data_size()
{
  int const type_code= get_type_code();

  uchar buf[sizeof(m_width)+1];
  uchar *end= net_store_length(buf, (m_width + 7) / 8);

  DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
                  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););
  int data_size= ROWS_HEADER_LEN;
  data_size+= no_bytes_in_map(&m_cols);
  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);
  return data_size;
}
@@ -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));
  res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap,
                              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);
  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,

  // This constructor should not be reached.
  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) */


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.
 */
+0 −17
Original line number Diff line number Diff line
@@ -175,14 +175,6 @@ class Old_rows_log_event : public Log_event
  ulong       m_table_id;	/* Table ID */
  MY_BITMAP   m_cols;		/* Bitmap denoting columns available */
  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 */

@@ -442,12 +434,8 @@ class Update_rows_log_event_old : public Old_rows_log_event
  Update_rows_log_event_old(THD*, TABLE*, ulong table_id,
                            MY_BITMAP const *cols,
                            bool is_transactional);

  void init(MY_BITMAP const *cols);
#endif

  virtual ~Update_rows_log_event_old();

#ifdef HAVE_REPLICATION
  Update_rows_log_event_old(const char *buf, uint event_len,
                            const Format_description_log_event *description_event);
@@ -466,11 +454,6 @@ class Update_rows_log_event_old : public Old_rows_log_event
  }
#endif

  virtual bool is_valid() const
  {
    return Old_rows_log_event::is_valid() && m_cols_ai.bitmap;
  }

protected:
#ifdef MYSQL_CLIENT
  void print(FILE *file, PRINT_EVENT_INFO *print_event_info);