From dd7d169593f70fd6894ffadc5ce99bf9cf4907a2 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 14 Feb 2018 17:02:11 +0300 Subject: [PATCH] MDEV-14767 system_versioning_alter_history breaks ALTER replication Vers SQL: force VERS_ALTER_HISTORY_KEEP behavior in the slave thread --- mysql-test/suite/versioning/r/rpl.result | 42 ++++++++++++++++++++++++ mysql-test/suite/versioning/t/rpl.test | 35 ++++++++++++++++++-- sql/sql_table.cc | 3 +- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/versioning/r/rpl.result b/mysql-test/suite/versioning/r/rpl.result index b91c8fd33c8..b5845a2d0b2 100644 --- a/mysql-test/suite/versioning/r/rpl.result +++ b/mysql-test/suite/versioning/r/rpl.result @@ -36,6 +36,7 @@ x 1 3 2 +# check unversioned -> versioned replication connection master; create or replace table t1 (x int primary key); connection slave; @@ -68,6 +69,7 @@ select * from t1 for system_time all; x 1 2 +# same thing (UPDATE, DELETE), but without PK connection master; create or replace table t1 (x int); connection slave; @@ -92,6 +94,7 @@ select * from t1 for system_time all; x 2 1 +# multi-update connection master; create or replace table t1 (x int) with system versioning; create or replace table t2 (x int) with system versioning; @@ -113,6 +116,45 @@ select * from t2 for system_time all; x 22 2 +# MDEV-14767 system_versioning_alter_history breaks ALTER replication +## Case 1: KEEP on the master, ALTER will work on the slave +connection master; +create or replace table t1 (a int) with system versioning; +set system_versioning_alter_history= KEEP; +alter table t1 add column b int; +connection slave; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +## Case 2: ERROR on the master, it'll fail on the master, the slave won't see it +connection master; +set system_versioning_alter_history= ERROR; +alter table t1 drop column b; +ERROR HY000: Not allowed for system-versioned `test`.`t1`. Change @@system_versioning_alter_history to proceed with ALTER. +connection slave; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +## Case 3: table is not versioned on the master, ALTER will work on the slave +connection master; +create or replace table t1 (a int); +connection slave; +create or replace table t1 (a int) with system versioning; +connection master; +alter table t1 add column b int; +connection slave; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING connection master; drop table t1, t2; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl.test b/mysql-test/suite/versioning/t/rpl.test index 342d58626b7..2f95fd1928c 100644 --- a/mysql-test/suite/versioning/t/rpl.test +++ b/mysql-test/suite/versioning/t/rpl.test @@ -45,7 +45,7 @@ sync_slave_with_master; select * from t1; select * from t1 for system_time all; -# check unversioned -> versioned replication +--echo # check unversioned -> versioned replication connection master; create or replace table t1 (x int primary key); sync_slave_with_master; @@ -69,7 +69,7 @@ sync_slave_with_master; select * from t1; select * from t1 for system_time all; -# same thing (UPDATE, DELETE), but without PK +--echo # same thing (UPDATE, DELETE), but without PK connection master; create or replace table t1 (x int); sync_slave_with_master; @@ -88,7 +88,7 @@ sync_slave_with_master; select * from t1; select * from t1 for system_time all; -# multi-update +--echo # multi-update connection master; create or replace table t1 (x int) with system versioning; create or replace table t2 (x int) with system versioning; @@ -101,6 +101,35 @@ select * from t2; select * from t1 for system_time all; select * from t2 for system_time all; +--echo # MDEV-14767 system_versioning_alter_history breaks ALTER replication +--echo ## Case 1: KEEP on the master, ALTER will work on the slave +connection master; +create or replace table t1 (a int) with system versioning; +set system_versioning_alter_history= KEEP; +alter table t1 add column b int; +sync_slave_with_master; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t1; + +--echo ## Case 2: ERROR on the master, it'll fail on the master, the slave won't see it +connection master; +set system_versioning_alter_history= ERROR; +--error ER_VERS_ALTER_NOT_ALLOWED +alter table t1 drop column b; +sync_slave_with_master; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t1; + +--echo ## Case 3: table is not versioned on the master, ALTER will work on the slave +connection master; +create or replace table t1 (a int); +sync_slave_with_master; +create or replace table t1 (a int) with system versioning; +connection master; +alter table t1 add column b int; +sync_slave_with_master; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t1; connection master; drop table t1, t2; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2bdd932706b..e3da436aebd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9196,7 +9196,8 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, const LEX_CSTRING *n { vers_survival_mod= alter_info->data_modifying() || alter_info->partition_modifying(); } - else if (vers_data_mod && thd->variables.vers_alter_history == VERS_ALTER_HISTORY_ERROR) + else if (vers_data_mod && !thd->slave_thread && + thd->variables.vers_alter_history == VERS_ALTER_HISTORY_ERROR) { my_error(ER_VERS_ALTER_NOT_ALLOWED, MYF(0), table_list->db.str, table_list->table_name.str);