From d6e0d29f84475a92e81487e032d761873db5c7c3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 24 Nov 2022 17:45:30 +0100 Subject: [PATCH] Fix write_set too * in online ALTER it must include the complete new row, note that an UPDATE should set all extra columns to their default values, as if UPDATE was completely done before the ALTER. * in rpl WRITE_ROWS_EVENT it must include all extra slave columns, but not existing columns unmarked in the m_cols (sequences do that) * in rpl UPDATE/DELETE events it should follow m_cols_ai also: default values must be updated for WRITE_ROWS_EVENT and for UPDATE/DELETE in the online ALTER mode, see above. Update the result file accordingly. Extend bitmap_copy() to support arguments of different lengths --- .../rpl/r/rpl_alter_extra_persistent.result | 14 ++++---- mysys/my_bitmap.c | 9 +++-- sql/log_event_server.cc | 33 ++++++++----------- sql/rpl_record.cc | 3 +- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result index acfcf02eacd..85d395ffea0 100644 --- a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result +++ b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result @@ -62,12 +62,12 @@ a connection slave; select * from t1 order by a; a z1 z2 z3 -11 12 13 13 -12 13 14 14 -13 14 15 15 -14 15 16 16 -15 16 17 17 -16 17 18 18 +11 12 13 3 +12 13 14 4 +13 14 15 5 +14 15 16 6 +15 16 17 7 +16 17 18 8 connection master; update t1 set a = a-10; select * from t1 order by a; @@ -147,7 +147,7 @@ a z1 z2 z3 4 5 6 6 5 6 7 7 6 7 8 8 -13 14 15 15 +13 14 15 5 connection master; update t1 set a = a - 10 where a = 13; select * from t1 order by a; diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 9893c7e4a58..229e512dc1e 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -576,14 +576,17 @@ uint bitmap_bits_set(const MY_BITMAP *map) void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + uint len= no_words_in_map(map), len2 = no_words_in_map(map2); DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map->n_bits == map2->n_bits); - end= map->last_word_ptr; - while (to <= end) + end= to + MY_MIN(len, len2 - 1); + while (to < end) *to++ = *from++; + + if (len2 <= len) + *to= (*from & ~map2->last_word_mask) | (*to & map2->last_word_mask); } diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index c5ee2ac991c..ab73944c896 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5061,6 +5061,9 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) if (m_width == table->s->fields && bitmap_is_set_all(&m_cols)) set_flags(COMPLETE_ROWS_F); + Rpl_table_data rpl_data{}; + if (rgi) rgi->get_table_data(table, &rpl_data); + /* Set tables write and read sets. @@ -5074,37 +5077,29 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) DBUG_PRINT_BITSET("debug", "Setting table's read_set from: %s", &m_cols); bitmap_set_all(table->read_set); - if (get_general_type_code() == DELETE_ROWS_EVENT || - get_general_type_code() == UPDATE_ROWS_EVENT) + bitmap_set_all(table->write_set); + table->rpl_write_set= table->write_set; + + if (rpl_data.copy_fields) + /* always full rows, all bits set */; + else + if (get_general_type_code() == WRITE_ROWS_EVENT) + bitmap_copy(table->write_set, &m_cols); // for sequences + else { bitmap_intersect(table->read_set,&m_cols); + bitmap_intersect(table->write_set, &m_cols_ai); table->mark_columns_per_binlog_row_image(); if (table->vfield) table->mark_virtual_columns_for_write(0); } - bitmap_set_all(table->write_set); - table->rpl_write_set= table->write_set; - - /* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */ - MY_BITMAP *after_image= ((get_general_type_code() == UPDATE_ROWS_EVENT) ? - &m_cols_ai : &m_cols); - bitmap_intersect(table->write_set, after_image); - if (table->versioned()) { bitmap_set_bit(table->write_set, table->s->vers.start_fieldno); bitmap_set_bit(table->write_set, table->s->vers.end_fieldno); } - /* Mark extra replica columns for write */ - for (Field **field_ptr= table->field; *field_ptr; ++field_ptr) - { - Field *field= *field_ptr; - if (field->field_index >= m_cols.n_bits && field->stored_in_db()) - bitmap_set_bit(table->write_set, field->field_index); - } - this->slave_exec_mode= slave_exec_mode_options; // fix the mode // Do event specific preparations @@ -5118,8 +5113,6 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) extra columns on the slave. In that case, do not force MODE_NO_AUTO_VALUE_ON_ZERO. */ - Rpl_table_data rpl_data{}; - if (rgi) rgi->get_table_data(table, &rpl_data); sql_mode_t saved_sql_mode= thd->variables.sql_mode; if (!is_auto_inc_in_extra_columns()) thd->variables.sql_mode= (rpl_data.copy_fields ? saved_sql_mode : 0) diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 2f9723c9b29..9d72e25b7df 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -389,7 +389,8 @@ int unpack_row(rpl_group_info *rgi, TABLE *table, uint const colcnt, } } - if (table->default_field) + if (table->default_field && (rpl_data.is_online_alter() || + LOG_EVENT_IS_WRITE_ROW(rgi->current_event->get_type_code()))) { error= table->update_default_fields(table->in_use->lex->ignore); if (unlikely(error))