mariadb/mysql-test/suite/versioning/t/rpl_row.test
Aleksey Midenkov 9286c9e647 MDEV-28254 Wrong position for row_start, row_end after adding column to implicit versioned table
Implicit system-versioned table does not contain system fields in SHOW
CREATE. Therefore after mysqldump recovery such table has system
fields in the last place in frm image. The original table meanwhile
does not guarantee these system fields on last place because adding
new fields via ALTER TABLE places them last. Thus the order of fields
may be different between master and slave, so row-based replication
may fail.

To fix this on ALTER TABLE we now place system-invisible fields always
last in frm image. If the table was created via old revision and has
an incorrect order of fields it can be fixed via any copy operation of
ALTER TABLE, f.ex.:

  ALTER TABLE t1 FORCE;

To check the order of fields in frm file one can use hexdump:

  hexdump -C t1.frm

Note, the replication fails only when all 3 conditions are met:

  1. row-based or mixed mode replication;
  2. table has new fields added via ALTER TABLE;
  3. table was rebuilt on some, but not all nodes via mysqldump image.

Otherwise it will operate properly even with incorrect order of
fields.
2022-04-22 15:49:37 +03:00

59 lines
1.8 KiB
Text

--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--source include/have_innodb.inc
--echo # MDEV-16252: MINIMAL binlog_row_image does not work for versioned tables
set @old_row_image= @@binlog_row_image;
set binlog_row_image= minimal;
create or replace table t1 (pk int, i int, primary key(pk))
with system versioning;
insert into t1 values (1,10),(2,20);
update t1 set i = 0;
--sync_slave_with_master
--connection master
drop table t1;
set binlog_row_image= @old_row_image;
--echo #
--echo # MDEV-28254 Wrong position for row_start, row_end after adding column
--echo # to implicit versioned table
--echo #
--let TMP= $MYSQLTEST_VARDIR/tmp
--let $MYSQLD_DATADIR= `select @@datadir`
set @@system_versioning_alter_history= keep;
set @@session.time_zone='+00:00';
create table t1 (x int) with system versioning engine innodb;
alter table t1 add column y int, algorithm=inplace;
check table t1;
--exec $MYSQL_DUMP --databases test > $TMP/dump.sql
--sync_slave_with_master
drop table t1;
--exec $MYSQL_SLAVE test < $TMP/dump.sql
show create table t1;
--connection master
set timestamp= 12345;
--let $start_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
insert t1 values (1, 1);
select *, unix_timestamp(row_start) as row_start, unix_timestamp(row_end) as row_end from t1;
--let $stop_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
set timestamp= default;
# NOTE: pipe grep is not Windows-compatible
--let grep_file= $TMP/out.txt
--let grep_regex= ^###
--exec $MYSQL_BINLOG -v -j $start_pos --stop-position=$stop_pos -o 3 $MYSQLD_DATADIR/master-bin.000001 > $grep_file
--source include/grep.inc
--sync_slave_with_master
select * from t1;
--connection master
drop table t1;
--remove_files_wildcard $TMP *.txt
--remove_files_wildcard $TMP *.sql
--source include/rpl_end.inc