Commit 10ae6e35 authored by Michael Widenius's avatar Michael Widenius

Fixed that the we don't change CREATE to CREATE OR REPLACE, except if the...

Fixed that the we don't change CREATE to CREATE OR REPLACE, except if the slave removed an existing table as part of CREATE.
This will help the following replicaition scenario:
MariaDB 10.0 master (statement replication) -> MariaDB 10.0 slave (row based replication) -> MySQL or MariaDB 5.x slave


mysql-test/r/mysqld--help.result:
  Updated help text
mysql-test/suite/rpl/r/create_or_replace_mix.result:
  Added more tests
mysql-test/suite/rpl/r/create_or_replace_row.result:
  Added more tests
mysql-test/suite/rpl/r/create_or_replace_statement.result:
  Added more tests
mysql-test/suite/rpl/t/create_or_replace.inc:
  Added more tests
sql/handler.h:
  Added org_options so that we can detect what come from the query and what was possible added later.
sql/sql_insert.cc:
  Only write CREATE OR REPLACE if was originally specified or if we delete a conflicting table as part of create
sql/sql_parse.cc:
  Remember orginal create options
sql/sql_table.cc:
  Only write CREATE OR REPLACE if was originally specified or if we delete a conflicting table as part of create
sql/sys_vars.cc:
  Updated help text
parent c386daf0
...@@ -871,12 +871,12 @@ The following options may be given as the first argument: ...@@ -871,12 +871,12 @@ The following options may be given as the first argument:
--slave-compressed-protocol --slave-compressed-protocol
Use compression on master/slave protocol Use compression on master/slave protocol
--slave-ddl-exec-mode=name --slave-ddl-exec-mode=name
Modes for how replication events should be executed. How replication events should be executed. Legal values
Legal values are STRICT and IDEMPOTENT (default). In are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode,
IDEMPOTENT mode, replication will not stop for DDL replication will not stop for DDL operations that are
operations that are idempotent. This means that CREATE idempotent. This means that CREATE TABLE is treated as
TABLE is treated CREATE TABLE OR REPLACE and DROP TABLE CREATE TABLE OR REPLACE and DROP TABLE is treated as DROP
is threated as DROP TABLE IF EXISTS. TABLE IF EXISTS.
--slave-domain-parallel-threads=# --slave-domain-parallel-threads=#
Maximum number of parallel threads to use on slave for Maximum number of parallel threads to use on slave for
events in a single replication domain. When using events in a single replication domain. When using
...@@ -886,14 +886,13 @@ The following options may be given as the first argument: ...@@ -886,14 +886,13 @@ The following options may be given as the first argument:
as many threads as it wants, up to the value of as many threads as it wants, up to the value of
slave_parallel_threads. slave_parallel_threads.
--slave-exec-mode=name --slave-exec-mode=name
Modes for how replication events should be executed. How replication events should be executed. Legal values
Legal values are STRICT (default) and IDEMPOTENT. In are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode,
IDEMPOTENT mode, replication will not stop for operations replication will not stop for operations that are
that are idempotent. For example, in row based idempotent. For example, in row based replication
replication attempts to delete rows that doesn't exist attempts to delete rows that doesn't exist will be
will be ignored.In STRICT mode, replication will stop on ignored. In STRICT mode, replication will stop on any
any unexpected difference between the master and the unexpected difference between the master and the slave
slave
--slave-load-tmpdir=name --slave-load-tmpdir=name
The location where the slave should put its temporary The location where the slave should put its temporary
files when replicating a LOAD DATA INFILE command files when replicating a LOAD DATA INFILE command
......
...@@ -115,6 +115,59 @@ t1 CREATE TABLE `t1` ( ...@@ -115,6 +115,59 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
# #
# Check how CREATE is logged on slave in case of conflicts
#
create table t1 (server_2_to_be_delete int);
create table t2 (server_2_to_be_delete int);
create table t4 (server_2_to_be_delete int);
set @org_binlog_format=@@binlog_format;
set @@global.binlog_format="ROW";
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
create temporary table t9 (a int);
insert into t9 values(1);
create table t1 (new_table int);
create table t2 select * from t9;
create table t4 like t9;
create table t5 select * from t9;
binlog from server 2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t2 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t4 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (new_table int)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t2)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t5)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
set @@global.binlog_format=@org_binlog_format;
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
drop table t1,t2,t4,t5,t9;
#
# Ensure that DROP TABLE is run as DROP IF NOT EXISTS # Ensure that DROP TABLE is run as DROP IF NOT EXISTS
# #
create table t1 (server_1_ver_1 int); create table t1 (server_1_ver_1 int);
......
...@@ -137,6 +137,59 @@ t1 CREATE TABLE `t1` ( ...@@ -137,6 +137,59 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
# #
# Check how CREATE is logged on slave in case of conflicts
#
create table t1 (server_2_to_be_delete int);
create table t2 (server_2_to_be_delete int);
create table t4 (server_2_to_be_delete int);
set @org_binlog_format=@@binlog_format;
set @@global.binlog_format="ROW";
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
create temporary table t9 (a int);
insert into t9 values(1);
create table t1 (new_table int);
create table t2 select * from t9;
create table t4 like t9;
create table t5 select * from t9;
binlog from server 2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t2 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t4 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (new_table int)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t2)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t5)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
set @@global.binlog_format=@org_binlog_format;
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
drop table t1,t2,t4,t5,t9;
#
# Ensure that DROP TABLE is run as DROP IF NOT EXISTS # Ensure that DROP TABLE is run as DROP IF NOT EXISTS
# #
create table t1 (server_1_ver_1 int); create table t1 (server_1_ver_1 int);
......
...@@ -115,6 +115,59 @@ t1 CREATE TABLE `t1` ( ...@@ -115,6 +115,59 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
# #
# Check how CREATE is logged on slave in case of conflicts
#
create table t1 (server_2_to_be_delete int);
create table t2 (server_2_to_be_delete int);
create table t4 (server_2_to_be_delete int);
set @org_binlog_format=@@binlog_format;
set @@global.binlog_format="ROW";
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
create temporary table t9 (a int);
insert into t9 values(1);
create table t1 (new_table int);
create table t2 select * from t9;
create table t4 like t9;
create table t5 select * from t9;
binlog from server 2
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t2 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t4 (server_2_to_be_delete int)
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; create table t1 (new_table int)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t2` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t2)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
)
slave-bin.000001 # Table_map # # table_id: # (test.t5)
slave-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-bin.000001 # Query # # COMMIT
set @@global.binlog_format=@org_binlog_format;
stop slave;
include/wait_for_slave_to_stop.inc
start slave;
include/wait_for_slave_to_start.inc
drop table t1,t2,t4,t5,t9;
#
# Ensure that DROP TABLE is run as DROP IF NOT EXISTS # Ensure that DROP TABLE is run as DROP IF NOT EXISTS
# #
create table t1 (server_1_ver_1 int); create table t1 (server_1_ver_1 int);
......
...@@ -95,6 +95,43 @@ show create table t1; ...@@ -95,6 +95,43 @@ show create table t1;
connection server_1; connection server_1;
drop table t1; drop table t1;
--echo #
--echo # Check how CREATE is logged on slave in case of conflicts
--echo #
save_master_pos;
connection server_2;
sync_with_master;
--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
create table t1 (server_2_to_be_delete int);
create table t2 (server_2_to_be_delete int);
create table t4 (server_2_to_be_delete int);
set @org_binlog_format=@@binlog_format;
set @@global.binlog_format="ROW";
stop slave;
--source include/wait_for_slave_to_stop.inc
start slave;
--source include/wait_for_slave_to_start.inc
connection server_1;
create temporary table t9 (a int);
insert into t9 values(1);
create table t1 (new_table int);
create table t2 select * from t9;
create table t4 like t9;
create table t5 select * from t9;
save_master_pos;
connection server_2;
sync_with_master;
--echo binlog from server 2
--source include/show_binlog_events.inc
set @@global.binlog_format=@org_binlog_format;
stop slave;
--source include/wait_for_slave_to_stop.inc
start slave;
--source include/wait_for_slave_to_start.inc
connection server_1;
drop table t1,t2,t4,t5,t9;
--echo # --echo #
--echo # Ensure that DROP TABLE is run as DROP IF NOT EXISTS --echo # Ensure that DROP TABLE is run as DROP IF NOT EXISTS
--echo # --echo #
......
...@@ -1591,6 +1591,7 @@ struct HA_CREATE_INFO ...@@ -1591,6 +1591,7 @@ struct HA_CREATE_INFO
uint stats_sample_pages; uint stats_sample_pages;
uint null_bits; /* NULL bits at start of record */ uint null_bits; /* NULL bits at start of record */
uint options; /* OR of HA_CREATE_ options */ uint options; /* OR of HA_CREATE_ options */
uint org_options; /* original options from query */
uint merge_insert_method; uint merge_insert_method;
uint extra_size; /* length of extra data segment */ uint extra_size; /* length of extra data segment */
SQL_I_List<TABLE_LIST> merge_list; SQL_I_List<TABLE_LIST> merge_list;
......
...@@ -4164,8 +4164,9 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) ...@@ -4164,8 +4164,9 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
result= store_create_info(thd, &tmp_table_list, &query, create_info, result= store_create_info(thd, &tmp_table_list, &query, create_info,
/* show_database */ TRUE, /* show_database */ TRUE,
MY_TEST(create_info->options & MY_TEST(create_info->org_options &
HA_LEX_CREATE_REPLACE)); HA_LEX_CREATE_REPLACE) ||
create_info->table_was_deleted);
DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */ DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
......
...@@ -2893,6 +2893,7 @@ case SQLCOM_PREPARE: ...@@ -2893,6 +2893,7 @@ case SQLCOM_PREPARE:
CREATE TABLE OR EXISTS failures by dropping the table and CREATE TABLE OR EXISTS failures by dropping the table and
retrying the create. retrying the create.
*/ */
create_info.org_options= create_info.options;
if (thd->slave_thread && if (thd->slave_thread &&
slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT && slave_ddl_exec_mode_options == SLAVE_EXEC_MODE_IDEMPOTENT &&
!(lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)) !(lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS))
......
...@@ -5460,8 +5460,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, ...@@ -5460,8 +5460,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
int result __attribute__((unused))= int result __attribute__((unused))=
store_create_info(thd, table, &query, store_create_info(thd, table, &query,
create_info, FALSE /* show_database */, create_info, FALSE /* show_database */,
MY_TEST(create_info->options & MY_TEST(create_info->org_options &
HA_LEX_CREATE_REPLACE)); HA_LEX_CREATE_REPLACE) ||
create_info->table_was_deleted);
DBUG_ASSERT(result == 0); // store_create_info() always return 0 DBUG_ASSERT(result == 0); // store_create_info() always return 0
do_logging= FALSE; do_logging= FALSE;
......
...@@ -2717,11 +2717,11 @@ static Sys_var_mybool Sys_slave_compressed_protocol( ...@@ -2717,11 +2717,11 @@ static Sys_var_mybool Sys_slave_compressed_protocol(
static const char *slave_exec_mode_names[]= {"STRICT", "IDEMPOTENT", 0}; static const char *slave_exec_mode_names[]= {"STRICT", "IDEMPOTENT", 0};
static Sys_var_enum Slave_exec_mode( static Sys_var_enum Slave_exec_mode(
"slave_exec_mode", "slave_exec_mode",
"Modes for how replication events should be executed. Legal values " "How replication events should be executed. Legal values "
"are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, " "are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, "
"replication will not stop for operations that are idempotent. " "replication will not stop for operations that are idempotent. "
"For example, in row based replication attempts to delete rows that " "For example, in row based replication attempts to delete rows that "
"doesn't exist will be ignored." "doesn't exist will be ignored. "
"In STRICT mode, replication will stop on any unexpected difference " "In STRICT mode, replication will stop on any unexpected difference "
"between the master and the slave", "between the master and the slave",
GLOBAL_VAR(slave_exec_mode_options), CMD_LINE(REQUIRED_ARG), GLOBAL_VAR(slave_exec_mode_options), CMD_LINE(REQUIRED_ARG),
...@@ -2729,11 +2729,11 @@ static Sys_var_enum Slave_exec_mode( ...@@ -2729,11 +2729,11 @@ static Sys_var_enum Slave_exec_mode(
static Sys_var_enum Slave_ddl_exec_mode( static Sys_var_enum Slave_ddl_exec_mode(
"slave_ddl_exec_mode", "slave_ddl_exec_mode",
"Modes for how replication events should be executed. Legal values " "How replication events should be executed. Legal values "
"are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode, " "are STRICT and IDEMPOTENT (default). In IDEMPOTENT mode, "
"replication will not stop for DDL operations that are idempotent. " "replication will not stop for DDL operations that are idempotent. "
"This means that CREATE TABLE is treated CREATE TABLE OR REPLACE and " "This means that CREATE TABLE is treated as CREATE TABLE OR REPLACE and "
"DROP TABLE is threated as DROP TABLE IF EXISTS. ", "DROP TABLE is treated as DROP TABLE IF EXISTS.",
GLOBAL_VAR(slave_ddl_exec_mode_options), CMD_LINE(REQUIRED_ARG), GLOBAL_VAR(slave_ddl_exec_mode_options), CMD_LINE(REQUIRED_ARG),
slave_exec_mode_names, DEFAULT(SLAVE_EXEC_MODE_IDEMPOTENT)); slave_exec_mode_names, DEFAULT(SLAVE_EXEC_MODE_IDEMPOTENT));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment