Skip to content

Commit

Permalink
Fix recalculation of vcols in binlog_row_image=minimal
Browse files Browse the repository at this point in the history
unpack_row() must calculate all stored and indexed vcols
(in fill_extra_persistent_columns()).

Also Update and Delete row events must mark in read_set
all columns needed for calculating all stored and indexed vcols.

If it's done properly in do_apply_event(), it no longer needs
to be repeated per row.
  • Loading branch information
vuvova committed Aug 15, 2023
1 parent e499b25 commit 9545eb9
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 17 deletions.
46 changes: 46 additions & 0 deletions mysql-test/suite/rpl/r/rpl_extra_col_slave_minimal.result
@@ -0,0 +1,46 @@
include/master-slave.inc
[connection master]
set binlog_row_image=minimal;
connection slave;
stop slave;
set global binlog_row_image=minimal;
include/reset_slave.inc
create table t1 (
a int key, b blob, c char(5),
d char(10) as (concat(trim(c), '-U')) unique,
e char(10) as (concat('S', b)) stored) engine=innodb;
connection master;
create table t1 (a int primary key, b blob, c char(5)) engine=innodb;
reset master;
connection slave;
start slave;
connection master;
set timestamp=unix_timestamp('2010-10-10 10:10:10');
insert t1 values (1,'.','Kyle'),(2,'?','JOE'),(3,'!','QA'), (4, '$', '4TH');
update t1 set c='UPD' where a=3;
update t1 set b='#' where a=2;
delete from t1 where a=4;
select * from t1;
a b c
1 . Kyle
2 # JOE
3 ! UPD
connection slave;
select * from t1;
a b c d e
1 . Kyle Kyle-U S.
2 # JOE JOE-U S#
3 ! UPD UPD-U S!
select d from t1;
d
JOE-U
Kyle-U
UPD-U
select * from t1 where d='JOE-U';
a b c d e
2 # JOE JOE-U S#
connection master;
drop table t1;
connection slave;
set global binlog_row_image=full;
include/rpl_end.inc
44 changes: 44 additions & 0 deletions mysql-test/suite/rpl/t/rpl_extra_col_slave_minimal.test
@@ -0,0 +1,44 @@
--source include/have_binlog_format_row.inc
--source include/have_innodb.inc
--source include/master-slave.inc

set binlog_row_image=minimal;

connection slave;
stop slave;
set global binlog_row_image=minimal;
--source include/reset_slave.inc

create table t1 (
a int key, b blob, c char(5),
d char(10) as (concat(trim(c), '-U')) unique,
e char(10) as (concat('S', b)) stored) engine=innodb;

connection master;
create table t1 (a int primary key, b blob, c char(5)) engine=innodb;
reset master;

connection slave;
start slave;

connection master;
set timestamp=unix_timestamp('2010-10-10 10:10:10');
insert t1 values (1,'.','Kyle'),(2,'?','JOE'),(3,'!','QA'), (4, '$', '4TH');
update t1 set c='UPD' where a=3;
update t1 set b='#' where a=2;
delete from t1 where a=4;
--sorted_result
select * from t1;
--sorted_result
sync_slave_with_master;
--sorted_result
select * from t1;
select d from t1; # no --sorted_result here, this must be KEYREAD, so must be sorted
select * from t1 where d='JOE-U';

connection master;
drop table t1;
sync_slave_with_master;
set global binlog_row_image=full;

--source include/rpl_end.inc
18 changes: 5 additions & 13 deletions sql/log_event_server.cc
Expand Up @@ -5077,7 +5077,12 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
bitmap_set_all(table->read_set);
if (get_general_type_code() == DELETE_ROWS_EVENT ||
get_general_type_code() == UPDATE_ROWS_EVENT)
{
bitmap_intersect(table->read_set,&m_cols);
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;
Expand Down Expand Up @@ -7336,12 +7341,6 @@ int Rows_log_event::find_row(rpl_group_info *rgi)

// We can't use position() - try other methods.

/*
We need to retrieve all fields
TODO: Move this out from this function to main loop
*/
table->use_all_columns();

/*
Save copy of the record in table->record[1]. It might be needed
later if linear search is used to find exact match.
Expand Down Expand Up @@ -7651,7 +7650,6 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
error= HA_ERR_GENERIC; // in case if error is not set yet
if (likely(!error))
{
m_table->mark_columns_per_binlog_row_image();
if (m_vers_from_plain && m_table->versioned(VERS_TIMESTAMP))
{
Field *end= m_table->vers_end_field();
Expand Down Expand Up @@ -7789,11 +7787,6 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
#endif /* WSREP_PROC_INFO */

thd_proc_info(thd, message);
// Temporary fix to find out why it fails [/Matz]
memcpy(m_table->read_set->bitmap, m_cols.bitmap, (m_table->read_set->n_bits + 7) / 8);
memcpy(m_table->write_set->bitmap, m_cols_ai.bitmap, (m_table->write_set->n_bits + 7) / 8);

m_table->mark_columns_per_binlog_row_image();

int error= find_row(rgi);
if (unlikely(error))
Expand Down Expand Up @@ -7884,7 +7877,6 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
error= vers_insert_history_row(m_table);
restore_record(m_table, record[2]);
}
m_table->default_column_bitmaps();

if (invoke_triggers && likely(!error) &&
unlikely(process_triggers(TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)))
Expand Down
8 changes: 5 additions & 3 deletions sql/rpl_record.cc
Expand Up @@ -143,6 +143,8 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
}
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
static int fill_extra_persistent_columns(TABLE *table, int master_cols);

/**
Unpack a row into @c table->record[0].
Expand Down Expand Up @@ -188,7 +190,6 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
@retval HA_ERR_CORRUPT_EVENT
Found error when trying to unpack fields.
*/
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
int
unpack_row(rpl_group_info *rgi,
TABLE *table, uint const colcnt,
Expand Down Expand Up @@ -490,7 +491,7 @@ int prepare_record(TABLE *const table, const uint skip, const bool check)
@param master_cols No of columns on master
@returns 0 on success
*/
int fill_extra_persistent_columns(TABLE *table, int master_cols)
static int fill_extra_persistent_columns(TABLE *table, int master_cols)
{
int error= 0;
Field **vfield_ptr, *vfield;
Expand All @@ -500,7 +501,8 @@ int fill_extra_persistent_columns(TABLE *table, int master_cols)
for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr)
{
vfield= *vfield_ptr;
if (vfield->field_index >= master_cols && vfield->stored_in_db())
if (vfield->field_index >= master_cols && (vfield->stored_in_db() ||
(vfield->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))))
{
bitmap_set_bit(table->write_set, vfield->field_index);
error= vfield->vcol_info->expr->save_in_field(vfield,0);
Expand Down
1 change: 0 additions & 1 deletion sql/rpl_record.h
Expand Up @@ -37,7 +37,6 @@ int unpack_row(rpl_group_info *rgi,

// Fill table's record[0] with default values.
int prepare_record(TABLE *const table, const uint skip, const bool check);
int fill_extra_persistent_columns(TABLE *table, int master_cols);
#endif

#endif

0 comments on commit 9545eb9

Please sign in to comment.