diff options
-rw-r--r-- | mysql-test/suite/versioning/r/rpl.result | 24 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/rpl.test | 33 | ||||
-rw-r--r-- | sql/log_event_server.cc | 21 |
3 files changed, 72 insertions, 6 deletions
diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result index a6ac9aad3ca..66fcbcb3925 100644 --- a/mysql-test/suite/versioning/r/rpl.result +++ b/mysql-test/suite/versioning/r/rpl.result @@ -455,4 +455,28 @@ a check_row_ts(rs,re) set sql_mode=default; connection master; drop tables t1, t2, t3; +# check versioned -> versioned replication without any keys on duplicate records +connection master; +create table t1 (a INT) with system versioning; +insert into t1 values (1); +insert into t1 values (1); +delete from t1; +connection slave; +include/diff_tables.inc [master:test.t1,slave:test.t1] +connection master; +drop table t1; +connection slave; +# check unversioned -> versioned replication with non-unique keys on duplicate records +connection master; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)); +connection slave; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)) with system versioning; +connection master; +insert into t1 values (1,1); +insert into t1 values (1,1); +delete from t1; +connection slave; +include/diff_tables.inc [master:test.t1,slave:test.t1] +connection master; +drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl.test b/mysql-test/suite/versioning/t/rpl.test index 16e6af75dba..19f096496fa 100644 --- a/mysql-test/suite/versioning/t/rpl.test +++ b/mysql-test/suite/versioning/t/rpl.test @@ -353,4 +353,37 @@ connection master; drop tables t1, t2, t3; --source suite/versioning/common_finish.inc +# +# MDEV-30430: Enabling system versioning on tables without primary key breaks replication +# Note that bugs are only present with row binlog format +# +--echo # check versioned -> versioned replication without any keys on duplicate records +connection master; +create table t1 (a INT) with system versioning; +insert into t1 values (1); +insert into t1 values (1); +delete from t1; +sync_slave_with_master; +--let $diff_tables= master:test.t1,slave:test.t1 +--source include/diff_tables.inc +connection master; +drop table t1; +sync_slave_with_master; + +--echo # check unversioned -> versioned replication with non-unique keys on duplicate records +connection master; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)); +connection slave; +set statement sql_log_bin=0 for create table t1 (a INT NOT NULL, b INT, INDEX(a,b)) with system versioning; +connection master; +insert into t1 values (1,1); +insert into t1 values (1,1); +delete from t1; +sync_slave_with_master; +--let $diff_tables= master:test.t1,slave:test.t1 +--source include/diff_tables.inc + +connection master; +drop table t1; + --source include/rpl_end.inc diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index a0126d0e338..5daf30b3016 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -7970,7 +7970,7 @@ uint8 Write_rows_log_event::get_trg_event_map() Returns TRUE if different. */ -static bool record_compare(TABLE *table) +static bool record_compare(TABLE *table, bool vers_from_plain= false) { bool result= FALSE; /** @@ -8003,10 +8003,19 @@ static bool record_compare(TABLE *table) /* Compare fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if (table->versioned() && (*ptr)->vers_sys_field()) - { + /* + If the table is versioned, don't compare using the version if there is a + primary key. If there isn't a primary key, we need the version to + identify the correct record if there are duplicate rows in the data set. + However, if the primary server is unversioned (vers_from_plain is true), + then we implicitly use row_end as the primary key on our side. This is + because the implicit row_end value will be set to the maximum value for + the latest row update (which is what we care about). + */ + if (table->versioned() && (*ptr)->vers_sys_field() && + (table->s->primary_key < MAX_KEY || + (vers_from_plain && table->vers_start_field() == (*ptr)))) continue; - } /** We only compare field contents that are not null. NULL fields (i.e., their null bits) were compared @@ -8400,7 +8409,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) /* We use this to test that the correct key is used in test cases. */ DBUG_EXECUTE_IF("slave_crash_if_index_scan", abort();); - while (record_compare(table)) + while (record_compare(table, m_vers_from_plain)) { while ((error= table->file->ha_index_next(table->record[0]))) { @@ -8453,7 +8462,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) goto end; } } - while (record_compare(table)); + while (record_compare(table, m_vers_from_plain)); /* Note: above record_compare will take into accout all record fields |