diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2016-12-18 17:06:43 +0000 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2017-05-05 20:36:22 +0300 |
commit | e45b85eb3e5bb905ee6f45dfb037fba1aa47266d (patch) | |
tree | b944fafd83679fda09748b816fd48b7037f04083 | |
parent | ef10ef98ab6e44737474a93daca91c22ae25fefa (diff) | |
download | mariadb-git-e45b85eb3e5bb905ee6f45dfb037fba1aa47266d.tar.gz |
SQL: replication from unversioned to versioned [fixes #94]
-rw-r--r-- | mysql-test/suite/versioning/r/rpl_row.result | 72 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/rpl_stmt.result | 72 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/rpl_test.inc | 57 | ||||
-rw-r--r-- | sql/handler.cc | 10 | ||||
-rw-r--r-- | sql/log_event.cc | 29 |
5 files changed, 232 insertions, 8 deletions
diff --git a/mysql-test/suite/versioning/r/rpl_row.result b/mysql-test/suite/versioning/r/rpl_row.result index b2d1adb7278..e193dc90ee0 100644 --- a/mysql-test/suite/versioning/r/rpl_row.result +++ b/mysql-test/suite/versioning/r/rpl_row.result @@ -37,5 +37,77 @@ x 3 2 connection master; +create or replace table t1 (x int primary key) engine = innodb; +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +1 +2 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +2 +connection master; +create or replace table t1 (x int) engine = innodb; +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +2 +1 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +2 +1 +connection master; +create or replace table t1 (x int primary key) with system versioning engine = innodb; +connection slave; +alter table t1 without system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +select * from t1 for system_time all; +x +1 +2 +connection slave; +select * from t1; +x +2 +connection master; +delete from t1; +select * from t1 for system_time all; +x +1 +2 +connection slave; +select * from t1; +x +connection master; drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/r/rpl_stmt.result b/mysql-test/suite/versioning/r/rpl_stmt.result index b2d1adb7278..e193dc90ee0 100644 --- a/mysql-test/suite/versioning/r/rpl_stmt.result +++ b/mysql-test/suite/versioning/r/rpl_stmt.result @@ -37,5 +37,77 @@ x 3 2 connection master; +create or replace table t1 (x int primary key) engine = innodb; +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +1 +2 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +1 +2 +connection master; +create or replace table t1 (x int) engine = innodb; +connection slave; +alter table t1 with system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +connection slave; +select * from t1; +x +2 +select * from t1 for system_time all; +x +2 +1 +connection master; +delete from t1; +connection slave; +select * from t1; +x +select * from t1 for system_time all; +x +2 +1 +connection master; +create or replace table t1 (x int primary key) with system versioning engine = innodb; +connection slave; +alter table t1 without system versioning; +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +select * from t1 for system_time all; +x +1 +2 +connection slave; +select * from t1; +x +2 +connection master; +delete from t1; +select * from t1 for system_time all; +x +1 +2 +connection slave; +select * from t1; +x +connection master; drop table t1; include/rpl_end.inc diff --git a/mysql-test/suite/versioning/t/rpl_test.inc b/mysql-test/suite/versioning/t/rpl_test.inc index abd156faa8c..bba67efc19b 100644 --- a/mysql-test/suite/versioning/t/rpl_test.inc +++ b/mysql-test/suite/versioning/t/rpl_test.inc @@ -29,5 +29,62 @@ sync_slave_with_master; select * from t1; select * from t1 for system_time all; +# check unversioned -> versioned replication +connection master; +create or replace table t1 (x int primary key) engine = innodb; +sync_slave_with_master; +alter table t1 with system versioning; + +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +delete from t1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +# same thing (UPDATE, DELETE), but without PK +connection master; +create or replace table t1 (x int) engine = innodb; +sync_slave_with_master; +alter table t1 with system versioning; + +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +connection master; +delete from t1; +sync_slave_with_master; +select * from t1; +select * from t1 for system_time all; + +# same thing, but reverse: versioned -> unversioned +connection master; +create or replace table t1 (x int primary key) with system versioning engine = innodb; +sync_slave_with_master; +alter table t1 without system versioning; + +connection master; +insert into t1 values (1); +update t1 set x= 2 where x = 1; +select * from t1 for system_time all; +sync_slave_with_master; +select * from t1; + +connection master; +delete from t1; +select * from t1 for system_time all; +sync_slave_with_master; +select * from t1; + connection master; drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index b90ee5f6425..0712d3e5798 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6003,8 +6003,8 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data) DBUG_ASSERT(new_data == table->record[0]); DBUG_ASSERT(old_data == table->record[1]); - // InnoDB changes sys_trx_end to curr_trx_id and we need to restore MAX_TRX - if (table->file->check_table_binlog_row_based(1)) + // it is important to keep 'old_data' intact for versioning to work correctly on slave side + if (table->file->check_table_binlog_row_based(1) && table->versioned()) memcpy(table->record[2], table->record[1], table->s->reclength); MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str); mark_trx_read_write(); @@ -6017,8 +6017,10 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data) if (likely(!error) && !row_already_logged) { rows_changed++; - if (table->file->check_table_binlog_row_based(1)) { - memcpy(table->record[1], table->record[2], table->s->reclength); + if (table->file->check_table_binlog_row_based(1)) + { + if (table->versioned()) + memcpy(table->record[1], table->record[2], table->s->reclength); error= binlog_log_row(table, old_data, new_data, log_func); } } diff --git a/sql/log_event.cc b/sql/log_event.cc index c7cbff9c615..0e48791fd5c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -12766,7 +12766,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 skip_sys_start) { bool result= FALSE; /** @@ -12799,7 +12799,10 @@ static bool record_compare(TABLE *table) /* Compare fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - + if (skip_sys_start && *ptr == table->vers_start_field()) + { + continue; + } /** We only compare field contents that are not null. NULL fields (i.e., their null bits) were compared @@ -12994,6 +12997,24 @@ int Rows_log_event::find_row(rpl_group_info *rgi) prepare_record(table, m_width, FALSE); error= unpack_current_row(rgi); + bool skip_sys_start= false; + + if (table->versioned()) + { + Field *sys_trx_end= table->vers_end_field(); + DBUG_ASSERT(table->read_set); + bitmap_set_bit(table->read_set, sys_trx_end->field_index); + // master table is unversioned + if (sys_trx_end->val_int() == 0) + { + DBUG_ASSERT(table->write_set); + bitmap_set_bit(table->write_set, sys_trx_end->field_index); + sys_trx_end->set_max(); + table->vers_start_field()->set_notnull(); + skip_sys_start= true; + } + } + DBUG_PRINT("info",("looking for the following record")); DBUG_DUMP("record[0]", table->record[0], table->s->reclength); @@ -13169,7 +13190,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, skip_sys_start)) { while ((error= table->file->ha_index_next(table->record[0]))) { @@ -13233,7 +13254,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) goto end; } } - while (record_compare(table)); + while (record_compare(table, skip_sys_start)); /* Note: above record_compare will take into accout all record fields |