Skip to content

Commit

Permalink
Add column names to rbr table map log events.
Browse files Browse the repository at this point in the history
Summary:
Column names added to table map log events are used by slave
to find out the corresponding field in slave's table whose index
may be different than the index of the field in master's table
due to a schema change.

This behavior is controlled for each table using
  Alter table rbr_column_names=1

This is an inplace alter which does metadata only change in the table
frm file.

During a schema change on a replica set, slaves may have different schema
than master which will break RBR. The following functionality needs to be
added to online schema change (OSC):

a. Before starting OSC, run alter table rbr_column_names=1 on master of the
replica set. This will get replicated to the slaves.

b. Run OSC on all slaves first and then on master.

c. Run alter table rbr_column_names=0 on master of the replica set to
turn off the feature.

The column names will increase the binlog size, so they should be used
temporarily on per-table basis only while OSC is running on the replica set.
This change is backward compatible but older MySQL versions will not understand
the new format of table map log events. So, before using this feature
all the servers in the replica set must be upgraded to new MySQL with this
change.

Note mysqlbinlog is not updated to show table column names when available.

Test Plan: mtr tests

Reviewers: ebergen, jtolmer

Reviewed By: jtolmer
  • Loading branch information
santoshbanda authored and jtolmer committed Jan 5, 2016
1 parent 915b131 commit c09eb80
Show file tree
Hide file tree
Showing 23 changed files with 562 additions and 22 deletions.
2 changes: 1 addition & 1 deletion mysql-test/r/mysqld--help-notwin-profiling.result
Original file line number Diff line number Diff line change
Expand Up @@ -1404,7 +1404,7 @@ performance-schema-max-rwlock-instances -1
performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1
performance-schema-max-stage-classes 150
performance-schema-max-statement-classes 173
performance-schema-max-statement-classes 174
performance-schema-max-table-handles -1
performance-schema-max-table-instances -1
performance-schema-max-thread-classes 50
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/mysqld--help-notwin.result
Original file line number Diff line number Diff line change
Expand Up @@ -1402,7 +1402,7 @@ performance-schema-max-rwlock-instances -1
performance-schema-max-socket-classes 10
performance-schema-max-socket-instances -1
performance-schema-max-stage-classes 150
performance-schema-max-statement-classes 173
performance-schema-max-statement-classes 174
performance-schema-max-table-handles -1
performance-schema-max-table-instances -1
performance-schema-max-thread-classes 50
Expand Down
80 changes: 80 additions & 0 deletions mysql-test/suite/rpl/r/rpl_rbr_column_names.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
include/master-slave.inc
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
call mtr.add_suppression("Slave SQL.*Column [0-9] of table .test.t[0-9]*. cannot be converted from type.* Error_code: 1677");
create table t1 (a int, b text) rbr_column_names=1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1 RBR_COLUMN_NAMES=1
drop table t1;
create table t1 (b text);
Check slave can deal with missing columns
insert into t1 values(1, "column1");
select * from t1;
b
column1
drop table t1;
create table t1 (b text, a int);
Check slave can deal with columns in different order
insert into t1(a, b) values(2, "column2");
update t1 set b="update column2" where a=2;
select * from t1;
b a
update column2 2
drop table t1;
create table t1 (extra_column text, a int, b text);
Check slave can deal with new columns added at the beginning
insert into t1 values(2, "column2");
select * from t1;
extra_column a b
NULL 2 column2
drop table t1;
create table t1(a int, extra_column text, b text);
Check slave can deal with new columns added in the middle
insert into t1 values(2, "column2");
insert into t1 values(3, "column3");
delete from t1 where a=3 and b="column3";
select * from t1;
a extra_column b
2 NULL column2
drop table t1;
create table t1 (a int, b int);
Check slave fails with an error due to type mismatch
insert into t1 values(1, "column2");
include/wait_for_slave_sql_error.inc [errno=1677]
include/stop_slave.inc
include/rpl_reset.inc
Check rbr_column_names can be changed using ALTER TABLE
alter table t1 rbr_column_names = 0;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t1 rbr_column_names = 1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1 RBR_COLUMN_NAMES=1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 RBR_COLUMN_NAMES=1
drop table t1;
include/rpl_end.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
include/master-slave.inc
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
set @saved_slave_type_conversions = @@global.slave_type_conversions;
set @@global.slave_type_conversions = 'ALL_LOSSY,ALL_NON_LOSSY';
create table t1(a int, b tinyblob, c int) rbr_column_names=1;
Check slave can deal with reordering of columns
drop table t1;
create table t1(a int, c tinyint, b mediumblob) rbr_column_names=1;
insert into t1 values(1, "tiny blob", 100);
select * from t1;
a c b
1 100 tiny blob
Check slave can deal with deleted columns
drop table t1;
create table t1(c tinyint, b mediumblob) rbr_column_names=1;
insert into t1 values(1, "tiny blob", 100);
select * from t1;
c b
100 tiny blob
Check slave can deal with added columns
drop table t1;
create table t1(a int, d int, c tinyint, b mediumblob) rbr_column_names=1;
insert into t1 values(1, "tiny blob", 100);
select * from t1;
a d c b
1 NULL 100 tiny blob
set @@global.slave_type_conversions = @saved_slave_type_conversions;
drop table t1;
include/rpl_end.inc
73 changes: 73 additions & 0 deletions mysql-test/suite/rpl/t/rpl_rbr_column_names.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
source include/master-slave.inc;
source include/have_binlog_format_row.inc;
call mtr.add_suppression("Slave SQL.*Column [0-9] of table .test.t[0-9]*. cannot be converted from type.* Error_code: 1677");

connection master;
create table t1 (a int, b text) rbr_column_names=1;
show create table t1;
sync_slave_with_master;

drop table t1;
create table t1 (b text);
--echo Check slave can deal with missing columns
connection master;
insert into t1 values(1, "column1");
sync_slave_with_master;
select * from t1;

drop table t1;
create table t1 (b text, a int);
--echo Check slave can deal with columns in different order
connection master;
insert into t1(a, b) values(2, "column2");
update t1 set b="update column2" where a=2;
sync_slave_with_master;
select * from t1;

drop table t1;
create table t1 (extra_column text, a int, b text);
--echo Check slave can deal with new columns added at the beginning
connection master;
insert into t1 values(2, "column2");
sync_slave_with_master;
select * from t1;

drop table t1;
create table t1(a int, extra_column text, b text);
--echo Check slave can deal with new columns added in the middle
connection master;
insert into t1 values(2, "column2");
insert into t1 values(3, "column3");
delete from t1 where a=3 and b="column3";
sync_slave_with_master;
select * from t1;

drop table t1;
create table t1 (a int, b int);
--echo Check slave fails with an error due to type mismatch
connection master;
insert into t1 values(1, "column2");
connection slave;
let $slave_sql_errno=convert_error(ER_SLAVE_CONVERSION_FAILED);
source include/wait_for_slave_sql_error.inc;
source include/stop_slave.inc;
let $rpl_only_running_threads= 1;
source include/rpl_reset.inc;

--echo Check rbr_column_names can be changed using ALTER TABLE
connection master;
alter table t1 rbr_column_names = 0;
show create table t1;
sync_slave_with_master;
show create table t1;

connection master;
alter table t1 rbr_column_names = 1;
show create table t1;
sync_slave_with_master;
show create table t1;


connection master;
drop table t1;
source include/rpl_end.inc;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# This test verifies slave_type_conversions when
# rbr_column_names is enabled for a table.
source include/have_binlog_format_row.inc;
source include/master-slave.inc;

connection slave;
set @saved_slave_type_conversions = @@global.slave_type_conversions;
set @@global.slave_type_conversions = 'ALL_LOSSY,ALL_NON_LOSSY';

connection master;
create table t1(a int, b tinyblob, c int) rbr_column_names=1;
sync_slave_with_master;

--echo Check slave can deal with reordering of columns
drop table t1;
create table t1(a int, c tinyint, b mediumblob) rbr_column_names=1;
connection master;
insert into t1 values(1, "tiny blob", 100);
sync_slave_with_master;
select * from t1;

--echo Check slave can deal with deleted columns
drop table t1;
create table t1(c tinyint, b mediumblob) rbr_column_names=1;
connection master;
insert into t1 values(1, "tiny blob", 100);
sync_slave_with_master;
select * from t1;

--echo Check slave can deal with added columns
drop table t1;
create table t1(a int, d int, c tinyint, b mediumblob) rbr_column_names=1;
connection master;
insert into t1 values(1, "tiny blob", 100);
sync_slave_with_master;
select * from t1;

set @@global.slave_type_conversions = @saved_slave_type_conversions;
connection master;
drop table t1;
source include/rpl_end.inc;

3 changes: 2 additions & 1 deletion sql/handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4568,7 +4568,8 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::ALTER_COLUMN_NAME |
Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::CHANGE_CREATE_OPTION |
Alter_inplace_info::ALTER_RENAME;
Alter_inplace_info::ALTER_RENAME |
Alter_inplace_info::ALTER_RBR_COLUMN_NAMES;

/* Is there at least one operation that requires copy algorithm? */
if (ha_alter_info->handler_flags & ~inplace_offline_operations)
Expand Down
5 changes: 5 additions & 0 deletions sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ given at all. */
given at all.
*/
#define HA_CREATE_USED_STATS_SAMPLE_PAGES (1L << 24)
#define HA_CREATE_USED_RBR_COLUMN_NAMES (1L << 47)


/*
Expand Down Expand Up @@ -1102,6 +1103,8 @@ typedef struct st_ha_create_information
uint extra_size; /* length of extra data segment */
bool varchar; /* 1 if table has a VARCHAR */
enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */
bool rbr_column_names; /* If true, column names for this table are logged
in Table_map_log_events */
} HA_CREATE_INFO;

/**
Expand Down Expand Up @@ -1253,6 +1256,8 @@ class Alter_inplace_info
*/
static const HA_ALTER_FLAGS RECREATE_TABLE = 1L << 29;

static const HA_ALTER_FLAGS ALTER_RBR_COLUMN_NAMES = 1L << 47;

/**
Create options (like MAX_ROWS) for the new version of table.
Expand Down
1 change: 1 addition & 0 deletions sql/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ static SYMBOL symbols[] = {
{ "QUERY", SYM(QUERY_SYM)},
{ "QUICK", SYM(QUICK)},
{ "RANGE", SYM(RANGE_SYM)},
{ "RBR_COLUMN_NAMES", SYM(RBR_COLUMN_NAMES_SYM)},
{ "READ", SYM(READ_SYM)},
{ "READ_ONLY", SYM(READ_ONLY_SYM)},
{ "READ_WRITE", SYM(READ_WRITE_SYM)},
Expand Down
Loading

0 comments on commit c09eb80

Please sign in to comment.