diff options
Diffstat (limited to 'mysql-test/suite/rpl/t')
695 files changed, 44903 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/t/circular_serverid0.cnf b/mysql-test/suite/rpl/t/circular_serverid0.cnf new file mode 100644 index 00000000..277aac28 --- /dev/null +++ b/mysql-test/suite/rpl/t/circular_serverid0.cnf @@ -0,0 +1,30 @@ +!include ../my.cnf + +[mysqld.1] +gtid-domain-id=4 +server-id=4 +# +log-slave-updates +slave-parallel-threads=0 +gtid-strict-mode=1 +gtid-ignore-duplicates=1 + +# +# Max-size row events to minimum with the idea to create +# a number of Rows_log_event per Query. +# +binlog-row-event-max-size=1024 + +[mysqld.2] +gtid-domain-id=2 +server-id=2 +# +log-slave-updates +slave-parallel-threads=0 +gtid-strict-mode=1 +gtid-ignore-duplicates=1 +binlog-row-event-max-size=1024 +# The slave will be initialized with a @@global.dbug-var value +skip-slave-start=1 + + diff --git a/mysql-test/suite/rpl/t/circular_serverid0.test b/mysql-test/suite/rpl/t/circular_serverid0.test new file mode 100644 index 00000000..64cf231c --- /dev/null +++ b/mysql-test/suite/rpl/t/circular_serverid0.test @@ -0,0 +1,103 @@ +# +# Testing chain/circular replication scenario of MDEV-9670 +# The effect of the bug was that we got a commit with a GTID with server_id +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--let $rpl_topology= 1->2->1 +--source include/rpl_init.inc + +--let $rpl_connection_name= M4 +--let $rpl_server_number= 1 +--source include/rpl_connect.inc + +--let $rpl_connection_name= M2 +--let $rpl_server_number= 2 +--source include/rpl_connect.inc + +# The parameter reflects binlog-row-event-max-size @cnf. +--let $row_size=1024 + +--connection M2 +STOP SLAVE; +SET @old_debug= @@global.debug_dbug; +SET GLOBAL debug_dbug= "d,dbug.rows_events_to_delay_relay_logging"; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection M2 +# This query also creates a Gtid event group whose Gtid will remain in +# ignored status for too long causing a following group split. + +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b VARCHAR(30000)) ENGINE=innodb; +--sync_slave_with_master M4 + +# This INSERT will be logged as two Write_log events which the buggy +# slave applier would split. + +--connection M4 +eval INSERT INTO `t1` VALUES (null, repeat('a', $row_size)), (null, repeat('b', $row_size)); + +# START M2 IO thread and wait for its signal to follow with the SQL +# thread start. At this moment the SQL thread shall be having 2 and +# "half" groups to execute. The "hafl" one would be committed by the +# buggy applier after which the IO is released to queue the rest of +# the 3rd group which the SQL thread commits separately to complete +# the split. + +--connection M2 + +# wait for IO signal to start the SQL thread. IO will be hanging upon that. +SET debug_sync='now WAIT_FOR start_sql_thread'; + +# Now the slave server has relay log whose last group is incomplete. +# An unfixed slave server would go to "insert" a "fake" +# Gtid_list_log_event event which actually would commit the incomplete +# group. However before to actual commit do_apply_event() hits some assert. +# In the fixed server the fake Gtid_list_log_event is *not* inserted +# in the middle of a group. +START SLAVE SQL_THREAD; + +# Sleep for a little time to give SQL thread a chance to commit while +# the IO thread is hanging (see +# DBUG_EXECUTE_IF("dbug.rows_events_to_delay_relay_logging"...) in +# queue_event). Alternatively to reproduce the case when buggy slave +# wait for the 1st group commit + +#--let $count= 1 +#--let $table= t1 +#--source include/wait_until_rows_count.inc + +--sleep 2 + +# Demonstrate either no split group in the correct slave or the 1nd +# group in the buggy one +--source include/show_binlog_events.inc + +# Release the IO thread +SET debug_sync='now SIGNAL go_on_relay_logging'; + +# Sync servers +--sync_slave_with_master M4 +--connection M4 +--sync_slave_with_master M2 +--connection M2 + +# Demonstrate replication goes correctly not to create any split, or +# the 2nd group in the buggy slave +--source include/show_binlog_events.inc + +# +# Cleanup +# +--connection M4 +drop table t1; + +--connection M2 +SET GLOBAL debug_dbug= @old_debug; +SET debug_sync='RESET'; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/create_or_replace.inc b/mysql-test/suite/rpl/t/create_or_replace.inc new file mode 100644 index 00000000..df46cc36 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace.inc @@ -0,0 +1,227 @@ +# Test CREATE OR REPLACE TABLE in replication +--source include/have_innodb.inc + +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +# Create help tables +create table t2 (a int) engine=myisam; +insert into t2 values (0),(1),(2),(2); +create temporary table t3 (a_in_temporary int) engine=myisam; + +--echo # +--echo # Check how create table and create or replace table are logged +--echo # + +save_master_pos; +connection server_2; +sync_with_master; +create table t1 (to_be_deleted int); + +connection server_1; +CREATE TABLE t1 AS SELECT 1 AS f1; +CREATE OR REPLACE TABLE t1 AS SELECT 2 AS f1; +CREATE OR REPLACE table t1 like t2; +CREATE OR REPLACE table t1 like t3; +drop table t1; + +--echo binlog from server 1 +--source include/show_binlog_events.inc +save_master_pos; +connection server_2; +sync_with_master; +--echo binlog from server 2 +--source include/show_binlog_events.inc + +connection server_1; + +--echo # +--echo # Ensure that also failed create_or_replace are logged +--echo # + +--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1) + +create table t1 (a int); +--error ER_TABLE_MUST_HAVE_COLUMNS +create or replace table t1; +drop table if exists t1; +# The following is not logged as t1 does not exists; +--error ER_DUP_ENTRY +create or replace table t1 (a int primary key) select a from t2; + +create table t1 (a int); +# This should as a delete as we will delete t1 +--error ER_DUP_ENTRY +create or replace table t1 (a int primary key) select a from t2; + +# Same with temporary table +create temporary table t9 (a int); + +--error ER_DUP_ENTRY +create or replace temporary table t9 (a int primary key) select a from t2; + +--echo binlog from server 1 +--source include/show_binlog_events.inc +save_master_pos; +connection server_2; +sync_with_master; +show tables; +connection server_1; + +--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1) +create table t1 (a int); +--error ER_DUP_FIELDNAME +create or replace table t1 (a int, a int) select * from t2; +--source include/show_binlog_events.inc + +drop table if exists t1,t2; +drop temporary table if exists t9; + +--echo # +--echo # Ensure that CREATE are run as CREATE OR REPLACE on slave +--echo # + +save_master_pos; +connection server_2; +sync_with_master; +create table t1 (server_2_to_be_delete int); +connection server_1; +create table t1 (new_table int); + +save_master_pos; +connection server_2; +sync_with_master; + +show create table t1; +connection server_1; +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 # Ensure that DROP TABLE is run as DROP IF NOT EXISTS +--echo # + +create table t1 (server_1_ver_1 int); +create table t4 (server_1_ver_2 int); + +save_master_pos; +connection server_2; +sync_with_master; +--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1) + +# Drop the table on the slave +drop table t1; +connection server_1; +drop table t1,t4; +create table t1 (server_2_ver_2 int); +save_master_pos; +connection server_2; +sync_with_master; +show create table t1; +--echo binlog from server 2 +--source include/show_binlog_events.inc +connection server_1; +drop table t1; + +--echo # +--echo # Ensure that CREATE ... SELECT is recorded as one GTID on the slave +--echo # + +save_master_pos; +connection server_2; +sync_with_master; +--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1) +connection server_1; + +create table t1 (a int); +insert into t1 values (0),(1),(2); +create table t2 engine=myisam select * from t1; +create or replace table t2 engine=innodb select * from t1; +save_master_pos; +connection server_2; +sync_with_master; +--echo binlog from server 2 +--source include/show_binlog_events.inc +connection server_1; +drop table t1; + +--echo # +--echo # Check logging of drop temporary table +--echo # + +drop temporary table t3; + +--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1) + +set @org_binlog_format=@@binlog_format; +set binlog_format="STATEMENT"; +create temporary table t5 (a int); +drop temporary table t5; +set binlog_format="ROW"; +create temporary table t6 (a int); +drop temporary table t6; +set binlog_format="STATEMENT"; +create temporary table t7 (a int); +set binlog_format="ROW"; +drop temporary table t7; +create temporary table t8 (a int); +--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR +set binlog_format="STATEMENT"; +drop temporary table t8; +set @@binlog_format=@org_binlog_format; + +# MDEV-20091: +# 1. No DROP should be logged for non-existing tmp table, nor +# 2. at the connection close when its creation has not been logged. +set @@session.binlog_format=default; +drop temporary table if exists t9; + +--connect(con1,localhost,root,,) +set session binlog_format=default; +create temporary table t9 (i int); +--echo *** Must be no DROP logged for t9 when there was no CREATE, at disconnect too *** +--disconnect con1 + +--connection server_1 +--source include/show_binlog_events.inc + +# Clean up +drop table t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/create_or_replace2.test b/mysql-test/suite/rpl/t/create_or_replace2.test new file mode 100644 index 00000000..f0091db7 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace2.test @@ -0,0 +1,42 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_row_or_statement.inc +--source include/have_metadata_lock_info.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-6525 ; Problems with CREATE OR REPLACE under lock +--echo # + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE FUNCTION f1() RETURNS INT RETURN ( SELECT MAX(a) FROM t1 ); + +--connect (con1,localhost,root,,test) + +CREATE TEMPORARY TABLE tmp (b INT) ENGINE=InnoDB; +LOCK TABLE t1 WRITE; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; + +CREATE OR REPLACE TABLE t1 LIKE tmp; +SHOW CREATE TABLE t1; + +--connection default +set session lock_wait_timeout=1; +--error 1205 +SELECT f1(); + +set session lock_wait_timeout=@@global.lock_wait_timeout; +--send SELECT f1() +--connection con1 +# This is here just in case, any timeout should be ok +--sleep 1 +unlock tables; +--connection default +--error 1054 +--reap +--disconnect con1 + +# Cleanup +drop function f1; +drop table t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/create_or_replace_mix.cnf b/mysql-test/suite/rpl/t/create_or_replace_mix.cnf new file mode 100644 index 00000000..03d69b28 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_mix.cnf @@ -0,0 +1,9 @@ +!include suite/rpl/my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb diff --git a/mysql-test/suite/rpl/t/create_or_replace_mix.test b/mysql-test/suite/rpl/t/create_or_replace_mix.test new file mode 100644 index 00000000..0cabef15 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_mix.test @@ -0,0 +1,4 @@ +# Testing create or replace table in mixed mode. + +--source include/have_binlog_format_mixed.inc +--source create_or_replace.inc diff --git a/mysql-test/suite/rpl/t/create_or_replace_row.cnf b/mysql-test/suite/rpl/t/create_or_replace_row.cnf new file mode 100644 index 00000000..03d69b28 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_row.cnf @@ -0,0 +1,9 @@ +!include suite/rpl/my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb diff --git a/mysql-test/suite/rpl/t/create_or_replace_row.test b/mysql-test/suite/rpl/t/create_or_replace_row.test new file mode 100644 index 00000000..88dd8fd2 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_row.test @@ -0,0 +1,4 @@ +# Testing create or replace table in mixed mode. + +--source include/have_binlog_format_row.inc +--source create_or_replace.inc diff --git a/mysql-test/suite/rpl/t/create_or_replace_statement.cnf b/mysql-test/suite/rpl/t/create_or_replace_statement.cnf new file mode 100644 index 00000000..03d69b28 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_statement.cnf @@ -0,0 +1,9 @@ +!include suite/rpl/my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb diff --git a/mysql-test/suite/rpl/t/create_or_replace_statement.test b/mysql-test/suite/rpl/t/create_or_replace_statement.test new file mode 100644 index 00000000..2709e414 --- /dev/null +++ b/mysql-test/suite/rpl/t/create_or_replace_statement.test @@ -0,0 +1,4 @@ +# Testing create or replace table in mixed mode. + +--source include/have_binlog_format_statement.inc +--source create_or_replace.inc diff --git a/mysql-test/suite/rpl/t/create_select.cnf b/mysql-test/suite/rpl/t/create_select.cnf new file mode 100644 index 00000000..65a4396e --- /dev/null +++ b/mysql-test/suite/rpl/t/create_select.cnf @@ -0,0 +1,16 @@ +!include suite/rpl/my.cnf + +[mysqld.1] + +[mysqld.2] +log-slave-updates +binlog-checksum=CRC32 + +[mysqld.3] +log-slave-updates +binlog-checksum=CRC32 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + diff --git a/mysql-test/suite/rpl/t/create_select.test b/mysql-test/suite/rpl/t/create_select.test new file mode 100644 index 00000000..c1f8fc8f --- /dev/null +++ b/mysql-test/suite/rpl/t/create_select.test @@ -0,0 +1,37 @@ +--source include/have_innodb.inc + +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +# +# Test of MDEV-8428 Mangled DML statements on 2nd level slave when enabling +# binlog checksums +# + +connection server_1; + +CREATE DATABASE test_8428; +USE test_8428; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1), (2), (3), (4), (5); +CREATE TABLE t2 AS SELECT * FROM t1; +CREATE TABLE t3 ENGINE=MyISAM AS SELECT * FROM t1; + +save_master_pos; +connection server_2; +sync_with_master; + +SHOW TABLES IN test_8428; + +save_master_pos; +connection server_3; +sync_with_master; + +SHOW TABLES IN test_8428; +SELECT * from test_8428.t1; + +# Cleanup +connection server_1; +DROP DATABASE test_8428; +--source include/rpl_end.inc +--echo # End of test diff --git a/mysql-test/suite/rpl/t/failed_create_view-6409.test b/mysql-test/suite/rpl/t/failed_create_view-6409.test new file mode 100644 index 00000000..5d96e6f8 --- /dev/null +++ b/mysql-test/suite/rpl/t/failed_create_view-6409.test @@ -0,0 +1,24 @@ +# +# MDEV-6409 CREATE VIEW replication problem if error occurs in mysql_register_view +# + +# +# +# verify that failed CREATE VIEW is not replicated + +create table v1 (a int); + +source include/master-slave.inc; + +connection master; +create table t1 (a int); +--error ER_TABLE_EXISTS_ERROR +create view v1 as select * from t1; +show tables; +sync_slave_with_master; +show tables; + +connection master; +drop table if exists t1, v1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/grant_replication_slave.test b/mysql-test/suite/rpl/t/grant_replication_slave.test new file mode 100644 index 00000000..c5aca0a6 --- /dev/null +++ b/mysql-test/suite/rpl/t/grant_replication_slave.test @@ -0,0 +1,39 @@ +--echo # +--echo # MDEV-21743 Split up SUPER privilege to smaller privileges +--echo # + +# Checking that REPLICATION SLAVE is enough to start replication + +create user rpl@localhost; +grant replication slave on *.* to rpl@localhost; + +source include/master-slave.inc; +connection slave; +stop slave; +change master to master_user='rpl'; +connection master; + +create database mysqltest1; +create table mysqltest1.t1 (a int); +insert mysqltest1.t1 values (1),(2),(3); +select * from mysqltest1.t1; +flush tables; +create user foo@localhost; +grant select on *.* to foo@localhost; + +connection slave; +start slave; +connection master; +sync_slave_with_master; +select * from mysqltest1.t1; +show grants for foo@localhost; +connection master; +drop user foo@localhost; +drop database mysqltest1; +sync_slave_with_master; +stop slave; +change master to master_user='root'; +start slave; + +source include/rpl_end.inc; +drop user rpl@localhost; diff --git a/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test new file mode 100644 index 00000000..405d1a92 --- /dev/null +++ b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test @@ -0,0 +1,35 @@ +# +# MDEV-9737 Duplicate error in replication with slave triggers and auto increment +# +source include/master-slave.inc; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + + +create table t1(id int auto_increment primary key); +create table t2(id int auto_increment primary key); + +sync_slave_with_master; +create table slave_only(id int auto_increment primary key); +insert into slave_only values(NULL); +create trigger t1i after insert on t1 for each row insert into slave_only values(NULL); + +stop slave; +set global replicate_ignore_table="test.t2"; +start slave; + +connection master; +insert into t2 values(NULL); +insert into t1 values(NULL); + +sync_slave_with_master; + +drop table t1, t2, slave_only; +stop slave; +set global replicate_ignore_table=""; +start slave; + +connection master; +drop table t1, t2; + +source include/rpl_end.inc; + diff --git a/mysql-test/suite/rpl/t/kill_hard-6290.test b/mysql-test/suite/rpl/t/kill_hard-6290.test new file mode 100644 index 00000000..76242356 --- /dev/null +++ b/mysql-test/suite/rpl/t/kill_hard-6290.test @@ -0,0 +1,11 @@ +# +# MDEV-6290 Crash in KILL HARD QUERY USER x@y when slave threads are running +# + +# this test doesn't depend on the binlog format, no need to run it three times +--source include/have_binlog_format_mixed.inc + +--source include/master-slave.inc +--connection server_2 +kill user test2@nohost; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/kill_race_condition.test b/mysql-test/suite/rpl/t/kill_race_condition.test new file mode 100644 index 00000000..25a7b18b --- /dev/null +++ b/mysql-test/suite/rpl/t/kill_race_condition.test @@ -0,0 +1,36 @@ +source include/have_debug_sync.inc; +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +connection master; +create table t1 (a int); +--sync_slave_with_master + +connection slave; +SET @saved_dbug = @@GLOBAL.debug_dbug; +set global debug_dbug='d,rows_log_event_before_open_table'; + +connection master; +insert t1 values (1),(2),(3); + +connection slave; +set debug_sync='now WAIT_FOR before_open_table'; +let $a=`select id from information_schema.processlist where state='debug sync point: now'`; +replace_result $a slave_sql_thread; +eval kill $a; +set debug_sync='now SIGNAL go_ahead_sql'; +--let $slave_sql_errno= 1927 +--source include/wait_for_slave_sql_error.inc +let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +--echo Last_SQL_Error = $error +SET @@GLOBAL.debug_dbug = @saved_dbug; +set debug_sync='RESET'; +connection master; +drop table t1; + +connection slave; +--source include/start_slave.inc +let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +--echo Last_SQL_Error = $error + +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/last_insert_id.cnf b/mysql-test/suite/rpl/t/last_insert_id.cnf new file mode 100644 index 00000000..1c229e4a --- /dev/null +++ b/mysql-test/suite/rpl/t/last_insert_id.cnf @@ -0,0 +1,20 @@ +!include suite/rpl/my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb +replicate-ignore-table=db.t2 + +[mysqld.3] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + + diff --git a/mysql-test/suite/rpl/t/last_insert_id.test b/mysql-test/suite/rpl/t/last_insert_id.test new file mode 100644 index 00000000..f23cca40 --- /dev/null +++ b/mysql-test/suite/rpl/t/last_insert_id.test @@ -0,0 +1,30 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_statement.inc +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +connection server_1; + +create table t1 (id int not null auto_increment primary key, i int) engine=InnoDB; +insert into t1 (i) values (-1); +insert into t1 (i) values (LAST_INSERT_ID()); +select * from t1; + +save_master_pos; + +connection server_2; + +sync_with_master; +select * from t1; +save_master_pos; + +connection server_3; + +sync_with_master; +select * from t1; + +connection server_1; +drop table t1; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/mdev_17588-slave.opt b/mysql-test/suite/rpl/t/mdev_17588-slave.opt new file mode 100644 index 00000000..d73dbeca --- /dev/null +++ b/mysql-test/suite/rpl/t/mdev_17588-slave.opt @@ -0,0 +1 @@ +--loose-disable-innodb --replicate-ignore-table=test.t3 diff --git a/mysql-test/suite/rpl/t/mdev_17588.test b/mysql-test/suite/rpl/t/mdev_17588.test new file mode 100644 index 00000000..44644158 --- /dev/null +++ b/mysql-test/suite/rpl/t/mdev_17588.test @@ -0,0 +1,44 @@ +--source include/master-slave.inc +--source include/have_innodb.inc + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection master +create table t1 (a int) engine=innodb; +create table t2 (a int); +create table t3 (a int) engine=innodb; +--save_master_pos + +--connection slave +# Using ER_UNKNOWN_STORAGE_ENGINE wont work +let $slave_sql_errno= 1286; +--source include/wait_for_slave_sql_error_and_skip.inc +--sync_with_master + +--let $assert_text= Status should be 'Slave has read all relay log...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" +#Like "Slave has read all relay log%" +--source include/rpl_assert.inc + +show tables; +show create table t2; +--error ER_NO_SUCH_TABLE +show create table t1; +--error ER_NO_SUCH_TABLE +show create table t3; + +--connection master +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + + +CALL mtr.add_suppression('Slave: Unknown storage engine .* Error_code: 1286'); +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt b/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt new file mode 100644 index 00000000..db53e17d --- /dev/null +++ b/mysql-test/suite/rpl/t/myisam_external_lock-slave.opt @@ -0,0 +1,2 @@ +--log-slave-updates=0 +--skip_external_locking=0 diff --git a/mysql-test/suite/rpl/t/myisam_external_lock.test b/mysql-test/suite/rpl/t/myisam_external_lock.test new file mode 100644 index 00000000..14824fd8 --- /dev/null +++ b/mysql-test/suite/rpl/t/myisam_external_lock.test @@ -0,0 +1,24 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# +# MDEV-6871 Multi-value insert on MyISAM table that makes slaves crash +# This only happens if external_lock is enabled +# + +drop table if exists t1; +CREATE TABLE `t1` (`col1` int(11) NOT NULL,`col2` int(11) NOT NULL, + PRIMARY KEY (`col1`,`col2`), + KEY `col2` (`col2`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO `t1` VALUES (2775,974),(2775,975),(2775,976),(2778,977),(2778,978),(2782,979),(2790,986),(2790,1139),(2792,840),(2792,984),(2792,989),(2793,982),(2793,992),(2793,993),(2793,994),(2795,323),(2795,332),(2797,980),(2797,997),(2797,998),(2798,1103),(2798,1104),(2799,841),(2799,985),(2799,988),(2833,983),(2833,990),(2833,991),(2834,981),(2834,995),(2834,996),(2835,316),(2835,317),(3007,854),(3007,856),(3008,855),(3008,857),(3009,823),(3009,824),(3014,1),(3015,1),(3016,2),(3017,2),(3018,3),(3019,3),(3024,842),(3024,843),(3024,844),(3025,845),(3025,846),(3025,847),(3040,31),(3041,32),(3042,52),(3042,55),(3043,53),(3043,54),(3044,278),(3044,279),(3044,280),(3044,281),(3044,282),(3044,283),(3044,284),(3044,285),(3045,1),(3046,1),(3049,220),(3050,221),(3050,222),(3051,2),(3052,2),(3053,223),(3054,224),(3055,225),(3056,226),(3057,227),(3058,228),(3059,229),(3060,327),(3066,236),(3067,237),(3068,238),(3069,239),(3070,240),(3080,241),(3081,242),(3082,247),(3083,248),(3084,249),(3085,250),(3086,251),(3087,252),(3088,253),(3089,254),(3090,255),(3091,256),(3092,257),(3093,258),(3094,259),(3096,263),(3097,264),(3100,273),(3100,302),(3101,266),(3102,267),(3103,268),(3104,269),(3105,270),(3111,275),(3112,238),(3113,272),(3115,286),(3116,318),(3116,319),(3117,290),(3117,292),(3118,238),(3119,291),(3119,293),(3120,304),(3121,305),(3122,306),(3123,307),(3124,308),(3125,309),(3126,310),(3127,311),(3128,312),(3128,336),(3129,313),(3129,350),(3130,314),(3131,315),(3131,351),(3132,325),(3132,328),(3134,502),(3138,334),(3139,338),(3139,339),(3140,340),(3140,341),(3141,344),(3141,345),(3142,346),(3142,347),(3149,351),(3149,354),(3150,351),(3150,356),(3152,358),(3152,359),(3153,361),(3153,370),(3154,363),(3154,369),(3156,350),(3156,371),(3159,376),(3160,377),(3160,379),(3160,384),(3161,378),(3161,380),(3161,383),(3162,388),(3162,389),(3162,390),(3169,392),(3169,393),(3169,394),(3170,395),(3170,396),(3170,397),(3171,398),(3171,399),(3171,400),(3172,401),(3172,402),(3172,403),(3173,404),(3173,405),(3173,406),(3178,351),(3178,421),(3190,411),(3190,412),(3191,413),(3191,414),(3192,415),(3192,416),(3193,417),(3193,418),(3194,419),(3194,420),(3195,353),(3195,424),(3196,425),(3196,426),(3197,427),(3197,428),(3198,429),(3198,430),(3199,431),(3199,432),(3200,433),(3200,434),(3201,435),(3201,436),(3202,437),(3202,438),(3203,439),(3203,440),(3204,441),(3204,442),(3205,443),(3205,444),(3206,445),(3206,446),(3207,447),(3207,448),(3208,449),(3208,450),(3209,451),(3209,452),(3210,453),(3210,454),(3211,455),(3211,456),(3212,457),(3212,458),(3213,459),(3213,460),(3214,461),(3214,462),(3215,463),(3215,464),(3218,466),(3218,467),(3218,468),(3219,469),(3219,470),(3219,471),(3220,474),(3220,475),(3220,476),(3221,477),(3221,478),(3221,479),(3222,480),(3222,481),(3223,482),(3223,483),(3224,484),(3224,485),(3225,486),(3225,487),(3227,503),(3227,505),(3228,506),(3228,507),(3230,508),(3230,509),(3231,510),(3231,511),(3232,512),(3232,513),(3233,514),(3233,515),(3234,516),(3234,517),(3235,518),(3235,519),(3237,521),(3237,522),(3239,524),(3239,525),(3240,526),(3240,527),(3241,528),(3241,529),(3242,530),(3242,531),(3243,532),(3243,533),(3244,534),(3244,535),(3245,536),(3245,537),(3246,538),(3246,539),(3252,540),(3252,541),(3254,543),(3254,544),(3254,545),(3255,547),(3255,548),(3255,571),(3256,550),(3256,551),(3256,572),(3257,553),(3257,554),(3257,573),(3258,556),(3258,557),(3258,574),(3259,559),(3259,560),(3259,575),(3260,561),(3260,562),(3260,563),(3261,565),(3261,576),(3262,566),(3262,567),(3263,568),(3263,569),(3263,570),(3264,577),(3264,578),(3265,579),(3265,580),(3266,581),(3266,582),(3266,591),(3267,583),(3267,584),(3267,592),(3268,585),(3268,586),(3268,593),(3269,587),(3269,588),(3269,594),(3270,589),(3270,590),(3271,595),(3271,596),(3271,597),(3272,598),(3272,599),(3273,600),(3273,601),(3273,602),(3274,603),(3274,604),(3274,605),(3275,606),(3275,607),(3275,608),(3276,609),(3276,610),(3276,611),(3277,612),(3277,613),(3277,614),(3278,615),(3278,616),(3279,617),(3279,618),(3279,619),(3279,628),(3279,629),(3280,620),(3280,621),(3280,622),(3281,623),(3281,624),(3281,625),(3282,626),(3282,825),(3283,630),(3283,631),(3284,632),(3284,633),(3284,634),(3285,635),(3285,940),(3286,638),(3286,639),(3286,640),(3287,641),(3287,642),(3287,643),(3288,644),(3288,645),(3288,646),(3289,647),(3289,648),(3289,649),(3290,650),(3290,651),(3290,652),(3291,653),(3291,654),(3291,655),(3292,656),(3292,657),(3292,658),(3293,659),(3293,660),(3293,661),(3294,662),(3294,663),(3294,664),(3295,665),(3295,666),(3295,667),(3296,668),(3296,669),(3296,670),(3297,671),(3297,672),(3297,673),(3298,674),(3298,675),(3298,676),(3299,677),(3299,678),(3299,679),(3300,680),(3300,681),(3300,682),(3301,683),(3301,684),(3301,685),(3302,686),(3302,687),(3302,688),(3303,689),(3303,690),(3303,691),(3304,692),(3304,693),(3304,694),(3305,695),(3305,696),(3305,697),(3306,698),(3306,699),(3306,700),(3307,701),(3307,702),(3307,703),(3308,704),(3308,705),(3308,706),(3309,707),(3309,708),(3310,709),(3310,710),(3311,711),(3311,712),(3311,713),(3312,714),(3312,715),(3312,716),(3313,717),(3313,1167),(3314,720),(3314,721),(3314,722),(3315,723),(3315,724),(3315,725),(3316,726),(3316,727),(3316,728),(3317,729),(3317,730),(3317,731),(3318,732),(3318,733),(3318,734),(3319,735),(3319,736),(3319,737),(3320,738),(3320,739),(3320,740),(3321,741),(3321,742),(3322,743),(3322,744),(3323,745),(3323,746),(3323,747),(3324,748),(3324,749),(3324,750),(3325,751),(3325,752),(3325,753),(3326,754),(3326,755),(3327,756),(3327,757),(3328,758),(3328,789),(3329,761),(3329,790),(3330,762),(3330,763),(3331,768),(3331,785),(3331,786),(3332,769),(3332,783),(3332,784),(3335,766),(3336,767),(3343,770),(3343,771),(3344,772),(3344,773),(3345,774),(3345,775),(3347,776),(3347,777),(3347,987),(3348,778),(3348,779),(3349,780),(3372,781),(3372,782),(3373,787),(3373,788),(3376,791),(3376,792),(3377,793),(3377,794),(3378,799),(3378,800),(3379,801),(3379,802),(3380,795),(3380,796),(3381,797),(3381,798),(3383,805),(3384,806),(3384,807),(3385,808),(3385,809),(3386,810),(3386,811),(3387,812),(3387,814),(3388,815),(3388,816),(3391,817),(3391,818),(3391,819),(3392,820),(3392,821),(3392,822),(3393,826),(3393,827),(3394,828),(3394,829),(3395,830),(3395,831),(3396,834),(3396,835),(3397,832),(3397,833),(3398,836),(3398,837),(3399,838),(3399,839),(3410,850),(3410,851),(3411,852),(3411,853),(3412,848),(3412,849),(3419,860),(3419,951),(3420,859),(3420,861),(3422,862),(3422,863),(3423,864),(3423,865),(3424,866),(3424,867),(3424,872),(3424,873),(3425,868),(3425,869),(3425,874),(3425,875),(3426,878),(3426,879),(3427,876),(3427,877),(3428,880),(3432,884),(3432,885),(3432,886),(3434,887),(3434,888),(3434,889),(3441,894),(3441,895),(3442,896),(3442,897),(3444,904),(3445,905),(3449,906),(3449,907),(3450,908),(3450,909),(3453,910),(3458,915),(3458,916),(3459,917),(3459,918),(3463,919),(3463,920),(3485,929),(3486,930),(3487,931),(3488,932),(3489,933),(3493,2),(3494,2),(3501,934),(3502,936),(3503,938),(3504,939),(3505,941),(3506,942),(3507,943),(3508,944),(3509,945),(3510,946),(3511,947),(3512,948),(3514,949),(3514,950),(3515,953),(3516,954),(3517,955),(3518,956),(3519,957),(3520,958),(3521,959),(3527,960),(3527,965),(3528,961),(3528,962),(3529,963),(3529,964),(3530,966),(3530,967),(3531,968),(3531,969),(3535,970),(3535,971),(3536,972),(3536,973),(3540,999),(3540,1000),(3541,1001),(8888,9999); + +drop table t1; + +save_master_pos; +connection slave; +sync_with_master; + +connection master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test b/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test new file mode 100644 index 00000000..2b6d0791 --- /dev/null +++ b/mysql-test/suite/rpl/t/mysql-wsrep#110-2.test @@ -0,0 +1,44 @@ +# +# codership/mysql-wsrep/110 - Assertion `table_found' failed in unpack_row() with SAVEPOINT, trigger, error handler +# + +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY); +CREATE TABLE t3 (f1 INTEGER PRIMARY KEY); + +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CALL p1(NEW.f1); + +DELIMITER |; + +CREATE PROCEDURE p1 (IN x INT) +BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK TO event_logging; + INSERT t3 VALUES (x); + END; + SAVEPOINT event_logging; + + INSERT INTO t2 VALUES (x); + + RELEASE SAVEPOINT event_logging; +END| +DELIMITER ;| + +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); + + +DROP TABLE t3; +DROP TABLE t2; +DROP TABLE t1; + +DROP PROCEDURE p1; + +sync_slave_with_master; +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/parallel_backup.test b/mysql-test/suite/rpl/t/parallel_backup.test new file mode 100644 index 00000000..6ed182c0 --- /dev/null +++ b/mysql-test/suite/rpl/t/parallel_backup.test @@ -0,0 +1,75 @@ +--source include/have_innodb.inc +# The test is not format specific, MIXED is required to optimize testing time +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-21953: deadlock between BACKUP STAGE BLOCK_COMMIT and parallel +--echo # replication +--echo # + +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE = innodb; + +--sync_slave_with_master +--source include/stop_slave.inc +SET @old_parallel_threads= @@GLOBAL.slave_parallel_threads; +SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode; +SET @@global.slave_parallel_threads= 2; +SET @@global.slave_parallel_mode = 'optimistic'; + +--connection master +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +--save_master_pos + +# The plot: +# Block the 1st of two workers and, at waiting-for-prior-commit by the 2nd, +# issue BACKUP commands. +# BLOCK_COMMIT may hang so it is --send. +# Release the 1st worker to observe a deadlock unless its fixed. + +--connect (aux_slave,127.0.0.1,root,,test,$SLAVE_MYPORT,) +BEGIN; +# block the 1st worker and wait for the 2nd ready to commit +INSERT INTO t1 VALUES (1); + +--connection slave +--source include/start_slave.inc + +--connection aux_slave +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +# While the 1st worker is locked out run backup +--connect (backup_slave,127.0.0.1,root,,test,$SLAVE_MYPORT,) +BACKUP STAGE START; +--send BACKUP STAGE BLOCK_COMMIT + +# release the 1st work +--connection aux_slave +--sleep 1 +ROLLBACK; + +--connection backup_slave +--reap +BACKUP STAGE END; + +--connection slave +--sync_with_master + +--let $diff_tables= master:t1,slave:t1 +--source include/diff_tables.inc + + +# Clean up. +--connection slave +--source include/stop_slave.inc +SET @@global.slave_parallel_threads= @old_parallel_threads; +SET @@global.slave_parallel_mode = @old_parallel_mode; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/password_expiration.test b/mysql-test/suite/rpl/t/password_expiration.test new file mode 100644 index 00000000..6934500c --- /dev/null +++ b/mysql-test/suite/rpl/t/password_expiration.test @@ -0,0 +1,53 @@ +# +# Test a slave connection is properly handled when the replication +# user has an expired password +# + +--source include/not_embedded.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc + +--connection master +create user 'repl_user' password expire; +grant replication slave on *.* to repl_user; +flush privileges; +set global disconnect_on_expired_password=ON; + +--connection slave +--let $master_user= query_get_value(SHOW SLAVE STATUS, Master_User, 1) +CHANGE MASTER TO MASTER_USER= 'repl_user'; + +START SLAVE; +# ER_MUST_CHANGE_PASSWORD_LOGIN +--let $slave_io_errno= 1862 +--source include/wait_for_slave_io_error.inc + +# restart slave +--source include/stop_slave_sql.inc +RESET SLAVE; + +--connection master +# force sandbox mode for repl_user +set global disconnect_on_expired_password=OFF; + +--connection slave +START SLAVE; +# ER_MUST_CHANGE_PASSWORD +--let $slave_io_errno= 1820 +--source include/wait_for_slave_io_error.inc + +--connection master +DROP USER 'repl_user'; +set global disconnect_on_expired_password=default; + +--connection slave +--source include/stop_slave_sql.inc +eval CHANGE MASTER TO MASTER_USER='$master_user'; +RESET SLAVE; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rename.test b/mysql-test/suite/rpl/t/rename.test new file mode 100644 index 00000000..ac499157 --- /dev/null +++ b/mysql-test/suite/rpl/t/rename.test @@ -0,0 +1,33 @@ +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-16229 Replication aborts with ER_VIEW_SELECT_TMPTABLE after +--echo # half-failed RENAME +--echo # + +CREATE TABLE t1 (a INT); +CREATE TEMPORARY TABLE t1 (b INT); +RENAME TABLE t1 TO tmp, tmp TO t1; +SHOW CREATE TABLE t1; +--error ER_VIEW_SELECT_TMPTABLE +CREATE VIEW v AS SELECT * FROM t1; + +RENAME TABLE t1 TO tmp, t1 TO t2; +SHOW CREATE TABLE tmp; +SHOW CREATE TABLE t2; +--error ER_VIEW_SELECT_TMPTABLE +CREATE VIEW v AS SELECT * FROM tmp; +CREATE VIEW v AS SELECT * FROM t2; + +--sync_slave_with_master + +# Cleanup + +--connection master + +DROP VIEW v; +DROP TABLE tmp; +DROP TABLE t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/replace.test b/mysql-test/suite/rpl/t/replace.test new file mode 100644 index 00000000..36afda0d --- /dev/null +++ b/mysql-test/suite/rpl/t/replace.test @@ -0,0 +1,24 @@ +# +# Test of REPLACE with replication +# + +source include/master-slave.inc; + +# +# Test of doing replace on unique key on table with auto_increment +# + +drop table if exists t1; +CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136; +insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0); +select * from t1; +replace into t1 (pr_page, pr_type,test) values(1,"one",2); +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +# End of 5.5 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_000010-slave.opt b/mysql-test/suite/rpl/t/rpl_000010-slave.opt new file mode 100644 index 00000000..cbd77ee2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000010-slave.opt @@ -0,0 +1 @@ +--debug-disconnect-slave-event-count=2 diff --git a/mysql-test/suite/rpl/t/rpl_000010.test b/mysql-test/suite/rpl/t/rpl_000010.test new file mode 100644 index 00000000..de6337dd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000010.test @@ -0,0 +1,16 @@ +# This tests the offset off by 22 mystery bug +# Must run slave with --disconnect-slave-event-count=1 --master-connect-retry=1 + +source include/master-slave.inc; + +create table t1 (n int not null auto_increment primary key); +insert into t1 values(NULL); +insert into t1 values(2); +sync_slave_with_master; +select n from t1; +connection master; +drop table t1; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_000011-slave.opt b/mysql-test/suite/rpl/t/rpl_000011-slave.opt new file mode 100644 index 00000000..7c3d2411 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000011-slave.opt @@ -0,0 +1 @@ +--verbose=1 diff --git a/mysql-test/suite/rpl/t/rpl_000011.test b/mysql-test/suite/rpl/t/rpl_000011.test new file mode 100644 index 00000000..289b79f7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000011.test @@ -0,0 +1,34 @@ +# +# Test very simply slave replication (to ensure it works at all) +# In addition, test also: +# MDEV-5829 STOP SLAVE resets global status variables +# + +source include/master-slave.inc; +--connection slave +let $initial_com_insert= query_get_value(show global status like "Com_insert", Value, 1); +--connection master +create table t1 (n int); +insert into t1 values(1); +sync_slave_with_master; +let $current_com_insert= query_get_value(show global status like "Com_insert", Value, 1); +--let $delta_com_insert= `select $current_com_insert - $initial_com_insert from dual` +--echo # Com_insert = $delta_com_insert +stop slave; +let $current_com_insert= query_get_value(show global status like "Com_insert", Value, 1); +--let $delta_com_insert= `select $current_com_insert - $initial_com_insert from dual` +--echo # Com_insert = $delta_com_insert +--source include/wait_for_slave_to_stop.inc +start slave; +--source include/wait_for_slave_to_start.inc +connection master; +insert into t1 values(2); +#let slave catch up +sync_slave_with_master; +select * from t1; +connection master; +drop table t1; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_000013.test b/mysql-test/suite/rpl/t/rpl_000013.test new file mode 100644 index 00000000..9f1b0666 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000013.test @@ -0,0 +1,55 @@ +# This test is to verify that DROP TEMPORARY TABLE +# is automatically binlogged and sent to slave +# when a temp table is dropped by disconnection +# of a master's conection. +# So it does not apply to row-based, where we neither need +# nor do this automatic binlogging. And if we run this test +# in row-based, it hangs waiting for an offset which is never +# reached (the "sync_with_master 1"), logically. + +--source include/have_binlog_format_mixed_or_statement.inc +source include/master-slave.inc; + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +create table t2(n int); +create temporary table t1 (n int); +insert into t1 values(1),(2),(3); +--disable_warnings +insert into t2 select * from t1; +--enable_warnings +connection master1; +create temporary table t1 (n int); +insert into t1 values (4),(5); +--disable_warnings +insert into t2 select * from t1 as t10; +--enable_warnings +save_master_pos; +disconnect master; +connection slave; +#add 1 to catch drop table +sync_with_master 1; +connection master1; +insert into t2 values(6); +save_master_pos; +disconnect master1; +connection slave; +# same trick to go one more event +sync_with_master 1; +select * from t2; +show status like 'Slave_open_temp_tables'; +# +# Clean up +# +connect (master2,localhost,root,,); +connection master2; + +# We will get a warning for t1 as this is a temporary table that doesn't +# exist in this connection. + +drop table if exists t1,t2; + +--source include/rpl_end.inc +# End of 4.1 tests diff --git a/mysql-test/suite/rpl/t/rpl_000017.test b/mysql-test/suite/rpl/t/rpl_000017.test new file mode 100644 index 00000000..893117e6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_000017.test @@ -0,0 +1,47 @@ +# ==== Purpose ==== +# +# Unknown. +# +# ==== Notes ==== +# +# This test uses the -slave.opt file to start the slave with +# --skip-slave-start. + +--source include/not_windows.inc + +--let $rpl_skip_start_slave= 1 +--source include/master-slave.inc + +--connection slave +--let $slave_datadir= `SELECT @@datadir` + +--remove_file $slave_datadir/master.info +--write_file $slave_datadir/master.info +master-bin.000001 +4 +127.0.0.1 +replicate +aaaaaaaaaaaaaaab +$MASTER_MYPORT +1 +0 +EOF + +connection master; +grant replication slave on *.* to replicate@localhost identified by 'aaaaaaaaaaaaaaab'; +grant replication slave on *.* to replicate@127.0.0.1 identified by 'aaaaaaaaaaaaaaab'; +connection slave; +--source include/start_slave.inc + +connection master; +create table t1(n int); +insert into t1 values(24); +sync_slave_with_master; +select * from t1; +connection master; +drop table t1; +delete from mysql.user where user="replicate"; + +# End of 4.1 tests +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_15867.test b/mysql-test/suite/rpl/t/rpl_15867.test new file mode 100644 index 00000000..6de39041 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_15867.test @@ -0,0 +1,11 @@ +--source include/master-slave.inc +CREATE TEMPORARY TABLE t (i INT); +CREATE TABLE t AS SELECT * FROM t; + +--sync_slave_with_master + +# Cleanup +--connection master +DROP TEMPORARY TABLE t; +DROP TABLE t; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_15919-slave.opt b/mysql-test/suite/rpl/t/rpl_15919-slave.opt new file mode 100644 index 00000000..62ab6dad --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_15919-slave.opt @@ -0,0 +1 @@ +--lower_case_table_names=1 diff --git a/mysql-test/suite/rpl/t/rpl_15919.test b/mysql-test/suite/rpl/t/rpl_15919.test new file mode 100644 index 00000000..a5b25929 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_15919.test @@ -0,0 +1,18 @@ +--source include/have_case_sensitive_file_system.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection master +create table RPL(a int); +insert into RPL values(1); + +--sync_slave_with_master +select * from rpl; +insert into RPL values(3); +insert into rpl values(4); +select * from rpl; + +--connection master +drop table RPL; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_EE_err.test b/mysql-test/suite/rpl/t/rpl_EE_err.test new file mode 100644 index 00000000..b2ca3aac --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_EE_err.test @@ -0,0 +1,2 @@ +let $engine_type=myisam; +-- source include/rpl_EE_err.test diff --git a/mysql-test/suite/rpl/t/rpl_LD_INFILE.test b/mysql-test/suite/rpl/t/rpl_LD_INFILE.test new file mode 100644 index 00000000..0f02bdcc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_LD_INFILE.test @@ -0,0 +1,39 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +############################################################################# +# TEST: To test the LOAD DATA INFILE in rbr # +############################################################################# + +# Includes +-- source include/master-slave.inc + +# Begin clean up test section +--disable_warnings +connection master; +DROP TABLE IF EXISTS test.t1; +--enable_warnings + +# Section 1 test +CREATE TABLE test.t1 (a VARCHAR(255), PRIMARY KEY(a)); +LOAD DATA INFILE '../../std_data/words2.dat' INTO TABLE test.t1; +DELETE FROM test.t1 WHERE a = 'abashed'; +DELETE FROM test.t1; +LOAD DATA INFILE '../../std_data/words2.dat' INTO TABLE test.t1; + + +SELECT * FROM test.t1 ORDER BY a DESC; +save_master_pos; +sync_slave_with_master; +connection slave; +SELECT * FROM test.t1 ORDER BY a DESC; + +# Cleanup +#show binlog events; +connection master; +DROP TABLE test.t1; +sync_slave_with_master; + +# End of 5.0 test case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_alter.test b/mysql-test/suite/rpl/t/rpl_alter.test new file mode 100644 index 00000000..8b8bcfb3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter.test @@ -0,0 +1,71 @@ +source include/master-slave.inc; +create database mysqltest; + +create table mysqltest.t1 ( n int); +alter table mysqltest.t1 add m int; +insert into mysqltest.t1 values (1,2); +create table mysqltest.t2 (n int); +insert into mysqltest.t2 values (45); +rename table mysqltest.t2 to mysqltest.t3, mysqltest.t1 to mysqltest.t2; +sync_slave_with_master; +select * from mysqltest.t2; +select * from mysqltest.t3; +connection master; +drop database mysqltest; +sync_slave_with_master; + +# End of 4.1 tests + +connection master; +use test; + +--echo # +--echo # Test bug where ALTER TABLE MODIFY didn't replicate properly +--echo # + +create table t1 (a int unsigned primary key, b int); +show create table t1; +insert into t1 (a) values (1),((1<<32)-1); +select * from t1; +alter table t1 modify a bigint; +show create table t1; +select * from t1; +alter table t1 modify a int unsigned; +show create table t1; +select * from t1; +alter table t1 modify a bigint unsigned; +show create table t1; +select * from t1; +sync_slave_with_master; +use test; +select * from t1; +show create table t1; +connection master; +# +create table t2 (a int unsigned auto_increment primary key, b int); +show create table t2; +alter table t2 modify a bigint; +show create table t2; +alter table t2 modify a bigint auto_increment; +show create table t2; +drop table t1,t2; + +--echo # +--echo # MDEV-8432: Slave cannot replicate signed integer-type values +--echo # with high bit set to 1 +--echo # Test replication when we have int on master and bigint on slave +--echo # + +create table t1 (a int unsigned primary key, b int); +sync_slave_with_master; +SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY'; +alter table t1 modify a bigint unsigned; +connection master; +insert into t1 (a) values (1),((1<<32)-1); +sync_slave_with_master; +select * from t1; +SET GLOBAL SLAVE_TYPE_CONVERSIONS=''; +connection master; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_alter_db.test b/mysql-test/suite/rpl/t/rpl_alter_db.test new file mode 100644 index 00000000..f6f07825 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_db.test @@ -0,0 +1,15 @@ +source include/master-slave.inc; + +--echo ==== Verify that alter database does not stop replication ==== + +create database temp_db; +use temp_db; # to be different from initial `test' db of mysqltest client +alter database collate latin1_bin; + +sync_slave_with_master; + +--echo ==== Clean up ==== +connection master; +drop database temp_db; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test new file mode 100644 index 00000000..4e604787 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test @@ -0,0 +1,106 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--enable_connect_log +--connection master +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); + +--sync_slave_with_master +select * from t1 order by a; +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; + +--connection master +insert into t1 values(5); +insert into t1 values(6); + +--sync_slave_with_master +select * from t1 order by a; + + +--echo #UPDATE query + +--connection master +update t1 set a = a+10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a-10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #DELETE quert +--connection master +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #REPLACE query +--connection master +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); + +--sync_slave_with_master +select * from t1 order by a; + +--echo #SELECT query +--connection master +select * from t1 where a > 2 and a < 4; + +--connection slave +select * from t1 where a > 2 and a < 4; + +--echo #UPDATE with SELECT query +--connection master +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; + +--connection master + +--echo #entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; + +--connection slave +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +select * from t1 order by a; +alter table t1 drop column z4; +start slave; + +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master +select * from t1 order by a; + +--connection master +select * from t1 order by a; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_alter_instant.test b/mysql-test/suite/rpl/t/rpl_alter_instant.test new file mode 100644 index 00000000..260f7e92 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_instant.test @@ -0,0 +1,50 @@ +source include/have_innodb.inc; +source include/master-slave.inc; + +use test; +create table t1 (id int primary key, c1 int default 10, c2 varchar(20) default 'holiday') engine = innodb; + +insert into t1 values(1, 12345, 'abcde'), (2, default, default), (3, 23456, 'xyzab'); + +set time_zone='+03:00'; +set timestamp = 1; +alter table t1 add column d1 timestamp not null default current_timestamp; + +select * from t1; +sync_slave_with_master; + +connection slave; +set time_zone='+03:00'; +select * from t1; + +connection master; +alter table t1 add column d2 timestamp not null default current_timestamp, ALGORITHM=copy; + +sync_slave_with_master; + +connection slave; +select * from t1; + +connection master; +drop table t1; + + +# datetime +create table t4 (id int primary key, c2 int); +insert into t4 values(1,1),(2,2),(3,3); +set timestamp = 1000; +alter table t4 add column (c3 datetime default current_timestamp(), c4 timestamp not null default current_timestamp()); +select * from t4; +alter table t4 add column c5 time not null default current_timestamp(); +alter table t4 add column c6 date not null default current_timestamp(); + +select * from t4; +sync_slave_with_master; + +connection slave; +select * from t4; + +connection master; +drop table t4; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt b/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt new file mode 100644 index 00000000..a8a6af19 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment-master.opt @@ -0,0 +1 @@ +--auto-increment-increment=10 --auto-increment-offset=2 diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt new file mode 100644 index 00000000..79ed6f96 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t_ignored1 diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment.test b/mysql-test/suite/rpl/t/rpl_auto_increment.test new file mode 100644 index 00000000..6d01fdb8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment.test @@ -0,0 +1,7 @@ +##################################### +# Wrapper for rpl_auto_increment.test# +##################################### +-- source include/have_innodb.inc +let $engine_type=innodb; +let $engine_type2=myisam; +-- source include/rpl_auto_increment.test diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test new file mode 100644 index 00000000..1e5f9e53 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test @@ -0,0 +1,66 @@ +# +# Test of auto_increment +# BUG#11932 +# +# Bug reported that master and slave get out of sync after TRUNCATE +# TABLE. +# +# Test supplied by Are Casilla + +source include/master-slave.inc; +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); +--disable_warnings +connection master; +drop database if exists test1; +--enable_warnings +create database test1; +use test1; + +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL auto_increment, + `fname` varchar(100) default NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; + +INSERT INTO `t1` VALUES (1, 'blablabla'); + +CREATE TABLE `t2` ( + `id` int(10) NOT NULL auto_increment, + `comment` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=3 ; + +INSERT INTO `t2` VALUES (1, 'testtest 1'); +INSERT INTO `t2` VALUES (2, 'test 2'); + +DELIMITER $; +CREATE PROCEDURE simpleproc3 () + NOT DETERMINISTIC + BEGIN + INSERT INTO t1 (fname) (SELECT t2.comment FROM t2 WHERE t2.id = '1'); + INSERT INTO t1 (fname) VALUES('test'); + END + $ +DELIMITER ;$ + +--disable_warnings +CALL simpleproc3(); +--enable_warnings + +select * from t2; + +TRUNCATE TABLE `t1`; +--disable_warnings +CALL simpleproc3(); +--enable_warnings + +select * from t1; + +sync_slave_with_master; + +use test1; +select * from t1; + +connection master; +drop database test1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test b/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test new file mode 100644 index 00000000..6f7e0d80 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment_bug33029.test @@ -0,0 +1,60 @@ +# BUG#33029 5.0 to 5.1 replication fails on dup key when inserting +# using a trig in SP + +# For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12 exclusive, +# if one statement in a SP generated AUTO_INCREMENT value by the top +# statement, all statements after it would be considered generated +# AUTO_INCREMENT value by the top statement, and a erroneous INSERT_ID +# value might be associated with these statement, which could cause +# duplicate entry error and stop the slave. + +# Test if the slave can replicate from such a buggy master + +# The bug33029-slave-relay-bin.000001 file is the +# slave-replay-bin.000003 file generated by run the +# rpl_auto_increment_bug33029.test with clean up statements at the end +# of the test case removed on a buggy 5.0 server + +--let $rpl_skip_start_slave= 1 +--source include/master-slave.inc + +--echo ==== Initialize ==== +--connection slave + +# The binlog we read does funny things with triggers and causes this warning. +--disable_query_log +CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); +--enable_query_log + +# Need to restore this at the end; CHANGE MASTER modifies it (see the +# manual for CHANGE MASTER). +SET @old_relay_log_purge= @@global.relay_log_purge; + +# the relay log contains create t1, t2 tables and load data infile +--let $fake_relay_log = $MYSQL_TEST_DIR/std_data/bug33029-slave-relay-bin.000001 +--source include/setup_fake_relay_log.inc + +--echo ==== Test ==== +start slave sql_thread; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= 3776 +--source include/wait_for_slave_param.inc + + +echo # Result on slave; +SELECT * FROM t1; +SELECT * FROM t2; + +--echo ==== Clean up ==== + +stop slave sql_thread; +--source include/cleanup_fake_relay_log.inc + +DROP TABLE t1, t2; +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; + +SET @@global.relay_log_purge= @old_relay_log_purge; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test new file mode 100644 index 00000000..32f08be7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test @@ -0,0 +1,62 @@ +# Test of auto-increment. +# +# BUG#11754117-45670 +# Multipart primary key with the autoincrement part not first in it +# is replication unsafe. +# + +source include/have_binlog_format_mixed.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); + +--connection master +create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam; +--error ER_WRONG_AUTO_KEY +create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb; +create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb; + +set @@binlog_format=statement; +--echo *** autoincrement field is not the first in PK warning must be there: *** +insert into tm set b=null, a=1; +show warnings; +--echo *** no warning when autoincrement is the first in PK +insert into ti set b=null, a=1; +show warnings; + +delimiter //; +create function multi_part_pk_with_autoinc (arg int) +returns int +begin + insert into tm set b=null, a=arg; + return arg; +end// +delimiter ;// + +select multi_part_pk_with_autoinc (3); +--echo *** autoincrement field is not the first in PK warning must be there: *** +show warnings; + +set @@binlog_format=mixed; +insert into tm set b=null, a=2; + +sync_slave_with_master; + +if (`select count(*) <> 3 from tm`) +{ + --echo Wrong result from SELECT on the slave side. + select * from tm; + --die +} + +# cleanup + +--connection master + +drop table tm, ti; +drop function multi_part_pk_with_autoinc; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test b/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test new file mode 100644 index 00000000..82db8f08 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment_update_failure.test @@ -0,0 +1,211 @@ +# +# Bug45677 +# This test verifies the following two properties: +# P1) insert/update in an autoinc column causes statement to +# be logged in row format if binlog_format=mixed. +# P2) if binlog_format=mixed, and a trigger or function contains +# two or more inserts/updates in a table that has an autoinc +# column, then the slave should not go out of sync, even if +# there are concurrent transactions. +# +# Property (P1) is tested by executing an insert and an update on +# a table that has an autoinc column, and verifying that these +# statements result in row events in the binlog. +# Property (P2) is tested by setting up the test scenario and +# verifying that the tables are identical on master and slave. +# + +source include/have_binlog_format_mixed.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +--echo # Test case1: INVOKES A TRIGGER with after insert action +let $trigger_action = after insert; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case2: INVOKES A TRIGGER with before insert action +let $trigger_action = before insert; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case3: INVOKES A TRIGGER with after update action +let $trigger_action = after update; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case4: INVOKES A TRIGGER with before update action +let $trigger_action = before update; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case5: INVOKES A TRIGGER with after delete action +let $trigger_action = after delete; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case6: INVOKES A TRIGGER with before delete action +let $trigger_action = before delete; +source include/rpl_auto_increment_invoke_trigger.test; + +--echo # Test case7: CALLS A FUNCTION which INVOKES A TRIGGER with after insert action +let $insert_action = after insert; +source include/rpl_autoinc_func_invokes_trigger.test; + +--echo # Test case8: CALLS A FUNCTION which INVOKES A TRIGGER with before insert action +let $insert_action = before insert; +source include/rpl_autoinc_func_invokes_trigger.test; + +--echo # Test case9: INSERT DATA INTO VIEW WHICH INVOKES TRIGGERS with after insert action +let $insert_action = after insert; +source include/rpl_auto_increment_insert_view.test; + +--echo # Test case10: INSERT DATA INTO VIEW WHICH INVOKES TRIGGERS with before insert action +let $insert_action = before insert; +source include/rpl_auto_increment_insert_view.test; + +--echo # Test case11: INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES INTO A TABLE WITH AUTOINC COLUMN +connection master; +create table t1(a int) engine=innodb; +create table t2(i1 int not null auto_increment, a int, primary key(i1)) engine=innodb; +delimiter //; +CREATE FUNCTION f1_two_inserts() RETURNS INTEGER +BEGIN + INSERT INTO t2(a) values(2); + INSERT INTO t2(a) values(2); + RETURN 1; +END// +delimiter ;// +begin; +insert into t1(a) values(f1_two_inserts()); + +connection master1; +#The default autocommit is set to 1, so the statement is auto committed +insert into t2(a) values(4),(5); + +connection master; +commit; +insert into t1(a) values(f1_two_inserts()); +commit; + +connection master; +--echo #Test result for INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES on master +select * from t2 ORDER BY i1; + +sync_slave_with_master; +connection slave; +--echo #Test result for INVOKES A FUNCTION TO INSERT TWO OR MORE VALUES on slave +select * from t2 ORDER BY i1; + +connection master; +drop table t1; +drop table t2; +drop function f1_two_inserts; +sync_slave_with_master; + +--echo # Test case12: INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES OF A TABLE WITH AUTOINC COLUMN +connection master; +create table t1(a int) engine=innodb; +create table t2(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb; +delimiter //; +CREATE FUNCTION f1_two_updates() RETURNS INTEGER +BEGIN + update t2 set a = a + 5 where b = 1; + update t2 set a = a + 5 where b = 2; + update t2 set a = a + 5 where b = 3; + update t2 set a = a + 5 where b = 4; + RETURN 1; +END// +delimiter ;// + +connection master1; +#The default autocommit is set to 1, so the statement is auto committed +insert into t2(a,b) values(1,1); +insert into t2(a,b) values(2,2); +insert into t2(a,b) values(3,3); +insert into t2(a,b) values(4,4); +insert into t1(a) values(f1_two_updates()); + +connection master; +begin; +insert into t1(a) values(f1_two_updates()); +commit; + +connection master; +--echo #Test result for INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES on master +select * from t2 ORDER BY i1; + +sync_slave_with_master; +connection slave; +--echo #Test result for INVOKES A FUNCTION TO UPDATE TWO OR MORE VALUES on slave +select * from t2 ORDER BY i1; + +connection master; +drop table t1; +drop table t2; +drop function f1_two_updates; +sync_slave_with_master; + +--echo # Test case13: UPDATE MORE THAN ONE TABLES ON TOP-STATEMENT +connection master; +create table t1(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb; +create table t2(i1 int not null auto_increment, a int, b int, primary key(i1)) engine=innodb; +begin; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t1(a,b) values(1,1),(2,2); +insert into t2(a,b) values(1,1),(2,2); +update t1,t2 set t1.a=t1.a+5, t2.a=t2.a+5 where t1.b=t2.b; +insert into t1(a,b) values(3,3); +insert into t2(a,b) values(3,3); +commit; +--echo # To verify if it works fine when these statements are not be marked as unsafe +source include/show_binlog_events.inc; + +sync_slave_with_master; +--echo #Test if the results are consistent on master and slave +--echo #for 'UPDATE MORE THAN ONE TABLES ON TOP-STATEMENT' +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; +let $diff_tables= master:t2, slave:t2; +source include/diff_tables.inc; + +connection master; +drop table t1; +drop table t2; +sync_slave_with_master; + +--echo # Test case14: INSERT DATA INTO VIEW WHICH INVOLVED MORE THAN ONE TABLES +connection master; +CREATE TABLE t1(i1 int not null auto_increment, c1 INT, primary key(i1)) engine=innodb; +CREATE TABLE t2(i1 int not null auto_increment, c2 INT, primary key(i1)) engine=innodb; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +begin; +INSERT INTO t1(c1) VALUES (11), (12); +INSERT INTO t2(c2) VALUES (13), (14); + +CREATE VIEW v15 AS SELECT c1, c2 FROM t1, t2; + +INSERT INTO v15(c1) VALUES (15),(16); +INSERT INTO v15(c2) VALUES (17),(18); + +connection master1; +INSERT INTO v15(c1) VALUES (19),(20); +INSERT INTO v15(c2) VALUES (21),(22); + +connection master; +INSERT INTO v15(c1) VALUES (23), (24); +INSERT INTO v15(c2) VALUES (25), (26); +commit; +--echo # To verify if it works fine when these statements are not be marked as unsafe +source include/show_binlog_events.inc; + +sync_slave_with_master; +--echo #Test if the results are consistent on master and slave +--echo #for 'INSERT DATA INTO VIEW WHICH INVOLVED MORE THAN ONE TABLES' +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; +let $diff_tables= master:t2, slave:t2; +source include/diff_tables.inc; + +connection master; +drop table t1; +drop table t2; +drop view v15; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test new file mode 100644 index 00000000..a93fcbac --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test @@ -0,0 +1,87 @@ +############################################################################### +# Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK +# +# Problem: +# ======== +# 1) Drop table queries are re-generated by server +# before writing the events(queries) into binlog +# for various reasons. If table name/db name contains +# a non regular characters (like latin characters), +# the generated query is wrong. Hence it breaks the +# replication. +# 2) In the edge case, when table name contains +# 64 latin characters (latin takes 2 bytes), server is +# throwing an assert (M_TBLLEN < 128) +# +# 3) In the edge case, when db name contains 64 latin +# characters, binlog contents are interpreted wrongly +# which is leading to replication issues. +# +############################################################################### + +--source include/not_windows.inc +--source include/master-slave.inc + +--let iter=1 +# Change iteration to 4 after fixing Bug #22280214 +while ($iter <= 2) +{ + --connection master + if ($iter == 1) + { + --echo Test case 1:- table name with one character latin name. + --let $tblname= REPEAT(CHAR(131),1) + } + if ($iter == 2) + { + --echo Test case 2:- table name and database names with one character latin name. + --let $tblname= REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1) + --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`") + PREPARE STMT FROM @s; EXECUTE stmt; + } + # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING + # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be + # uncommented. + #if ($iter == 3) + #{ + # --echo Test case 3:- table name and database names with 64 latin characters name. + # --let $tblname= REPEAT(CHAR(131),64),"`.`", REPEAT(CHAR(131),64) + # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + #if ($iter == 4) + #{ + # --echo Test case 4:- table name and database names with 64 Euro(€) characters. + # --let $tblname= REPEAT(CHAR(226,130,172),64),"`.`", REPEAT(CHAR(226,130,172),64) + # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(226,130,172),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + --eval SET @s:=CONCAT("CREATE TABLE `",$tblname,"` (a INT)") + PREPARE STMT FROM @s; EXECUTE stmt; + --eval SET @s:=CONCAT("INSERT INTO `",$tblname,"` VALUES (1)") + PREPARE STMT FROM @s; EXECUTE stmt; + --eval SET @s:=CONCAT("DROP TABLE `",$tblname, "`") + PREPARE STMT FROM @s; EXECUTE stmt; + if ($iter == 2) + { + --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`") + PREPARE STMT FROM @s; EXECUTE stmt; + } + # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING + # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be + # uncommented. + #if ($iter == 3) + #{ + # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + #if ($iter == 4) + #{ + # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(226,130,172),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + --sync_slave_with_master + --inc $iter +} + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt new file mode 100644 index 00000000..a8de78ed --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt @@ -0,0 +1 @@ +--loose-innodb --binlog-ignore-db=db2 diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt new file mode 100644 index 00000000..264b1728 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt @@ -0,0 +1 @@ +--loose-innodb --replicate-do-db=db1 diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test new file mode 100644 index 00000000..659f074e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test @@ -0,0 +1,173 @@ +source include/have_innodb.inc; +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +connection master; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +SET @@session.binlog_direct_non_transactional_updates= FALSE; + +disable_warnings; +DROP DATABASE IF EXISTS db1; +DROP DATABASE IF EXISTS db2; +enable_warnings; + +CREATE DATABASE db1; +CREATE DATABASE db2; + +use db1; + +CREATE TABLE db1.t1 (a INT) ENGINE=InnoDB; +CREATE TABLE db1.t2 (s CHAR(255)) ENGINE=MyISAM; + +sync_slave_with_master; +source include/stop_slave.inc; +connection master; + +DELIMITER //; +CREATE PROCEDURE db1.p1 () +BEGIN + INSERT INTO t1 VALUES (1); + INSERT INTO t1 VALUES (2); + INSERT INTO t1 VALUES (3); + INSERT INTO t1 VALUES (4); + INSERT INTO t1 VALUES (5); +END// + +CREATE PROCEDURE db1.p2 () +BEGIN + INSERT INTO t1 VALUES (6); + INSERT INTO t1 VALUES (7); + INSERT INTO t1 VALUES (8); + INSERT INTO t1 VALUES (9); + INSERT INTO t1 VALUES (10); + INSERT INTO t2 VALUES ('executed db1.p2()'); +END// +DELIMITER ;// + +INSERT INTO db1.t2 VALUES ('before call db1.p1()'); + +# Note: the master_log_pos is set to be the position of the BEGIN + 1, +# so before fix of BUG#43263 if the BEGIN is ignored, then all the +# INSERTS in p1 will be replicated in AUTOCOMMIT=1 mode and the slave +# SQL thread will stop right before the first INSERT. After fix of +# BUG#43263, BEGIN will not be ignored by the replication db rules, +# and then the whole transaction will be executed before slave SQL +# stop. +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_pos= `SELECT $master_pos + 1`; + +use test; +BEGIN; +CALL db1.p1(); +COMMIT; + +# The position where the following START SLAVE UNTIL will stop at +let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +INSERT INTO db1.t2 VALUES ('after call db1.p1()'); +SELECT * FROM db1.t1; +SELECT * FROM db1.t2; + +connection slave; + +replace_result $master_pos MASTER_POS; +eval start slave until master_log_file='master-bin.000001', master_log_pos=$master_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_sql_stop_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +let $result= query_get_value(SELECT $slave_sql_stop_pos - $master_end_trans_pos as result, result, 1); + +--echo # +--echo # If we got non-zero here, then we're suffering BUG#43263 +--echo # +eval SELECT $result as 'Must be 0'; +SELECT * from db1.t1; +SELECT * from db1.t2; + +connection master; + +INSERT INTO db1.t2 VALUES ('before call db1.p2()'); + +# See comments above. +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_pos= `SELECT $master_pos + 1`; + +BEGIN; +CALL db1.p2(); +disable_warnings; +ROLLBACK; +enable_warnings; +let $master_end_trans_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +INSERT INTO db1.t2 VALUES ('after call db1.p2()'); +SELECT * FROM db1.t1; +SELECT * FROM db1.t2; + +connection slave; + +replace_result $master_pos MASTER_POS; +eval start slave until master_log_file='master-bin.000001', master_log_pos=$master_pos; +source include/wait_for_slave_sql_to_stop.inc; + +let $slave_sql_stop_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +let $result= query_get_value(SELECT $slave_sql_stop_pos - $master_end_trans_pos as result, result, 1); + +--echo # +--echo # If we got non-zero here, then we're suffering BUG#43263 +--echo # +eval SELECT $result as 'Must be 0'; +SELECT * from db1.t1; +SELECT * from db1.t2; + +START SLAVE; +source include/wait_for_slave_sql_to_start.inc; + +--echo # +--echo # SAVEPOINT and ROLLBACK TO have the same problem in BUG#43263 +--echo # This was reported by BUG#50407 +connection master; +let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1); + +BEGIN; +INSERT INTO db1.t1 VALUES(20); + +--echo # +--echo # Verify whether this statement is binlogged correctly +/*comment*/ SAVEPOINT has_comment; +USE db1; +INSERT INTO db1.t1 VALUES(30); +INSERT INTO db1.t2 VALUES("in savepoint has_comment"); +USE db2; +SavePoint mixed_cases; +USE db1; +INSERT INTO db1.t2 VALUES("in savepoint mixed_cases"); +INSERT INTO db1.t1 VALUES(40); +USE db2; +ROLLBACK TO mixed_cases; +ROLLBACK TO has_comment; +USE db1; +INSERT INTO db1.t2 VALUES("after rollback to"); +INSERT INTO db1.t1 VALUES(50); +USE db2; +COMMIT; +source include/show_binlog_events.inc; +sync_slave_with_master; + +--echo # +--echo # Verify INSERT statements in savepoints are executed, for MyISAM table +--echo # is not effected by ROLLBACK TO +SELECT * FROM db1.t2 WHERE s LIKE '% savepoint %'; +--echo # +--echo # Verify INSERT statements on the Innodb table are rolled back; +SELECT * FROM db1.t1 WHERE a IN (30, 40); + +--echo # +--echo # Clean up +--echo # +connection master; +DROP DATABASE db1; +DROP DATABASE db2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_compress.test b/mysql-test/suite/rpl/t/rpl_binlog_compress.test new file mode 100644 index 00000000..ef1e4508 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_compress.test @@ -0,0 +1,61 @@ +# +# Test of compressed binlog with replication +# + +source include/master-slave.inc; + +set @old_log_bin_compress=@@log_bin_compress; +set @old_log_bin_compress_min_len=@@log_bin_compress_min_len; +set @old_binlog_format=@@binlog_format; +set @old_binlog_row_image=@@binlog_row_image; + +set global log_bin_compress=on; +set global log_bin_compress_min_len=10; + +drop table if exists t1; +CREATE TABLE t1 (pr_id int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, pr_page int(11) NOT NULL, pr_type varbinary(60) NOT NULL, test int, UNIQUE KEY pr_pagetype (pr_page,pr_type)) ENGINE=myisam AUTO_INCREMENT=136; + +set binlog_format=statement; +insert into t1 (pr_page, pr_type, test) values(1,"one",0),(2,"two",0); +replace into t1 (pr_page, pr_type,test) values(1,"one",2); +update t1 set test=test+1 where pr_page > 1; +delete from t1 where test=1; + +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; + + +set binlog_format=row; +insert into t1 (pr_page, pr_type, test) values(3,"three",0),(4,"four",4),(5, "five", 0); +replace into t1 (pr_page, pr_type,test) values(3,"one",2); +update t1 set test=test+1 where pr_page > 3; +delete from t1 where test=1; + +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; + + +set binlog_row_image=minimal; +insert into t1 (pr_page, pr_type, test) values(6,"six",0),(7,"seven",7),(8, "eight", 0); +replace into t1 (pr_page, pr_type,test) values(6,"six",2); +update t1 set test=test+1 where pr_page > 6; +delete from t1 where test=1; + +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +set global log_bin_compress=@old_log_bin_compress; +set global log_bin_compress_min_len=@old_log_bin_compress_min_len; +set binlog_format=@old_binlog_format; +set binlog_row_image=@old_binlog_row_image; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_corruption.test b/mysql-test/suite/rpl/t/rpl_binlog_corruption.test new file mode 100644 index 00000000..66b0c80f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_corruption.test @@ -0,0 +1,50 @@ +# ==== Purpose ==== +# +# Verify that the slave stops gracefully when reading a relay log with +# corrupted data. +# +# ==== Implementation ==== +# +# Setup "fake replication" where the slave only starts the SQL thread, +# not the IO thread, and reads from an existing relay log that has +# been prepared so that it contains the error. This requires some +# extra server options: see the -master.opt file. +# +# ==== Related bugs ==== +# +# BUG#31793: log event corruption causes crash +# BUG#40482: server/mysqlbinlog crashes when reading invalid Incident_log_event + +--source include/master-slave.inc + +# BUG#40482 only manifested itself in debug-compiled binaries. +-- source include/have_debug.inc + +--connection slave +call mtr.add_suppression('Found invalid event in binary log'); +call mtr.add_suppression('Slave SQL.*Relay log read failure: Could not parse relay log event entry.* 1594'); + +# +# BUG#40482: server/mysqlbinlog crashes when reading invalid Incident_log_event +# +# The relay log contains an Incident_log_event with a non-existing +# incident number. + +--echo ==== Initialize ==== +--source include/stop_slave.inc +RESET SLAVE; + +let $fake_relay_log= $MYSQL_TEST_DIR/std_data/bug40482-bin.000001; +source include/setup_fake_relay_log.inc; + +--echo ==== Test ==== +START SLAVE SQL_THREAD; +let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE +source include/wait_for_slave_sql_error.inc; +let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +--echo Last_SQL_Error = $error + +--echo ==== Clean up ==== +source include/cleanup_fake_relay_log.inc; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test new file mode 100644 index 00000000..f26e9565 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test @@ -0,0 +1,121 @@ +# ==== Purpose ==== +# +# Test verifies that Start binlog_dump message will report GTID position +# requested by slave when log_warnings > 1. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Have LOG_WARNINGS=2 +# 1 - On a fresh slave server which has not replicated any GTIDs execute +# "CHANGE MASTER TO MASTER_USE_GTID=current_pos;" command. Start the +# slave. +# 2 - In Master error log verify that pattern "using_gtid(1), gtid('')" is +# present. +# 3 - On slave server do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=no;" command. Start the slave threads. +# 4 - In Master error log verify that pattern "using_gtid(0), gtid('')" is +# present. +# 5- Execute a DDL and DML on master server. This will generated two GTIDs +# on the master server ('0-1-2'). Sync the slave server with master. +# 6 - On slave do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=slave_pos;" command. Start slave threads. +# 7 - In Master error verify that pattern "using_gtid(1), gtid('0-1-2')" is +# present. +# 8 - On Master change domain ID to 10 and execute a DML operation. It will +# generate a GTID 10-1-1. +# 9 - On slave do STOP SLAVE and execute "CHANGE MASTER TO +# MASTER_USE_GTID=slave_pos;" command. Start slave threads. +# 10 -In Master error verify that pattern "using_gtid(1), +# gtid('0-1-2,10-1-1')" is present. +# +# ==== References ==== +# +# MDEV-20428: "Start binlog_dump" message doesn't indicate GTID position +# + +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection master +SET GLOBAL LOG_WARNINGS=2; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=current_pos; +--source include/start_slave.inc + +--connection master +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; +} +--echo "Test Case 1: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'\'\).* +--source include/search_pattern_in_file.inc + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +--source include/start_slave.inc + +--connection master +--echo "Test Case 2: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(0), gtid('')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(0\), gtid\(\'\'\).* +--source include/search_pattern_in_file.inc +CREATE TABLE t (f INT) ENGINE=INNODB; +INSERT INTO t VALUES(10); +save_master_pos; + +--connection slave +sync_with_master; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +--connection master +--echo "Test Case 3: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2\'\).* +--source include/search_pattern_in_file.inc +SET @@SESSION.gtid_domain_id=10; +INSERT INTO t VALUES(20); +save_master_pos; + +--connection slave +sync_with_master; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +--connection master +--echo "Test Case 4: Start binlog_dump to slave_server(#), pos(master-bin.000001, ###), using_gtid(1), gtid('0-1-2,10-1-1')" +--let SEARCH_FILE=$log_error_ +--let SEARCH_RANGE=-50000 +--let SEARCH_PATTERN=using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).* +--source include/search_pattern_in_file.inc + +--echo "===== Clean up =====" +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID=no; +--source include/start_slave.inc + +--connection master +DROP TABLE t; +SET GLOBAL LOG_WARNINGS=default; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test b/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test new file mode 100644 index 00000000..869c715f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_dup_entry.test @@ -0,0 +1,72 @@ +# ==== Purpose ==== +# +# Test verifies that there are no duplicate entries in binlog (i.e a safe +# statement which follows an unsafe statement gets logged in both row format +# and statement format resulting in duplicate entry) when binlog-format=MIXED +# and LOCK TABLES are enabled. +# +# ==== Implementation ==== +# +# Steps: +# 1 - Create three tables t1,t2 and t3 with AUTO_INCREMENT on. +# 2 - Create a trigger on table t3, so that trigger execution results in +# unsafe statement. Note query that modifies autoinc column in +# sub-statement can make the master and slave inconsistent. Hence they +# are logged in row format. +# 3 - Lock tables t1,t2 and t3. +# 4 - Execute an unsafe update which modifies tables t1 and t3. But since t2 +# table is also locked its table map event also gets written into the +# binary log during the execution of update. +# 5 - Execute a safe DML operation using table 't2' and verify that master +# doesn't report any assert. +# 6 - Ensure that slave is in sync with master and data is consistent. +# +# ==== References ==== +# +# MDEV-19158: MariaDB 10.2.22 is writing duplicate entries into binary log + +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +CREATE TABLE t1 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, someLabel varchar(30) NOT NULL, flag tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY (id)) Engine=MyISAM; +CREATE TABLE t2 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, data varchar(30) NOT NULL, status tinyint(1) NOT NULL, PRIMARY KEY (id)) Engine=MyISAM; +CREATE TABLE t3 (id mediumint(8) unsigned NOT NULL AUTO_INCREMENT, t1id mediumint(8) unsigned NOT NULL, flag tinyint(1) NOT NULL DEFAULT 0, status tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY (id)) Engine=MyISAM; + +INSERT INTO t1 ( id, someLabel, flag ) VALUES ( 1, 'ABC', 0 ); + +DELIMITER |; + +CREATE OR REPLACE TRIGGER doNothing +BEFORE UPDATE ON t1 +FOR EACH ROW + BEGIN + IF + new.someLabel != old.someLabel + THEN + UPDATE t3 SET t3.flag = 0; + END IF; + END| + +DELIMITER ;| + +FLUSH LOGS; + +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2 (data, status) VALUES ('1', 4); +UPDATE t1 SET flag = 1 WHERE id = 1; +INSERT INTO t2 (data, status) VALUES ('2', 4); +UNLOCK TABLES; + +sync_slave_with_master; + +let $diff_tables= master:t1, slave:t1; +--source include/diff_tables.inc +let $diff_tables= master:t2, slave:t2; +--source include/diff_tables.inc +let $diff_tables= master:t3, slave:t3; +--source include/diff_tables.inc + +--connection master +DROP TABLE t1, t2, t3; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt b/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt new file mode 100644 index 00000000..f8e46a44 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_errors-master.opt @@ -0,0 +1 @@ +--max_binlog_size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_binlog_errors.test b/mysql-test/suite/rpl/t/rpl_binlog_errors.test new file mode 100644 index 00000000..30faaf79 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_errors.test @@ -0,0 +1 @@ +--source include/rpl_binlog_errors.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_grant.test b/mysql-test/suite/rpl/t/rpl_binlog_grant.test new file mode 100644 index 00000000..f8513021 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_grant.test @@ -0,0 +1,42 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc +-- source include/have_binlog_format_mixed_or_statement.inc +source include/master-slave.inc; + +let $VERSION=`select version()`; + +# Bug #21975: grant/revoke statements in transaction +# used to disappear from binlog upon rallback. +# Now GRANT/REVOKE do implicitly commit +# transaction + +create database d1; +use d1; +create table t (s1 int) engine=innodb; +set @@autocommit=0; +start transaction; +insert into t values (1); +create user x@y; +grant select on t to x@y; +let $wait_binlog_event= grant select; +source include/wait_for_binlog_event.inc; +# +# There is no active transaction here +# +rollback; +show grants for x@y; +start transaction; +insert into t values (2); +revoke select on t from x@y; +let $wait_binlog_event= revoke select; +source include/wait_for_binlog_event.inc; +# +# There is no active transaction here +# +commit; +select * from t; +show grants for x@y; +drop user x@y; +drop database d1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_index.test b/mysql-test/suite/rpl/t/rpl_binlog_index.test new file mode 100644 index 00000000..95c49c3d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_index.test @@ -0,0 +1,217 @@ +# ==== Purpose ==== +# +# Test that server can work fine after moving binlog or relay log +# files to another directory and setting binlog or relay log paths to +# the new path. +# +# ==== Method ==== +# +# Start replication, and then shutdown the master, move the binary +# logs and the log index file to a another directory and then restart +# the server with option to set the new binlog directory. After master +# restarted successfully, do the similar on slave to check the relay +# log of slave. +# +# ==== Reference ==== +# +# BUG#12133 master.index file keeps mysqld from starting if bin log has been moved +# BUG#42576 Relay logs in relay-log.info&localhost-relay-bin.index not processed after move + +source include/master-slave.inc; +# There is no need to run this test case on all binlog format +source include/have_binlog_format_row.inc; + +# Since this test relies heavily on filesystem operations (like +# moving files around, backslashes and so forth) we avoid messing +# around with windows access violations for not cluttering the +# test case any further. It is prepared to support windows, but +# it is not 100% compliant. +--source include/not_windows.inc + +connection master; +--let $master_datadir= `select @@datadir` +connection slave; +--let $slave_datadir= `select @@datadir` +connection master; +--let $dirname= `select uuid()` +--let $tmpdir= $MYSQLTEST_VARDIR/tmp/$dirname +--mkdir $tmpdir + +CREATE TABLE t1 (a INT); +# flush to generate one more binlog file. +FLUSH BINARY LOGS; +INSERT INTO t1 VALUES (1); + +sync_slave_with_master; +--source include/stop_slave.inc +# +# Test on master +# +connection master; +--echo # Shutdown master +--let $rpl_server_number=1 +source include/rpl_stop_server.inc; + +--echo # Move the master binlog files and the index file to a new place +--move_file $master_datadir/master-bin.000001 $tmpdir/master-bin.000001 +--move_file $master_datadir/master-bin.000002 $tmpdir/master-bin.000002 +--move_file $master_datadir/master-bin.index $tmpdir/master-bin.index + +--echo # Restart master with log-bin option set to the new path +--let $rpl_server_parameters=--log-bin=$tmpdir/master-bin --log-bin-index=$tmpdir/master-bin +--let $keep_include_silent=1 +source include/rpl_start_server.inc; +--let $keep_include_silent=0 + +--echo # Master has restarted successfully +--connection slave +--source include/start_slave.inc +--connection master +# +# Test master can handle old format with directory path in index file +# +--let $is_windows= `select convert(@@version_compile_os using latin1) in ('Win32', 'Win64', 'Windows')` + +# write_var_to_file.inc will call SELECT INTO DUMPFILE, which has to be +# done before shutdown the server +--echo # Create the master-bin.index file with the old format +--let $write_to_file= $master_datadir/master-bin.index +if ($is_windows) +{ + --let $write_var= .\\\\master-bin.000001\n.\\\\master-bin.000002\n.\\\\master-bin.000003\n +} +if (!$is_windows) +{ + --let $write_var= ./master-bin.000001\n./master-bin.000002\n./master-bin.000003\n +} +--disable_query_log +source include/write_var_to_file.inc; +--enable_query_log +--sync_slave_with_master +--source include/stop_slave.inc + +--connection master +--echo # Shutdown master +--let $rpl_server_number=1 +source include/rpl_stop_server.inc; + +--echo # Move back the master binlog files +--move_file $tmpdir/master-bin.000001 $master_datadir/master-bin.000001 +--move_file $tmpdir/master-bin.000002 $master_datadir/master-bin.000002 +--move_file $tmpdir/master-bin.000003 $master_datadir/master-bin.000003 + +--echo # Remove the unneeded master-bin.index file +--remove_file $tmpdir/master-bin.index + +--echo # Restart master with log-bin option set to default +--let $rpl_server_parameters=--log-bin=$master_datadir/master-bin --log-bin-index=$master_datadir/master-bin +--let $keep_include_silent=1 +source include/rpl_start_server.inc; +--let $keep_include_silent=0 + +--echo # Master has restarted successfully +--connection slave +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +--echo # stop slave +--source include/stop_slave.inc +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +# switch to master because the slave has been shutdown +# and relocate_binlogs requires a running server to do +# SQL operations +--connection master + +--let $relocate_disable_query_log= 1 +--let $relocate_is_windows= $is_windows +--let $relocate_from=$slave_datadir +--let $relocate_into=$tmpdir + +--echo # relocate binlogs +--let $relocate_index_file=$slave_datadir/slave-bin.index +--source include/relocate_binlogs.inc + +--echo # relocate relay logs +--let $relocate_index_file=$slave_datadir/slave-relay-bin.index +--source include/relocate_binlogs.inc + +--echo # Restart slave with options log-bin, relay-log set to the new paths +--let $rpl_server_parameters=--log-bin=$tmpdir/slave-bin --relay-log=$tmpdir/slave-relay-bin --relay-log-index=$tmpdir/slave-relay-bin.index +--let $keep_include_silent=1 +--let $rpl_server_number= 2 +source include/rpl_start_server.inc; +--let $keep_include_silent=0 + +--connection slave + +--echo # Slave server has restarted successfully +--source include/start_slave.inc +--source include/stop_slave.inc + +connection master; +FLUSH LOGS; +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (2); + +FLUSH LOGS; + +connection slave; +FLUSH LOGS; +--source include/start_slave.inc +connection master; +sync_slave_with_master; +--let $diff_tables= master:t1,slave:t1 +source include/diff_tables.inc; + +connection master; +DROP TABLE t1; +--sync_slave_with_master +--source include/stop_slave.inc +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--connection master + +--let $relocate_from=$tmpdir +--let $relocate_into=$slave_datadir +--let $relocate_recreate_index= 1 + +# binlogs +--let $relocate_index_file=$tmpdir/slave-bin.index +--source include/relocate_binlogs.inc + +# relay logs + +# since the complete fix for the relocation of logs is +# done in BUG#13428851 it does not help here to try +# to start the slave as it would fail (relay-log.info is +# tainted with the full path in the RELAY_LOG_FILE position). +# Instead, we reset the slave and let the test clean up. +--let $relocate_fix_relay_log_info= $slave_datadir/relay-log.info +--let $relocate_index_file=$tmpdir/slave-relay-bin.index +--source include/relocate_binlogs.inc + +--echo # remove tmpdir +--remove_files_wildcard $tmpdir * +--rmdir $tmpdir + +--echo # restarted with previous slave settings +--let $rpl_server_parameters=--log-bin=$slave_datadir/slave-bin --relay-log=$slave_datadir/slave-relay-bin --relay-log-index=$slave_datadir/slave-relay-bin.index +--let $keep_include_silent=1 +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc +--let $keep_include_silent=0 + +--connection slave + +# The slave will restart if we have fixed the relay-log.info +# correctly +--source include/start_slave.inc + +--connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test b/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test new file mode 100644 index 00000000..ed4d713f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_binlog_rollback_cleanup.test @@ -0,0 +1,46 @@ +# ==== Purpose ==== +# +# Test verifies that when flushing an event to binary log fails the transaction +# is successfully rolled back and following COMMIT command doesn't report any +# assert. +# +# ==== Implementation ==== +# +# Steps: +# 0 - SET max_binlog_cache_size=64K +# 1 - Create an Innodb table and insert required amount of data. Execute an +# UPDATE operation which generates a big update event whose size exceeds +# max_binlog_cache_size. +# 2 - Wait for error 1197. Execute COMMIT command. +# 3 - COMMIT should be successful. +# +# ==== References ==== +# +# MDEV-18514: Assertion `!writer.checksum_len || writer.remains == 0' failed +# +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc +--connection master +let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1); +SET GLOBAL max_binlog_cache_size = 65536; +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=INNODB; +let $data = `select concat('"', repeat('a',6000), '"')`; +let $data1 = `select concat('"', repeat('b',6000), '"')`; +--disable_query_log +eval INSERT INTO t1 (a, data) VALUES (1, CONCAT($data, $data)); +eval INSERT INTO t1 (a, data) VALUES (2, CONCAT($data, $data)); +eval INSERT INTO t1 (a, data) VALUES (3, CONCAT($data, $data)); +eval INSERT INTO t1 (a, data) VALUES (4, CONCAT($data, $data)); +eval INSERT INTO t1 (a, data) VALUES (5, CONCAT($data, $data)); +START TRANSACTION; +--error ER_TRANS_CACHE_FULL +eval UPDATE t1 SET data=$data1; +COMMIT; +--enable_query_log + +--replace_result $old_max_binlog_cache_size ORIGINAL_VALUE +--eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bit.test b/mysql-test/suite/rpl/t/rpl_bit.test new file mode 100644 index 00000000..305a2abc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bit.test @@ -0,0 +1,92 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Sept/15/2005 # +############################################################################# +# Test: To test the replication of the bit field # +############################################################################# +# Change Author: JBM +# Change Date: 2006-01-16 +########## + +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP TABLE IF EXISTS test.t1; +--enable_warnings +# End of cleanup + +# Begin test section 1 + +CREATE TABLE test.t1 ( + dummyKey INTEGER NOT NULL, + f01 TINYINT, + f10 TINYINT, + f12 TINYINT, + f15 TINYINT, + f16 TINYINT, + f7 TINYINT, + f9 TINYINT, + f29 TINYINT, + f0 TINYINT, + fA1 TINYINT, + C32 TINYINT, + A42 TINYINT, + CA3 TINYINT, + A044 TINYINT, + f001 TINYINT, + A3002 TINYINT, + fC003 TINYINT, + CA300 TINYINT, + A305 TINYINT, + CA321 TINYINT, + r001 TINYINT, + bit1 BIT(6), + bit2 BIT(6), + bit3 BIT(6), + State1 TINYINT, + State2 TINYINT, + State3 TINYINT, + State4 TINYINT, + SubState TINYINT, + gState TINYINT, + oSupp TINYINT, + tSupp TINYINT, + sSuppD TINYINT, + mSuppf TINYINT, + GSuppDf TINYINT, + VNotSupp TINYINT, + x034 TINYINT, +PRIMARY KEY USING HASH (dummyKey) ); + +LOCK TABLES test.t1 WRITE; +INSERT INTO test.t1 VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'111110',b'110101',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'100100',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'101010',b'010101',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'101010',b'111111',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +UNLOCK TABLES; + + +SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1; +SELECT hex(bit1) FROM test.t1 ORDER BY bit1; +SELECT hex(bit2) from test.t1 ORDER BY bit2; +SELECT hex(bit3) from test.t1 ORDER BY bit3; +sync_slave_with_master; + +SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1; +SELECT hex(bit1) FROM test.t1 ORDER BY bit1; +SELECT hex(bit2) from test.t1 ORDER BY bit2; +SELECT hex(bit3) from test.t1 ORDER BY bit3; + +connection master; +DROP TABLE IF EXISTS test.t1; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bit_npk.test b/mysql-test/suite/rpl/t/rpl_bit_npk.test new file mode 100644 index 00000000..d65ef66a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bit_npk.test @@ -0,0 +1,113 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Sept/15/2005 # +############################################################################# +# Test: To test the replication of the bit field # +############################################################################# + +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP TABLE IF EXISTS test.t1; +--enable_warnings +# End of cleanup + +# Begin test section 1 + +CREATE TABLE test.t1 ( + dummyKey INTEGER NOT NULL, + f01 TINYINT, + f10 TINYINT, + f12 TINYINT, + f15 TINYINT, + f16 TINYINT, + f7 TINYINT, + f9 TINYINT, + f29 TINYINT, + f0 TINYINT, + fA1 TINYINT, + C32 TINYINT, + A42 TINYINT, + CA3 TINYINT, + A044 TINYINT, + f001 TINYINT, + A3002 TINYINT, + fC003 TINYINT, + CA300 TINYINT, + A305 TINYINT, + CA321 TINYINT, + r001 TINYINT, + bit1 BIT(6), + bit2 BIT(6), + bit3 BIT(6), + State1 TINYINT, + State2 TINYINT, + State3 TINYINT, + State4 TINYINT, + SubState TINYINT, + gState TINYINT, + oSupp TINYINT, + tSupp TINYINT, + sSuppD TINYINT, + mSuppf TINYINT, + GSuppDf TINYINT, + VNotSupp TINYINT, + x034 TINYINT); + +LOCK TABLES test.t1 WRITE; +INSERT INTO test.t1 VALUES (6,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'111110',b'110101',4,5,5,5,5,5,5,5,5,5,3,NULL,1); +INSERT INTO test.t1 VALUES (1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'111111',b'000000',b'100100',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (2,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'000000',b'101010',b'010101',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (3,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'101010',b'111111',b'000000',4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (4,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,b'0',1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (5,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (7,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4,5,5,5,5,5,5,5,5,5,3,2,1); +UNLOCK TABLES; + +UPDATE test.t1 set x034 = 50 where bit3 = b'000000'; +UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0'; +SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 + FROM test.t1 + ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034; +SELECT hex(bit1) from test.t1 ORDER BY bit1; +SELECT hex(bit2) from test.t1 ORDER BY bit2; +SELECT hex(bit3) from test.t1 ORDER BY bit3; +sync_slave_with_master; + +SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 + FROM test.t1 + ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034; +SELECT hex(bit1) from test.t1 ORDER BY bit1; +SELECT hex(bit2) from test.t1 ORDER BY bit2; +SELECT hex(bit3) from test.t1 ORDER BY bit3; + +connection master; +CREATE TABLE test.t2 (a INT, b BIT(1)); +INSERT INTO test.t2 VALUES (1, b'0'); +INSERT INTO test.t2 VALUES (1, b'1'); +UPDATE test.t2 SET a = 2 WHERE b = b'1'; + +CREATE TABLE test.t3 (a INT, b INT); +INSERT INTO test.t3 VALUES (1, NULL); +INSERT INTO test.t3 VALUES (1, 0); +UPDATE test.t3 SET a = 2 WHERE b = 0; + +SELECT a, hex(b) FROM test.t2 ORDER BY a,b; +SELECT * FROM test.t3 ORDER BY a,b; +sync_slave_with_master; + +SELECT a, hex(b) FROM test.t2 ORDER BY a,b; +SELECT * FROM test.t3 ORDER BY a,b; + +connection master; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_blackhole.test b/mysql-test/suite/rpl/t/rpl_blackhole.test new file mode 100644 index 00000000..927f0d80 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole.test @@ -0,0 +1,25 @@ +# PURPOSE. Test that blackhole works with replication in all three +# modes: STATEMENT, MIXED, and ROW. +# +# METHOD. We start by creating a table on the master and then change +# the engine to use blackhole on the slave. +# +# After insert/update/delete of one or more rows, the test the +# proceeds to check that replication is running after replicating an +# change, that the blackhole engine does not contain anything (which +# is just a check that the correct engine is used), and that something +# is written to the binary log. +# +# Whe check INSERT, UPDATE, and DELETE statement for tables with no +# key (forcing a range search on the slave), primary keys (using a +# primary key lookup), and index/key with multiple matches (forcing an +# index search). + +source include/have_blackhole.inc; +source include/master-slave.inc; + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +source include/rpl_blackhole_basic.test; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt new file mode 100644 index 00000000..91302791 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt @@ -0,0 +1 @@ +--binlog_annotate_row_events --timezone=GMT-3 diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt new file mode 100644 index 00000000..7ac6a84f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt @@ -0,0 +1 @@ +--binlog_annotate_row_events --replicate_annotate_row_events diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test new file mode 100644 index 00000000..afc8e257 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test @@ -0,0 +1,49 @@ +# ==== Purpose ==== +# +# Test verifies that when "replicate_annotate_row_events" are enabled on slave +# the DML operations on blackhole engine will be successful. It also ensures +# that Annotate events are logged into slave's binary log. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Enable "replicate_annotate_row_events" on slave and do DML operations +# on master. +# 1 - Slave server will successfully apply the DML operations and it is in +# sync with master. +# 2 - Verify that the "show binlog events" prints all annotate events. +# 3 - Stream the slave's binary log using "mysqlbinlog" tool and verify +# that the Annotate events are being displayed. +# +# ==== References ==== +# +# MDEV-11094: Blackhole table updates on slave fail when row annotation is +# enabled + +source include/have_blackhole.inc; +source include/have_binlog_format_row.inc; +source include/binlog_start_pos.inc; +source include/master-slave.inc; + +SET timestamp=1000000000; +RESET MASTER; +connection slave; +SET timestamp=1000000000; +RESET MASTER; + +connection master; +source include/rpl_blackhole_basic.test; + +# Verify on slave. +connection slave; +FLUSH LOGS; +--replace_column 2 # 5 # +--replace_result $binlog_start_pos <start_pos> +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +--eval show binlog events in 'slave-bin.000001' from $binlog_start_pos + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ +--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/slave-bin.000001 + +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_bug26395.test b/mysql-test/suite/rpl/t/rpl_bug26395.test new file mode 100644 index 00000000..0c1b2a7a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug26395.test @@ -0,0 +1,93 @@ +# ==== Purpose ==== +# +# Tests that an autocommitted XA transaction where the master crashes +# just before writing the XID log event is executed correctly. The +# master rolls back, so the slave should not execute statement. +# +# ==== Method ==== +# +# We want master to be alive so that it can replicate the statement to +# the slave. So in the test case, we must not crash the +# master. Instead, we fake the crash by just not writing the XID event +# to the binlog. This is done by the @@debug_dbug='d,do_not_write_xid' +# flag. This, in turn, requires us to do 'source +# include/have_debug.inc' +# +# So, unlike if the master had crashed, the master *will* execute the +# statement. But the slave should not execute it. Hence, after the +# test is executed, the expected result on master is a table with one +# row, and on slave a table with no rows. +# +# To simulate the slave correctly, we wait until everything up to but +# not including the XID is replicated. This has to be done with +# include/sync_slave_io_with_master.inc, not sync_slave_with_master, +# since the latter waits until the slave *SQL* thread has caught up +# with the master's position, which it will never do. +# +# +# ==== Related bugs ==== +# +# BUG#26395: if crash during autocommit update to transactional table on master, slave fails + +source include/have_innodb.inc; +# have_debug is needed since we use the @@debug variable on master +source include/have_debug.inc; +source include/master-slave.inc; + + +--echo ==== Initialize ==== + +--connection master + +CREATE TABLE tinnodb (a INT) ENGINE = INNODB; +SHOW CREATE TABLE tinnodb; + +# do_not_write_xid stops the master from writing an XID event. +set @old_debug= @@debug; +set @@debug_dbug= 'd,do_not_write_xid'; + + +--echo ==== Test ==== + +# Save the position up to which the slave SQL thread should execute. +save_master_pos; + +# Execute query and check that the row made it to the table. +INSERT INTO tinnodb VALUES (1); +SELECT * FROM tinnodb ORDER BY a; + +# Sync slave's IO thread. +--echo [on slave] +source include/sync_slave_io_with_master.inc; + +# Sync slave's SQL thread. +sync_with_master 0; + + +--echo ==== Verify results on slave ==== + +source include/stop_slave.inc; +let $tmp= query_get_value("SHOW SLAVE STATUS", Slave_IO_State, 1); +eval SELECT "$tmp" AS Slave_IO_State; +let $tmp= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +eval SELECT "$tmp" AS Last_SQL_Error; +let $tmp= query_get_value("SHOW SLAVE STATUS", Last_IO_Error, 1); +eval SELECT "$tmp" AS Last_IO_Error; +SELECT * FROM tinnodb ORDER BY a; + + +--echo ==== Clean up ==== + +# Easiest to clean up master and slave separately, without +# replication, since master and slave are out of sync. + +connection master; +DROP TABLE tinnodb; +set @@debug_dbug= @old_debug; + +connection slave; +DROP TABLE tinnodb; + +# Warning: do not add more tests here. The binlog is in a bad state. +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug31076.test b/mysql-test/suite/rpl/t/rpl_bug31076.test new file mode 100644 index 00000000..4e9517fb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug31076.test @@ -0,0 +1,146 @@ +source include/have_binlog_format_mixed_or_row.inc; +source include/master-slave.inc; + +SET @saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY'; + +CREATE DATABASE track; +USE track; + +CREATE TABLE `visits` ( + `visits_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `myid` varchar(32) NOT NULL DEFAULT '', + `src` varchar(64) NOT NULL DEFAULT '', + `ip` int(10) unsigned NOT NULL DEFAULT '0', + `cc` char(2) NOT NULL DEFAULT '', + `org` varchar(80) DEFAULT NULL, + `ref` varchar(255) NOT NULL DEFAULT '', + `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `host` varchar(30) NOT NULL DEFAULT '', + `entry` varchar(255) NOT NULL DEFAULT '', + `visit_exit` varchar(255) NOT NULL DEFAULT '', + `user_id` int(11) unsigned NOT NULL DEFAULT '0', + `visit_start` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`visits_id`), + KEY `ip` (`ip`), + KEY `time` (`time`), + KEY `user_id` (`user_id`) +) ENGINE=MyISAM AUTO_INCREMENT=21293381 DEFAULT CHARSET=latin1; + +CREATE TABLE `visits_events` ( + `event_id` mediumint(8) unsigned NOT NULL DEFAULT '0', + `visit_id` int(11) unsigned NOT NULL DEFAULT '0', + `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `src` varchar(64) NOT NULL DEFAULT '', + `data` varchar(255) NOT NULL DEFAULT '', + `visits_events_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`visits_events_id`), + KEY `event_id` (`event_id`), + KEY `visit_id` (`visit_id`), + KEY `data` (`data`) +) ENGINE=MyISAM AUTO_INCREMENT=33900731 DEFAULT CHARSET=latin1; + +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +--delimiter /*!*/; + +# at 4 (0x4) +#071204 14:29:31 server id 1 end_log_pos 106 +# Position Timestamp Type Master ID Size Master Pos Flags +# 4 3b 56 55 47 0f 01 00 00 00 66 00 00 00 6a 00 00 00 00 00 +# 17 04 00 35 2e 31 2e 32 33 2d 72 63 2d 64 65 62 75 |..5.1.23.rc.debu| +# 27 67 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 |g.log...........| +# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +# 47 00 00 00 00 3b 56 55 47 13 38 0d 00 08 00 12 00 |.....VUG.8......| +# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........| +# 67 08 08 02 |...| +# Start: binlog v 4, server v 5.1.23-rc-debug-log created 071204 14:29:31 at startup + +BINLOG ' +O1ZVRw8BAAAAZgAAAGoAAAAAAAQANS4xLjIzLXJjLWRlYnVnLWxvZwAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAA7VlVHEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC +'/*!*/; + +# at 164170623 +# at 164170679 +#7918 3:59:2 server id 436 end_log_pos 164170679 +# 9c90b7f 06 4d ef 46 13 b4 01 00 00 38 00 00 00 b7 0b c9 |.M.F.....8......| +# 9c90b8f 09 00 00 99 57 17 02 00 00 00 00 05 74 72 61 63 |....W.......trac| +# 9c90b9f 6b 00 0d 76 69 |k..vi| +# Table_map: `track`.`visits_events` mapped to number 35084185 +#7918 3:59:2 server id 436 end_log_pos 164170769 +# 9c90bb7 06 4d ef 46 17 b4 01 00 00 5a 00 00 00 11 0c c9 |.M.F.....Z......| +# 9c90bc7 09 10 00 99 57 17 02 00 00 01 00 06 ff c0 20 4e |....W..........N| +# 9c90bd7 00 be f5 43 01 06 4d ef 46 00 2b 44 6f 77 6e 6c |...C..M.F..Downl| +# 9c90be7 6f 61 64 73 2f 4d 79 53 51 4c 2d 34 2e 31 2f 6d |oads.MySQL.4.1.m| +# 9c90bf7 79 73 71 6c 2d 34 2e |ysql.4.| +# Write_rows: table id 35084185 flags: STMT_END_F + +BINLOG ' +Bk3vRhO0AQAAOAAAALcLyQkAAJlXFwIAAAAABXRyYWNrAA12aXNpdHNfZXZlbnRzAAYJAwcPDwM= +Bk3vRhe0AQAAWgAAABEMyQkQAJlXFwIAAAEABv/AIE4AvvVDAQZN70YAK0Rvd25sb2Fkcy9NeVNR +TC00LjEvbXlzcWwtNC4xLjEyYS13aW4zMi56aXBPaAIC +'/*!*/; +# at 164170769 +#7918 3:59:2 server id 436 end_log_pos 164170797 +# 9c90c11 06 4d ef 46 05 b4 01 00 00 |.M.F.....| +# Intvar +SET INSERT_ID=21231039/*!*/; +# at 164170797 +#7918 3:59:2 server id 436 end_log_pos 164171293 +# 9c90c2d 06 4d ef 46 02 b4 01 00 00 f0 01 00 00 1d 0e c9 |.M.F............| +# 9c90c3d 09 10 00 28 80 af 01 00 00 00 00 05 00 00 1f 00 |................| +# 9c90c4d 00 00 40 00 00 01 00 00 00 00 00 00 00 00 06 03 |................| +# 9c90c5d 73 74 64 04 08 00 08 00 08 00 05 03 55 54 43 74 |std.........UTCt| +# 9c90c6d 72 61 63 6b 00 49 4e 53 45 52 54 20 49 4e 54 4f |rack.INSERT.INTO| +# 9c90c7d 20 76 69 73 69 74 73 20 28 6d 79 69 64 2c 20 75 |.visits..myid..u| +# 9c90c8d 73 65 72 5f 69 64 2c 20 73 72 63 2c 20 69 70 2c |ser.id..src..ip.| +# 9c90c9d 20 63 63 2c 20 6f 72 67 2c 20 72 65 66 2c 20 74 |.cc..org..ref..t| +# 9c90cad 69 6d 65 2c 20 68 6f 73 74 2c 20 65 6e 74 72 79 |ime..host..entry| +# 9c90cbd 2c 20 76 69 73 69 74 5f 65 78 69 74 2c 20 76 69 |..visit.exit..vi| +# 9c90ccd 73 69 74 5f 73 74 61 72 74 29 0a 09 09 09 56 41 |sit.start.....VA| +# 9c90cdd 4c 55 45 53 20 28 27 33 6d 33 6c 34 72 68 73 36 |LUES...3m3l4rhs6| +# 9c90ced 64 6f 30 73 66 35 70 31 69 39 6c 72 39 34 67 39 |do0sf5p1i9lr94g9| +# 9c90cfd 32 38 61 32 37 32 76 27 2c 20 27 27 2c 20 27 27 |28a272v.........| +# 9c90d0d 2c 20 49 4e 45 54 5f 41 54 4f 4e 28 27 37 31 2e |..INET.ATON..71.| +# 9c90d1d 31 31 38 2e 31 32 34 2e 39 38 27 29 2c 20 27 27 |118.124.98......| +# 9c90d2d 2c 20 27 27 2c 20 27 68 74 74 70 3a 2f 2f 64 65 |.......http...de| +# 9c90d3d 76 2e 6d 79 73 71 6c 2e 63 6f 6d 2f 64 6f 77 6e |v.mysql.com.down| +# 9c90d4d 6c 6f 61 64 73 2f 63 6f 6e 6e 65 63 74 6f 72 2f |loads.connector.| +# 9c90d5d 6a 2f 33 2e 30 2e 68 74 6d 6c 27 2c 20 4e 55 4c |j.3.0.html...NUL| +# 9c90d6d 4c 2c 20 27 64 65 76 2e 6d 79 73 71 6c 2e 63 6f |L...dev.mysql.co| +# 9c90d7d 6d 27 2c 20 27 2f 67 65 74 2f 44 6f 77 6e 6c 6f |m.....get.Downlo| +# 9c90d8d 61 64 73 2f 43 6f 6e 6e 65 63 74 6f 72 2d 4a 2f |ads.Connector.J.| +# 9c90d9d 6d 79 73 71 6c 2d 63 6f 6e 6e 65 63 74 6f 72 2d |mysql.connector.| +# 9c90dad 6a 61 76 61 2d 33 2e 30 2e 31 37 2d 67 61 2e 7a |java.3.0.17.ga.z| +# 9c90dbd 69 70 2f 66 72 6f 6d 2f 70 69 63 6b 27 2c 20 27 |ip.from.pick....| +# 9c90dcd 2f 67 65 74 2f 44 6f 77 6e 6c 6f 61 64 73 2f 43 |.get.Downloads.C| +# 9c90ddd 6f 6e 6e 65 63 74 6f 72 2d 4a 2f 6d 79 73 71 6c |onnector.J.mysql| +# 9c90ded 2d 63 6f 6e 6e 65 63 74 6f 72 2d 6a 61 76 61 2d |.connector.java.| +# 9c90dfd 33 2e 30 2e 31 37 2d 67 61 2e 7a 69 70 |3.0.17.ga.zip| +# Query thread_id=28278824 exec_time=0 error_code=0 +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +use track/*!*/; +SET TIMESTAMP=1190087942/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/; +SET @@session.sql_mode=0/*!*/; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; +SET @@session.time_zone='UTC'/*!*/; +INSERT INTO visits (myid, user_id, src, ip, cc, org, ref, time, host, entry, visit_exit, visit_start) +VALUES ('3m3l4rhs6do0sf5p1i9lr94g928a272v', '', '', INET_ATON('71.118.124.98'), '', '', 'http://dev.mysql.com/downloads/connector/j/3.0.html', NULL, 'dev.mysql.com', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', '/get/Downloads/Connector-J/mysql-connector-java-3.0.17-ga.zip/from/pick', NOW())/*!*/; +# at 164171293 + +--delimiter ; + +SELECT * FROM visits; +SELECT * FROM visits_events; + +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions; + +# Cleanup +DROP DATABASE track; +sync_slave_with_master; + +--echo End of 5.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug33931.test b/mysql-test/suite/rpl/t/rpl_bug33931.test new file mode 100644 index 00000000..0b2cbb63 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug33931.test @@ -0,0 +1,49 @@ +# Test for +# Bug #33931 assertion at write_ignored_events_info_to_relay_log if init_slave_thread() fails +# Bug #33932 assertion at handle_slave_sql if init_slave_thread() fails + +source include/have_debug.inc; +source include/master-slave.inc; + +connection slave; + +# Add suppression for expected warnings in slaves error log +call mtr.add_suppression("Failed during slave I/O thread initialization"); +call mtr.add_suppression("Slave SQL.*Failed during slave thread initialization.* 1593"); + +--source include/stop_slave.inc +reset slave; + +# Set debug flags on slave to force errors to occur +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; + +--disable_query_log +eval CHANGE MASTER TO MASTER_USER='root', + MASTER_CONNECT_RETRY=1, + MASTER_HOST='127.0.0.1', + MASTER_PORT=$MASTER_MYPORT; +--enable_query_log + +start slave; + +# +# slave is going to stop because of emulated failures +# but there won't be any crashes nor asserts hit. +# + +# 1593 = ER_SLAVE_FATAL_ERROR +--let $slave_sql_errno= 1593 +--let $show_slave_sql_error= 1 +--source include/wait_for_slave_sql_error.inc + +# +# Cleanup +# +SET @@GLOBAL.debug_dbug = @saved_dbug; + +# Clear Last_SQL_Error +RESET SLAVE; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug37426.test b/mysql-test/suite/rpl/t/rpl_bug37426.test new file mode 100644 index 00000000..18e80a5f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug37426.test @@ -0,0 +1,22 @@ +############################################################# +# Purpose: Test for BUG#37426 +# RBR breaks for CHAR() UTF8 fields > 85 chars +############################################################# + +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +connection master; +CREATE TABLE char128_utf8 (i1 INT NOT NULL, c CHAR(128) CHARACTER SET utf8 NOT NULL, i2 INT NOT NULL); +INSERT INTO char128_utf8 VALUES ( 1, "123", 1 ); + +SELECT * FROM char128_utf8; +sync_slave_with_master; + +SELECT * FROM char128_utf8; + +# Clean up +connection master; +DROP TABLE char128_utf8; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt b/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt new file mode 100644 index 00000000..b457a7eb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug38694-slave.opt @@ -0,0 +1 @@ +--loose-debug-dbug=d,simulate_slave_delay_at_terminate_bug38694 diff --git a/mysql-test/suite/rpl/t/rpl_bug38694.test b/mysql-test/suite/rpl/t/rpl_bug38694.test new file mode 100644 index 00000000..57d7dde0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug38694.test @@ -0,0 +1,13 @@ +# Testing replication threads stopping concurrency issue +# at the server shutdown +# Related bugs: bug#38694, bug#29968, bug#25306 +# The test checks if a delay at the termination phase of slave threads +# DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); +# could cause any issue. + +source include/master-slave.inc; + +call mtr.add_suppression("Aborted connection"); + +# End of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_bug41902.test b/mysql-test/suite/rpl/t/rpl_bug41902.test new file mode 100644 index 00000000..bb6c5725 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug41902.test @@ -0,0 +1,67 @@ +# Test for Bug #41902 MYSQL_BIN_LOG::reset_logs() doesn't call my_error() +# in face of an error +# + +source include/have_debug.inc; +source include/master-slave.inc; + +# +# test checks that +# a. there is no crash when find_log_pos() returns with an error +# that tests expect to receive; +# b. in the case of multiple error messages the first error message is +# reported to the user and others are available as warnings. +# + +connection slave; +stop slave; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@debug_dbug="d,simulate_find_log_pos_error"; + +--error ER_UNKNOWN_TARGET_BINLOG +reset slave; +show warnings; + +SET @@debug_dbug=""; +reset slave; +change master to master_host='dummy'; + +SET @@debug_dbug="d,simulate_find_log_pos_error"; + +--error ER_UNKNOWN_TARGET_BINLOG +change master to master_host='dummy'; + +SET @@debug_dbug=""; +reset slave; +change master to master_host='dummy'; + +connection master; +SET @saved_dbug_m = @@global.debug_dbug; +SET @@debug_dbug="d,simulate_find_log_pos_error"; +--error ER_UNKNOWN_TARGET_BINLOG +reset master; + +SET @@debug_dbug=""; +reset master; + +SET @@debug_dbug="d,simulate_find_log_pos_error"; +--error ER_UNKNOWN_TARGET_BINLOG +purge binary logs to 'master-bin.000001'; + +SET @@debug_dbug=""; +purge binary logs to 'master-bin.000001'; + +--disable_query_log +call mtr.add_suppression("Failed to locate old binlog or relay log files"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index"); +set @@global.debug_dbug = @saved_dbug_m; +connection slave; +call mtr.add_suppression("Failed to locate old binlog or relay log files"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ..master-bin.000001 not listed in the index"); +--enable_query_log +SET @@GLOBAL.debug_dbug = @saved_dbug; + +--echo ==== clean up ==== +CHANGE MASTER TO MASTER_HOST = '127.0.0.1'; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test new file mode 100644 index 00000000..573c1d11 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_cant_read_event_incident.test @@ -0,0 +1 @@ +--source include/rpl_cant_read_event_incident.inc diff --git a/mysql-test/suite/rpl/t/rpl_change_master.test b/mysql-test/suite/rpl/t/rpl_change_master.test new file mode 100644 index 00000000..9ab49a58 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_change_master.test @@ -0,0 +1,111 @@ +# Verify that after CHANGE MASTER, replication (I/O thread and SQL +# thread) restart from where SQL thread left, not from where +# I/O thread left (some old bug fixed in 4.0.17) + +source include/master-slave.inc; +call mtr.add_suppression("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum"); + +connection master; +# Make SQL slave thread advance a bit +create table t1(n int); +sync_slave_with_master; +select * from t1; +# Now stop it and make I/O slave thread be ahead +stop slave sql_thread; +connection master; +insert into t1 values(1); +insert into t1 values(2); +save_master_pos; +let $slave_param= Read_Master_Log_Pos; +let $slave_param_value= query_get_value(SHOW MASTER STATUS, Position, 1); +connection slave; +source include/wait_for_slave_param.inc; +source include/stop_slave.inc; + +let $read_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1); +let $exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +if ($read_pos == $exec_pos) +{ + source include/show_rpl_debug_info.inc; + echo 'Read_Master_Log_Pos: $read_pos' == 'Exec_Master_Log_Pos: $exec_pos'; + die Failed because Read_Master_Log_Pos is equal to Exec_Master_Log_Pos; +} +change master to master_user='root'; +let $read_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1); +let $exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +if ($read_pos != $exec_pos) +{ + source include/show_rpl_debug_info.inc; + echo 'Read_Master_Log_Pos: $read_pos' <> 'Exec_Master_Log_Pos: $exec_pos'; + die Failed because Read_Master_Log_Pos is not equal to Exec_Master_Log_Pos; +} + +start slave; +sync_with_master; +select * from t1; +connection master; +drop table t1; +sync_slave_with_master; + +# End of 4.1 tests + +# +# BUG#12190 CHANGE MASTER has differ path requiremts on MASTER_LOG_FILE and RELAY_LOG_FILE +# + +if ($bug_59037_is_fixed == 'true') { +--source include/rpl_reset.inc + +connection master; +create table t1 (a int); +insert into t1 values (1); +flush logs; +insert into t1 values (2); + +# Note: the master positon saved by this will also be used by the +# 'sync_with_master' below. +sync_slave_with_master; + +# Check if the table t1 and t2 are identical on master and slave; +let $diff_tables= master:t1,slave:t1 +source include/diff_tables.inc; + +connection slave; +source include/stop_slave.inc; +delete from t1 where a=2; + +# start replication from the second insert, after fix of BUG#12190, +# relay_log_file does not use absolute path, only the filename is +# required +# +# Note: the follow change master will automatically reset +# relay_log_purge to false, save the old value to restore +let $relay_log_purge= `select @@global.relay_log_purge`; +CHANGE MASTER TO relay_log_file='slave-relay-bin.000005', relay_log_pos=4; +start slave sql_thread; +source include/wait_for_slave_sql_to_start.inc; + +# Sync to the same position saved by the 'sync_slave_with_master' above. +sync_with_master; + +# Check if the table t1 and t2 are identical on master and slave; +let $diff_tables= master:t1,slave:t1 +source include/diff_tables.inc; + +# clean up +connection slave; +start slave io_thread; +source include/wait_for_slave_io_to_start.inc; +eval set global relay_log_purge=$relay_log_purge; +connection master; +drop table t1; +} + +--connection master +# MDEV-22741: *SAN: ERROR: AddressSanitizer: use-after-poison on address in +# instrings/strmake.c:36 from change_master (on optimized builds) +CHANGE MASTER TO MASTER_USER='root', MASTER_SSL=0, MASTER_SSL_CA='', MASTER_SSL_CERT='', + MASTER_SSL_KEY='', MASTER_SSL_CRL='', MASTER_SSL_CRLPATH=''; +CHANGE MASTER TO MASTER_USER='root', MASTER_PASSWORD='', MASTER_SSL=0; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_charset.test b/mysql-test/suite/rpl/t/rpl_charset.test new file mode 100644 index 00000000..31ea2bc8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_charset.test @@ -0,0 +1,2 @@ +let $engine_type=myisam; +source include/rpl_charset.test; diff --git a/mysql-test/suite/rpl/t/rpl_charset_sjis.test b/mysql-test/suite/rpl/t/rpl_charset_sjis.test new file mode 100644 index 00000000..af4e8ff5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_charset_sjis.test @@ -0,0 +1,54 @@ +source include/have_sjis.inc; +source include/master-slave.inc; + +--disable_warnings +drop table if exists t1; +drop procedure if exists p1; +--enable_warnings +create table t1 (a varchar(255) character set sjis); +create procedure p1 (in a varchar(255) character set sjis) insert into t1 values (a); + +SET NAMES binary; +CALL p1 ('–\\'); +select hex(a) from t1 ; +sync_slave_with_master; +connection slave; +select hex(a) from t1; +connection master; +drop table t1; +drop procedure p1; +sync_slave_with_master; +connection master; + +# End of 5.0 tests + +--echo # +--echo # Start of 5.5 tests +--echo # + +--echo # +--echo # Bug#MDEV-4489 Replication of big5, cp932, gbk, sjis strings makes wrong values on slave +--echo # + +connection master; +SET NAMES sjis; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0x31),(X'31'),('1'); +PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (?)'; +SET @a='1'; +EXECUTE stmt USING @a; +DROP PREPARE stmt; +SELECT * FROM t1; +sync_slave_with_master; +connection slave; +SELECT * FROM t1; +connection master; +DROP TABLE t1; +sync_slave_with_master; +connection master; + +--echo # +--echo # End of 5.5 tests +--echo # + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_checksum-master.opt b/mysql-test/suite/rpl/t/rpl_checksum-master.opt new file mode 100644 index 00000000..a6e99a9f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum-master.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test new file mode 100644 index 00000000..0edf8fda --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum.test @@ -0,0 +1 @@ +--source include/rpl_checksum.inc diff --git a/mysql-test/suite/rpl/t/rpl_checksum_cache.test b/mysql-test/suite/rpl/t/rpl_checksum_cache.test new file mode 100644 index 00000000..59b338d2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum_cache.test @@ -0,0 +1 @@ +--source include/rpl_checksum_cache.inc diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf new file mode 100644 index 00000000..3ff94e45 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf @@ -0,0 +1,24 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[mysqld.4] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test new file mode 100644 index 00000000..8d610a87 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test @@ -0,0 +1,336 @@ +# ==== Purpose ==== +# +# Setup: circular replication on four hosts, i.e., topology +# server_1 -> server_2 -> server_3 -> server_4 -> server_1 +# +# Tested properties: +# - Correctly configured autoinc works. +# - Manual failover works. +# +# ==== Related bugs and worklogs ==== +# +# WL#3754 +# BUG#49978 + +--source include/have_innodb.inc + +# Use wait_for_slave_to_(start|stop) for current connections +let $keep_connection= 1; + +# Set up circular ring and new names for servers +--echo *** Set up circular replication on four servers *** +--let $rpl_topology= 1->2->3->4->1 +--source include/rpl_init.inc +--echo + +#set auto inc variables at each server +--let $_rpl_server= $rpl_server_count +while ($_rpl_server) +{ + connection server_$_rpl_server; + eval SET auto_increment_increment= $rpl_server_count; + eval SET auto_increment_offset= $_rpl_server; + + --dec $_rpl_server +} + +# Preparing data. +--echo *** Preparing data *** +--connection server_1 +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b VARCHAR(100), c INT NOT NULL, PRIMARY KEY(a)) ENGINE=MyISAM; +CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT, b VARCHAR(100), c INT NOT NULL, PRIMARY KEY(a)) ENGINE=InnoDB; +--source include/rpl_sync.inc +--connection server_4 +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); +--echo + +# +# Testing +# + +--echo *** Testing schema A->B->C->D->A *** +--echo +# insert data via all hosts +--connection server_1 +INSERT INTO t1(b,c) VALUES('A',1); +--sync_slave_with_master server_2 +INSERT INTO t1(b,c) VALUES('B',1); +--sync_slave_with_master server_3 +INSERT INTO t1(b,c) VALUES('C',1); +--sync_slave_with_master server_4 +INSERT INTO t1(b,c) VALUES('D',1); + +--source include/rpl_sync.inc + +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c = 1 ORDER BY a,b; +--connection server_2 +SELECT 'Master B',a,b FROM t1 WHERE c = 1 ORDER BY a,b; +--connection server_3 +SELECT 'Master C',a,b FROM t1 WHERE c = 1 ORDER BY a,b; +--connection server_4 +SELECT 'Master D',a,b FROM t1 WHERE c = 1 ORDER BY a,b; +--echo + +--echo *** Testing schema A->B->D->A if C has failure *** +--echo +--echo * Do failure for C and then make new connection B->D * + +# Note: server_N has auto_increment_offset=N. Below, we insert value 6 +# in the autoinc column on server_3 (and prevent it from replicating +# further using SQL_SLAVE_SKIP_COUNTER on server_4). Due to the +# auto_increment_offset setting, the autoinc value 6 is normally +# generated on server_2. When we later insert a row on server_2, we +# thus cause a duplicate key error on server_3. + +# Do not replicate next event from C +--connection server_4 +STOP SLAVE; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; +source include/start_slave.inc; +--connection server_3 +INSERT INTO t1 VALUES(6,'C',2); +--sync_slave_with_master server_4 + +--connection server_2 +INSERT INTO t1(b,c) VALUES('B',2); +# Wait while C will stop. +--connection server_3 +# 1062 = ER_DUP_ENTRY +call mtr.add_suppression("Slave SQL.*Duplicate entry .6. for key .PRIMARY.* error.* 1062"); +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +--connection server_1 +INSERT INTO t1(b,c) VALUES('A',2); +--connection server_4 +INSERT INTO t1(b,c) VALUES('D',2); + + +# Sync all servers except C +--connection server_2 +let $wait_condition= SELECT COUNT(*)=3 FROM t1 WHERE a > 4; +--let $server_connection= server_1 +--source include/wait_condition.inc + +--echo +--echo * Data on servers (C failed) * +# Masters C,D shouldn't have correct data +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_2 +SELECT 'Master B',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_3 +SELECT 'Master C',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_4 +SELECT 'Master D',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--echo + +--echo * Reconfigure replication to schema A->B->D->A * +# Exclude Master C +--connection server_3 +--source include/stop_slave_io.inc +--let $pos_c= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +--let $file_c= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1) + +--connection server_4 +--source include/stop_slave.inc + +--let $rpl_topology= 1->2->4->1,2->3 +--let $rpl_master_log_file= 4:$file_c +--let $rpl_master_log_pos= 4:$pos_c +--source include/rpl_change_topology.inc + +#--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 $file_c LOG_FILE $pos_c LOG_POS +#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SERVER_MYPORT_2,master_user='root',master_log_file='$file_c',master_log_pos=$pos_c +source include/start_slave.inc; +--connection server_2 +--sync_slave_with_master server_4 +--sync_slave_with_master server_1 +--echo + +--echo * Check data inserted before failure * +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_2 +SELECT 'Master B',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_3 +SELECT 'Master C',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--connection server_4 +SELECT 'Master D',a,b FROM t1 WHERE c = 2 ORDER BY a,b; +--echo + +--echo * Check data inserted after failure * +--connection server_1 +INSERT INTO t1(b,c) VALUES('A',3); +--connection server_2 +INSERT INTO t1(b,c) VALUES('B',3); +--connection server_4 +INSERT INTO t1(b,c) VALUES('D',3); +connection server_1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_sync.inc + +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c = 3 ORDER BY a,b; +--connection server_2 +SELECT 'Master B',a,b FROM t1 WHERE c = 3 ORDER BY a,b; +--connection server_3 +SELECT 'Master C',a,b FROM t1 WHERE c = 3 ORDER BY a,b; +--connection server_4 +SELECT 'Master D',a,b FROM t1 WHERE c = 3 ORDER BY a,b; +--connection server_1 +--echo + +--echo *** Testing restoring scheme A->B->C->D->A after failure *** +--echo +# Master D will ignore a next event from C so that event will not be +# distributed to other servers +--echo * Remove wrong event from C and restore B->C->D * +--connection server_4 +source include/stop_slave.inc; +--connection server_3 +DELETE FROM t1 WHERE a = 6; +--source include/start_slave.inc +--connection server_2 +--sync_slave_with_master server_3 +RESET MASTER; +--let $file_d= query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_d= query_get_value(SHOW MASTER STATUS, Position, 1) +--connection server_4 +RESET SLAVE; +--let $rpl_topology= 1->2->3->4->1 +--let $rpl_master_log_file= 4:$file_d +--let $rpl_master_log_pos= 4:$pos_d +--source include/rpl_change_topology.inc +#--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 $file_d LOG_FILE $pos_d LOG_POS +#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SERVER_MYPORT_3,master_user='root',master_log_file='$file_d',master_log_pos=$pos_d +--source include/start_slave.inc +--connection server_3 +--sync_slave_with_master server_4 +--source include/rpl_sync.inc + +--echo +--echo * Check data inserted before restoring schema A->B->C->D->A * +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b; +--sync_slave_with_master server_2 +SELECT 'Master B',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b; +--sync_slave_with_master server_3 +SELECT 'Master C',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b; +--sync_slave_with_master server_4 +SELECT 'Master D',a,b FROM t1 WHERE c IN (2,3) ORDER BY a,b; +--sync_slave_with_master server_1 +--echo + +--echo * Check data inserted after restoring schema A->B->C->D->A * +--connection server_1 +INSERT INTO t1(b,c) VALUES('A',4); +--connection server_2 +INSERT INTO t1(b,c) VALUES('B',4); +--connection server_3 +INSERT INTO t1(b,c) VALUES('C',4); +--connection server_4 +INSERT INTO t1(b,c) VALUES('D',4); +--connection server_1 + +--source include/rpl_sync.inc + +--connection server_1 +SELECT 'Master A',a,b FROM t1 WHERE c = 4 ORDER BY a,b; +--connection server_2 +SELECT 'Master B',a,b FROM t1 WHERE c = 4 ORDER BY a,b; +--connection server_3 +SELECT 'Master C',a,b FROM t1 WHERE c = 4 ORDER BY a,b; +--connection server_4 +SELECT 'Master D',a,b FROM t1 WHERE c = 4 ORDER BY a,b; +--connection server_1 +--echo + +--echo * Transactions with commits * +# Testing mixing of transactions and regular inserts +--connection server_1 +BEGIN; +--connection server_3 +BEGIN; +let $counter= 100; +--connection server_1 +--disable_query_log +while ($counter) { + --connection server_1 + INSERT INTO t2(b,c) VALUES('A',1); + --connection server_2 + INSERT INTO t2(b,c) VALUES('B',1); + --connection server_3 + INSERT INTO t2(b,c) VALUES('C',1); + --connection server_4 + INSERT INTO t2(b,c) VALUES('D',1); + dec $counter; +} +--connection server_1 +COMMIT; +--connection server_3 +COMMIT; +--connection server_1 +--enable_query_log + +--source include/rpl_sync.inc + +--connection server_1 +SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; +--connection server_2 +SELECT 'Master B',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; +--connection server_3 +SELECT 'Master C',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; +--connection server_4 +SELECT 'Master D',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; +--connection server_1 +--echo + +--echo * Transactions with rollbacks * +# Testing mixing of transactions with rollback and regular inserts +--connection server_1 +BEGIN; +--connection server_3 +BEGIN; +let $counter= 100; +--connection server_1 +--disable_query_log +while ($counter) { + --connection server_1 + INSERT INTO t2(b,c) VALUES('A',2); + --connection server_2 + INSERT INTO t2(b,c) VALUES('B',2); + --connection server_3 + INSERT INTO t2(b,c) VALUES('C',2); + --connection server_4 + INSERT INTO t2(b,c) VALUES('D',2); + dec $counter; +} +--connection server_1 +ROLLBACK; +--connection server_3 +ROLLBACK; +--connection server_1 +--enable_query_log + +--source include/rpl_sync.inc + +--connection server_1 +SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; +--connection server_2 +SELECT 'Master B',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; +--connection server_3 +SELECT 'Master C',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; +--connection server_4 +SELECT 'Master D',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; +--connection server_1 + +--echo + +# Clean up +--echo *** Clean up *** +--connection server_1 +DROP TABLE t1,t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_colSize.test b/mysql-test/suite/rpl/t/rpl_colSize.test new file mode 100644 index 00000000..d6f817af --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_colSize.test @@ -0,0 +1,228 @@ +################################################################## +# rpl_colSize # +# # +# This test is designed to test the changes included in WL#3228. # +# The changes include the ability to replicate with the master # +# having columns that are smaller (shorter) than the slave. # +################################################################## + +-- source include/master-slave.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo **** Testing WL#3228 changes. **** +--echo *** Create "wider" table on slave *** +sync_slave_with_master; +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +RESET SLAVE; + +SET @saved_slave_type_conversions = @@slave_type_conversions; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = 'ALL_NON_LOSSY'; + +eval CREATE TABLE t1 ( + a float (47), + b double (143,9), + c decimal (65,30), + d numeric (4,0), + e bit (32), + f char (21), + g varchar (1300), + h binary (33), + j varbinary (200), + k enum ('5','6','7', '8','9','0'), + l set ('1','2','3','4','5','6','7','8','9','0','11','12','13','14','15','16','17','18','19','21','22','23','24','25','26','27','28','29'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +--echo *** Create same table on master but with narrow columns *** +connection master; +eval CREATE TABLE t1 ( + a float (44), + b double (10,3), + c decimal (10,2), + d numeric (3,0), + e bit (16), + f char (10), + g varchar (100), + h binary (20), + j varbinary (20), + k enum ('5','6','7'), + l set ('1','2','3','4','5','6','7','8','9','0'), + m TINYBLOB, + n BLOB, + o MEDIUMBLOB, + p LONGBLOB, + q TINYTEXT, + r TEXT, + s MEDIUMTEXT, + t LONGTEXT +); + +RESET MASTER; + +--echo *** Start replication *** +connection slave; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +--echo *** Insert data on master and display it. *** +connection master; + +INSERT INTO t1 () VALUES ( + 17.567, + 2.123, + 10.20, + 125, + hex(64), + 'TEST', + 'This is a test', + 'binary data', + 'more binary data', + '6', + '7', + "blob 1", + "blob 2", + "blob 3", + "blob 4", + "text 1", + "text 2", + "text 3", + "text 4"); + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +--echo *** Select data from slave to compare *** +sync_slave_with_master; +connection slave; + +# Replace values in columns that display differently between SBR & RBR +--replace_column 5 # 8 # +SELECT * FROM t1 ORDER BY a; + +# Test boundary limits of varchar and char fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col a +# >255/<256 with m < s, m > s, and m == s <-- error will be caught in BUG#22086 +# <256/>255 with m < s, m > s, and m == s <-- col b +# >255/>255 with m < s, m > s, and m == s <-- col c +# +# Test boundary limits of CHAR fields +# Master/Slave +# <256/<256 with m < s, m > s, and m == s <-- col d +# >255/<256 with m < s, m > s, and m == s <-- error char limited to 255 chars +# <256/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars +# >255/>255 with m < s, m > s, and m == s <-- error char limited to 255 chars + +connection master; +DROP TABLE t1; + +--echo Create varchar table on master +CREATE TABLE t1 ( + a VARCHAR(50), + b VARCHAR(100), + c VARCHAR(300), + d CHAR(5) +); + +sync_slave_with_master slave; + +--echo Alter varchar table on slave +ALTER TABLE t1 CHANGE COLUMN a a VARCHAR(100); +ALTER TABLE t1 CHANGE COLUMN b b VARCHAR(400); +ALTER TABLE t1 CHANGE COLUMN c c VARCHAR(500); +ALTER TABLE t1 CHANGE COLUMN d d CHAR(100); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ("This is a test of col a.", + "This is another test of col b.", + "This is a test of the large col c.", + "Col d"); +SELECT * FROM t1; +--replace_result default DEFAULT +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on slave +SELECT * FROM t1; +--replace_result default DEFAULT +SHOW CREATE TABLE t1; + + +# Test boundary limits of bit fields +# m < s, m % 8 != 0, and s % 8 == 0 col a +# m < s, m % 8 == 0, and s % 8 != 0 col b +# m < s, m % 8 != 0, and s % 8 != 0 col c +# m > s, m % 8 != 0, and s % 8 == 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 == 0, and s % 8 != 0 <-- error will be caught in BUG#22086 +# m > s, m % 8 != 0, and s % 8 != 0 <-- error will be caught in BUG#22086 + +connection master; +DROP TABLE t1; + +--echo Create bit table on master +CREATE TABLE t1 ( + a BIT(7), + b BIT(8), + c BIT(21), + d BIT(11), + e BIT(11) +); + +sync_slave_with_master slave; + +--echo Create bit table on slave +DROP TABLE t1; +CREATE TABLE t1 ( + a BIT(16), + b BIT(22), + c BIT(54), + d BIT(25), + e BIT(13) +); + +connection master; + +--echo Insert some values and select them on master +INSERT INTO t1 VALUES ( + b'1010101', + b'10101011', + b'101010110101010101111', + b'10101010101', + b'10101011111' + ); + +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +--replace_result default DEFAULT +SHOW CREATE TABLE t1; + +sync_slave_with_master slave; + +--echo Insert some values and select them on master +SELECT BIN(a), BIN(b), BIN(c), BIN(d), BIN(e) FROM t1; +--replace_result default DEFAULT +SHOW CREATE TABLE t1; + +--echo *** Cleanup *** +connection master; +DROP TABLE t1; +sync_slave_with_master; + +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions; + +# END 5.1 Test Case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_commit_after_flush.test b/mysql-test/suite/rpl/t/rpl_commit_after_flush.test new file mode 100644 index 00000000..5d547908 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_commit_after_flush.test @@ -0,0 +1,5 @@ +-- source include/have_innodb.inc +-- source include/master-slave.inc +let $engine_type=innodb; +-- source include/rpl_commit_after_flush.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt new file mode 100644 index 00000000..3f82baff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt @@ -0,0 +1 @@ +--loose-innodb-lock-wait-timeout=1 diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error.test b/mysql-test/suite/rpl/t/rpl_concurrency_error.test new file mode 100644 index 00000000..72179ef2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_concurrency_error.test @@ -0,0 +1,150 @@ +############################################################################### +#BUG#44581 Slave stops when transaction with non-transactional table gets +#lock wait timeout +# +# In STMT and MIXED modes, a statement that changes both non-transactional and +# transactional tables must be written to the binary log whenever there are +# changes to non-transactional tables. This means that the statement gets into +# the # binary log even when the changes to the transactional tables fail. In +# particular, in the presence of a failure such statement is annotated with the +# error number and wrapped in a begin/rollback. On the slave, while applying +# the statement, it is expected the same failure and the rollback prevents the +# transactional changes to be persisted. + +# This test aims to verify if a statement that updates both transactional and +# non-transacitonal tables and fails due to concurrency problems is correctly +# processed by the slave in the sense that the statements get into the binary +# log, the error is ignored and only the non-transactional tables are changed. +############################################################################### + +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +--echo ######################################################################## +--echo # Environment +--echo ######################################################################## +connection master; + +CREATE TABLE t (i INT, PRIMARY KEY(i), f CHAR(8)) engine = Innodb; +CREATE TABLE n (d DATETIME, f CHAR(32)) engine = MyIsam; + +DELIMITER |; +CREATE TRIGGER tr AFTER UPDATE ON t FOR EACH ROW +BEGIN + INSERT INTO n VALUES ( now(), concat( 'updated t: ', old.f, ' -> ', new.f ) ); +END | +DELIMITER ;| + +INSERT INTO t VALUES (4,'black'), (2,'red'), (3,'yelow'), (1,'cyan'); + +connect (conn1, 127.0.0.1,root,,); +connect (conn2, 127.0.0.1,root,,); + +--echo ######################################################################## +--echo # Testing ER_LOCK_WAIT_TIMEOUT +--echo ######################################################################## + +let $type=2; + +while ($type) +{ + let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); + connection conn1; + if ($type == 2) + { + SET AUTOCOMMIT = 1; + BEGIN; + } + if ($type == 1) + { + SET AUTOCOMMIT = 0; + } + eval UPDATE t SET f = 'yellow $type' WHERE i = 3; + + connection conn2; + if ($type == 2) + { + SET AUTOCOMMIT = 1; + BEGIN; + } + if ($type == 1) + { + SET AUTOCOMMIT = 0; + } + --error ER_LOCK_WAIT_TIMEOUT + eval UPDATE IGNORE t SET f = 'magenta $type' WHERE f = 'red'; + eval INSERT INTO t VALUES (5 + ($type * 10),"brown"); + INSERT INTO n VALUES (now(),"brown"); + + connection conn1; + COMMIT; + + connection conn2; + ROLLBACK; + --source include/show_binlog_events.inc + + let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); + connection conn1; + if ($type == 2) + { + SET AUTOCOMMIT = 1; + BEGIN; + } + if ($type == 1) + { + SET AUTOCOMMIT = 0; + } + eval UPDATE t SET f = 'gray $type' WHERE i = 3; + + connection conn2; + if ($type == 2) + { + SET AUTOCOMMIT = 1; + BEGIN; + } + if ($type == 1) + { + SET AUTOCOMMIT = 0; + } + --error ER_LOCK_WAIT_TIMEOUT + eval UPDATE IGNORE t SET f = 'dark blue $type' WHERE f = 'red'; + eval INSERT INTO t VALUES (6 + ($type * 10),"brown"); + INSERT INTO n VALUES (now(),"brown"); + + connection conn1; + COMMIT; + + connection conn2; + COMMIT; + --source include/show_binlog_events.inc + + dec $type; +} + +connection master; +sync_slave_with_master; + +let $rpl_diff_statement= SELECT * FROM t order by i; +source include/rpl_diff.inc; + +let $rpl_diff_statement= SELECT * FROM n order by d, f; +source include/rpl_diff.inc; + +--echo ######################################################################## +--echo # Cleanup +--echo ######################################################################## + +connection master; +DROP TRIGGER tr; +DROP TABLE t; +DROP TABLE n; + +sync_slave_with_master; + +connection master; +disconnect conn1; +disconnect conn2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_conditional_comments.test b/mysql-test/suite/rpl/t/rpl_conditional_comments.test new file mode 100644 index 00000000..6e4ec874 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_conditional_comments.test @@ -0,0 +1,84 @@ +############################################################################### +# After the patch for BUG#49124: +# - Use ' ' instead of '!' in the conditional comments which are not applied on +# master. So they become common comments and will not be applied on slave. +# +# - Example: +# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*!999999 ,(3)*/ +# will be binlogged as +# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /* 99999 ,(3)*/'. +############################################################################### +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +CREATE TABLE t1(c1 INT); +source include/show_binlog_events.inc; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +--echo +--echo # Case 1: +--echo # ------------------------------------------------------------------ +--echo # In a statement, some CCs are applied while others are not. The CCs +--echo # which are not applied on master will be binlogged as common comments. + +/*!999999 --- */INSERT /*!INTO*/ /*!10000 t1 */ VALUES(10) /*!999999 ,(11)*/; + +source include/show_binlog_events.inc; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +sync_slave_with_master; +--let $diff_tables= master:t1,slave:t1 +--source include/diff_tables.inc + +--echo +--echo # Case 2: +--echo # ----------------------------------------------------------------- +--echo # Verify whether it can be binlogged correctly when executing prepared +--echo # statement. +--connection master +PREPARE stmt FROM 'INSERT INTO /*!999999 blabla*/ t1 VALUES(60) /*!999999 ,(61)*/'; +EXECUTE stmt; +DROP TABLE t1; +CREATE TABLE t1(c1 INT); +EXECUTE stmt; + +sync_slave_with_master; +--let $diff_tables= master:t1,slave:t1 +--source include/diff_tables.inc + +--connection master +--echo +SET @value=62; +PREPARE stmt FROM 'INSERT INTO /*!999999 blabla */ t1 VALUES(?) /*!999999 ,(63)*/'; +EXECUTE stmt USING @value; +DROP TABLE t1; +CREATE TABLE t1(c1 INT); +EXECUTE stmt USING @value; + +source include/show_binlog_events.inc; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +sync_slave_with_master; +--let $diff_tables= master:t1,slave:t1 +--source include/diff_tables.inc + +--echo +--echo # Case 3: +--echo # ----------------------------------------------------------------- +--echo # Verify it can restore the '!', if the it is an uncomplete conditional +--echo # comments +--connection master +--error 1064 +SELECT c1 FROM /*!999999 t1 WHEREN; #*/ + +# +# Bug#28388217 - SERVER CAN FAIL WHILE REPLICATING CONDITIONAL COMMENTS +# +insert t1 values (/*!50505 1 /* foo */ */ + 2); +insert t1 values (/*!999999 10 /* foo */ */ + 20); +source include/show_binlog_events.inc; +sync_slave_with_master; +select * from t1; +connection master; + +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_connection.test b/mysql-test/suite/rpl/t/rpl_connection.test new file mode 100644 index 00000000..31024006 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_connection.test @@ -0,0 +1,24 @@ +--source include/not_embedded.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +# +# BUG#13427949: CHANGE MASTER TO USER='' (EMPTY USER) CAUSES ERRORS ON VALGRING +# + +--connection slave +call mtr.add_suppression(".*Invalid .* username when attempting to connect to the master server.*"); + + +# Assert that we disallow empty users and that no problem +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USER= '', MASTER_PASSWORD= ''; +START SLAVE; +--let $slave_io_errno= 1045, 1593 +--source include/wait_for_slave_io_error.inc +--source include/stop_slave.inc + +CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD= ''; +START SLAVE; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_corruption-master.opt b/mysql-test/suite/rpl/t/rpl_corruption-master.opt new file mode 100644 index 00000000..2612c17a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption-master.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 --master-verify-checksum=1 diff --git a/mysql-test/suite/rpl/t/rpl_corruption-slave.opt b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt new file mode 100644 index 00000000..b32a5240 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 --slave-sql-verify-checksum=1 diff --git a/mysql-test/suite/rpl/t/rpl_corruption.test b/mysql-test/suite/rpl/t/rpl_corruption.test new file mode 100644 index 00000000..e51d1c65 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption.test @@ -0,0 +1 @@ +--source include/rpl_corruption.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_database-master.opt b/mysql-test/suite/rpl/t/rpl_create_database-master.opt new file mode 100644 index 00000000..85660a17 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_database-master.opt @@ -0,0 +1 @@ +--binlog-do-db=mysqltest_sisyfos --binlog-do-db=mysqltest_prometheus diff --git a/mysql-test/suite/rpl/t/rpl_create_database-slave.opt b/mysql-test/suite/rpl/t/rpl_create_database-slave.opt new file mode 100644 index 00000000..96d630c9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_database-slave.opt @@ -0,0 +1 @@ +--replicate-do-db=mysqltest_sisyfos --replicate-do-db=mysqltest_prometheus diff --git a/mysql-test/suite/rpl/t/rpl_create_database.test b/mysql-test/suite/rpl/t/rpl_create_database.test new file mode 100644 index 00000000..5eac3de0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_database.test @@ -0,0 +1,73 @@ +# +# Tests for replication of statements that manipulate databases. +# +# For this test file, we have a number of databases. All databases +# with "greek" names will be replicated on the slave, while other names +# (e.g., american) will not be replicated. +# + +source include/master-slave.inc; + +# Bug#6391 (binlog-do-db rules ignored) +# In this case, 'mysqltest_bob' should not be replicated to the slave. +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_prometheus; +DROP DATABASE IF EXISTS mysqltest_sisyfos; +DROP DATABASE IF EXISTS mysqltest_bob; +sync_slave_with_master; +# This database is not replicated +DROP DATABASE IF EXISTS mysqltest_bob; +--enable_warnings + +connection master; +CREATE DATABASE mysqltest_prometheus; +CREATE DATABASE mysqltest_sisyfos; +CREATE DATABASE mysqltest_bob; + +USE mysqltest_sisyfos; +# These should be replicated +CREATE TABLE t1 (b int); +INSERT INTO t1 VALUES(1); + +USE mysqltest_bob; +# These should *not* be replicated +CREATE TABLE t2 (b int); +INSERT INTO t2 VALUES(2); + +# Current database is now 'mysqltest_bob' +# The following should be replicated +ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1; + +USE mysqltest_sisyfos; +# The following should *not* be replicated +ALTER DATABASE mysqltest_bob CHARACTER SET latin1; + +SHOW DATABASES LIKE 'mysql%'; +sync_slave_with_master; +SHOW DATABASES LIKE 'mysql%'; + +connection master; +DROP DATABASE IF EXISTS mysqltest_sisyfos; +USE mysqltest_prometheus; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +CREATE DATABASE mysqltest_sisyfos; +USE mysqltest_sisyfos; +CREATE TABLE t2 (a INT); +let $VERSION=`select version()`; +SHOW DATABASES LIKE 'mysql%'; +sync_slave_with_master; +SHOW DATABASES LIKE 'mysql%'; +USE mysqltest_prometheus; +SHOW TABLES; +USE mysqltest_sisyfos; +SHOW TABLES; + +connection master; +DROP DATABASE IF EXISTS mysqltest_prometheus; +DROP DATABASE IF EXISTS mysqltest_sisyfos; +DROP DATABASE IF EXISTS mysqltest_bob; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_db.test b/mysql-test/suite/rpl/t/rpl_create_drop_db.test new file mode 100644 index 00000000..04721c9c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_db.test @@ -0,0 +1,33 @@ +--source include/master-slave.inc + +connection master; + +CREATE DATABASE db1; +CREATE DATABASE IF NOT EXISTS db1; +CREATE OR REPLACE DATABASE db2; +CREATE OR REPLACE DATABASE db1; +sync_slave_with_master; + +SHOW DATABASES LIKE 'db%'; + +connection master; +--error ER_DB_CREATE_EXISTS +CREATE DATABASE db1; + +--error ER_DB_DROP_EXISTS +DROP DATABASE db3; + +CREATE DATABASE IF NOT EXISTS db3; +sync_slave_with_master; + +SHOW DATABASES LIKE 'db%'; + +connection master; +DROP DATABASE db1; +DROP DATABASE db2; +DROP DATABASE IF EXISTS db3; +sync_slave_with_master; + +SHOW DATABASES LIKE 'db%'; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_event.test b/mysql-test/suite/rpl/t/rpl_create_drop_event.test new file mode 100644 index 00000000..96a7e82d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_event.test @@ -0,0 +1,27 @@ +--source include/master-slave.inc + +connection master; +SET GLOBAL event_scheduler=off; + +CREATE TABLE t1 (a INT); +CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (10); +--error ER_EVENT_ALREADY_EXISTS +CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11); +CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (11); +SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS; + +SET GLOBAL event_scheduler=on; +let $wait_condition= SELECT count(*)>0 FROM t1; +--source include/wait_condition.inc +SET GLOBAL event_scheduler=off; +SELECT DISTINCT a FROM t1; +DELETE FROM t1; + +--echo # Syncing slave with master +sync_slave_with_master; +SELECT EVENT_NAME,STATUS,EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS; +connection master; +DROP TABLE t1; +DROP EVENT ev1; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_function.test b/mysql-test/suite/rpl/t/rpl_create_drop_function.test new file mode 100644 index 00000000..5ae0b765 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_function.test @@ -0,0 +1,54 @@ +--source include/master-slave.inc + +connection master; + +CREATE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Hello, ', str, '!'); + +--error ER_SP_ALREADY_EXISTS +CREATE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Hello, ', str, '!'); + +sync_slave_with_master; + +SHOW CREATE FUNCTION hello; + +connection master; + +--error ER_WRONG_USAGE +CREATE OR REPLACE FUNCTION IF NOT EXISTS hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Hello, ', str, '!'); + +CREATE OR REPLACE FUNCTION hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Hello, ', str, '!'); + +SELECT hello('master'); +sync_slave_with_master; + +SELECT hello('slave'); + +connection master; +CREATE FUNCTION IF NOT EXISTS hello (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Hello, ', str, '!'); + +CREATE OR REPLACE FUNCTION bye (str CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN +CONCAT('Bye, ', str, '!'); + +SELECT hello('master'); +SELECT bye('master'); +sync_slave_with_master; + +SELECT hello('slave'); +SELECT bye('slave'); + +connection master; +DROP FUNCTION hello; +DROP FUNCTION IF EXISTS bye; +sync_slave_with_master; + +--error ER_SP_DOES_NOT_EXIST +DROP FUNCTION hello; + +DROP FUNCTION IF EXISTS bye; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_index.test b/mysql-test/suite/rpl/t/rpl_create_drop_index.test new file mode 100644 index 00000000..f1b65349 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_index.test @@ -0,0 +1,17 @@ +--source include/master-slave.inc + +connection master; + +CREATE TABLE t1 (a INT, b INT); +CREATE INDEX i1 ON t1 (a); +CREATE OR REPLACE INDEX i1 ON t1 (a, b); +sync_slave_with_master; + +SHOW CREATE TABLE t1; + +connection master; +SHOW CREATE TABLE t1; +DROP TABLE t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test b/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test new file mode 100644 index 00000000..6fb0313c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_procedure.test @@ -0,0 +1,81 @@ +--source include/master-slave.inc + +connection master; +CREATE TABLE t1 (id INT); +DELIMITER $$; +CREATE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ +DELIMITER ;$$ +CALL proc1(@cnt); +SELECT @cnt; +INSERT INTO t1 VALUES (1), (2), (3); +CALL proc1(@cnt); +SELECT @cnt; + +--echo # Syncing with slave +sync_slave_with_master; + +CALL proc1(@cnt); +SELECT @cnt; + +connection master; +DELIMITER $$; +--error ER_SP_ALREADY_EXISTS +CREATE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ + +CREATE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ + +--error ER_WRONG_USAGE +CREATE OR REPLACE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ + +CREATE OR REPLACE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ +DELIMITER ;$$ + +--echo # Syncing with slave +sync_slave_with_master; + +CALL proc1(@cnt); +SELECT @cnt; + +connection master; +DROP PROCEDURE proc1; +DELIMITER $$; +CREATE PROCEDURE IF NOT EXISTS proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ +DELIMITER ;$$ +INSERT INTO t1 VALUES (1), (2), (3); +CALL proc1(@cnt); +SELECT @cnt; + +--echo # Syncing with slave +sync_slave_with_master; + +CALL proc1(@cnt); +SELECT @cnt; + +connection master; +DROP PROCEDURE proc1; +DELIMITER $$; +CREATE OR REPLACE PROCEDURE proc1 (OUT cnt INT) BEGIN SELECT COUNT(*) INTO cnt FROM t1; END$$ +DELIMITER ;$$ +INSERT INTO t1 VALUES (1), (2), (3); +CALL proc1(@cnt); +SELECT @cnt; + +--echo # Syncing with slave +sync_slave_with_master; + +CALL proc1(@cnt); +SELECT @cnt; + +connection master; +DROP TABLE IF EXISTS t1; +DROP PROCEDURE proc1; + +DROP PROCEDURE IF EXISTS proc2; + +--echo # Syncing with slave +sync_slave_with_master; + +--error ER_SP_DOES_NOT_EXIST +DROP PROCEDURE proc1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_role.test b/mysql-test/suite/rpl/t/rpl_create_drop_role.test new file mode 100644 index 00000000..7260b473 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_role.test @@ -0,0 +1,48 @@ +--source include/master-slave.inc + +connection master; +CREATE ROLE role_1; +sync_slave_with_master; + +SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User; + +connection master; +CREATE ROLE IF NOT EXISTS role_1; +CREATE ROLE IF NOT EXISTS role_2; +sync_slave_with_master; + +SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User; + +connection master; + +--error ER_WRONG_USAGE +CREATE OR REPLACE ROLE IF NOT EXISTS role_3; + +CREATE OR REPLACE ROLE role_3; +CREATE OR REPLACE ROLE role_2; +sync_slave_with_master; + +SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User; + +connection master; +--error ER_CANNOT_USER +CREATE ROLE role_2; + +sync_slave_with_master; + +SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User; + +connection master; +DROP ROLE role_1; +DROP ROLE IF EXISTS role_2; +DROP ROLE IF EXISTS role_3; +DROP ROLE IF EXISTS role_4; + +--error ER_CANNOT_USER +DROP ROLE role_4; + +sync_slave_with_master; + +SELECT User FROM mysql.user WHERE is_role='Y' ORDER BY User; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test b/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test new file mode 100644 index 00000000..568d4e22 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_trigger.test @@ -0,0 +1,48 @@ +--source include/master-slave.inc + +--echo # Part 1 - initial creation +connection master; +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (val INT); +CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 1; +SET @sum=0; +INSERT INTO t1 VALUES (10), (20), (30); +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; +sync_slave_with_master; +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; + +--echo # Part 2 - CREATE IF NOT EXISTS (on a existing trigger) +connection master; +CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 2; +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; +sync_slave_with_master; +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; + +--echo # Part 3 - CREATE OR REPLACE (on a existing trigger) +connection master; +CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 3; +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; +sync_slave_with_master; +SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum'; + +--echo # Clearing up +connection master; +DROP TRIGGER val_sum; +DROP TABLE t1; +DROP TRIGGER IF EXISTS val_sum; + +--error ER_TRG_DOES_NOT_EXIST +DROP TRIGGER random_trigger; +DROP DATABASE db1; + +--error ER_NO_DB_ERROR +DROP TRIGGER IF EXISTS val_sum; + +--echo # Syncing slave with master +sync_slave_with_master; + +--error ER_TRG_DOES_NOT_EXIST +DROP TRIGGER val_sum; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_udf.test b/mysql-test/suite/rpl/t/rpl_create_drop_udf.test new file mode 100644 index 00000000..af24cabd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_udf.test @@ -0,0 +1,56 @@ +--source include/have_udf.inc +--source include/master-slave.inc + +connection master; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; +SELECT metaphon('master'); + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +--error ER_UDF_EXISTS +eval CREATE FUNCTION metaphon RETURNS INT SONAME "$UDF_EXAMPLE_SO"; + +sync_slave_with_master; + +SELECT metaphon('slave'); + +connection master; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; +DROP FUNCTION IF EXISTS random_function_name; +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +--error ER_WRONG_USAGE +eval CREATE OR REPLACE FUNCTION IF NOT EXISTS metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; +sync_slave_with_master; + +SELECT metaphon('slave'); + +connection master; +DROP FUNCTION metaphon; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE OR REPLACE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +--error ER_UDF_EXISTS +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; +sync_slave_with_master; + +SELECT metaphon('slave'); + +connection master; +DROP FUNCTION metaphon; +DROP FUNCTION IF EXISTS metaphon; +sync_slave_with_master; + +--error ER_SP_DOES_NOT_EXIST +DROP FUNCTION metaphon; + +DROP FUNCTION IF EXISTS metaphon; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_user.test b/mysql-test/suite/rpl/t/rpl_create_drop_user.test new file mode 100644 index 00000000..c5f193a0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_user.test @@ -0,0 +1,57 @@ +--source include/master-slave.inc + +connection master; +CREATE USER u1@localhost IDENTIFIED BY 'abcdefghijk'; +connect (user_a, localhost, u1,'abcdefghijk',); +connection user_a; +SELECT CURRENT_USER; +disconnect user_a; + +connection master; +CREATE USER IF NOT EXISTS u2@localhost; +connect (user_a, localhost, u2,,); +connection user_a; +SELECT CURRENT_USER; +disconnect user_a; + +connection master; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +sync_slave_with_master; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; + +connection master; +CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'abcdefghijk2'; +connect (user_a, localhost, u1,'abcdefghijk2',); +connection user_a; +SELECT CURRENT_USER; +disconnect user_a; +connection master; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +sync_slave_with_master; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; + +connection master; +--error ER_CANNOT_USER +CREATE USER u1@localhost; + +--error ER_CANNOT_USER +DROP USER u3@localhost; + +sync_slave_with_master; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; + +connection master; +DROP USER IF EXISTS u1@localhost; +DROP USER u2@localhost; +DROP USER IF EXISTS u3@localhost; +sync_slave_with_master; + +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_view.test b/mysql-test/suite/rpl/t/rpl_create_drop_view.test new file mode 100644 index 00000000..4abb3ffb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_view.test @@ -0,0 +1,56 @@ +--source include/master-slave.inc + +connection master; +CREATE TABLE t1(id INT); +CREATE VIEW v1 AS SELECT * FROM t1 WHERE id>10; +INSERT INTO t1 VALUES (5), (8), (10), (20), (30); +SELECT * FROM t1; +SELECT * FROM v1; + +--echo # Syncing slave with master +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM v1; + +connection master; +--error ER_TABLE_EXISTS_ERROR +CREATE VIEW v1 AS SELECT * FROM t1 WHERE id>10; + +CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10; + +--error ER_WRONG_USAGE +CREATE OR REPLACE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10; + +--echo # Syncing slave with master +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM v1; + +connection master; +CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1 WHERE id>10; +INSERT INTO t1 VALUES (50), (80), (3), (2), (40); +SELECT * FROM t1; +SELECT * FROM v1; + +--echo # Syncing slave with master +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM v1; + +connection master; +RENAME TABLE v1 TO v2; +DROP VIEW v2; +DROP TABLE t1; + +--error ER_UNKNOWN_VIEW +DROP VIEW v1; + +DROP VIEW IF EXISTS v2; + +--echo # Syncing slave with master +sync_slave_with_master; + +--error ER_NO_SUCH_TABLE +SELECT * FROM v1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test new file mode 100644 index 00000000..b27250f9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test @@ -0,0 +1,195 @@ +# BUG#45574: +# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists. +# +# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and +# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are +# binlogged even if either the DB, TABLE or EVENT does not exist. In +# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT +# exists. +# +# This problem caused some of the tests to fail randomly on PB or PB2. +# +# Description: +# Fixed this bug by adding calls to write_bin_log in: +# mysql_create_db +# mysql_create_table_no_lock +# mysql_create_like_table +# create_table_from_items +# +# Test is implemented as follows: +# i) test each "CREATE IF NOT EXISTS" (DDL), found in MySQL 5.1 manual +# exclude CREATE TEMPORARY TABLE, on existent objects; +# +# Note: +# rpl_create_tmp_table_if_not_exists.test tests CREATE TEMPORARY TABLE cases. +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# + +source include/master-slave.inc; +disable_warnings; +DROP DATABASE IF EXISTS mysqltest; + +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +sync_slave_with_master; + +connection slave; +#DROP database from slave. +#The database and all tables can be recreated in slave +#if binlog of the second CREATE command is recorded and sent from master to slave. +DROP DATABASE mysqltest; + +connection master; +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +# The following will not be logged because t2 existed and we will not +# put the data of SELECT into the binary log +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +sync_slave_with_master; + +connection slave; +SHOW TABLES in mysqltest; +#Execution time changes in each run. So we disregard it by calling replace_column. +replace_column 6 #; +SHOW EVENTS in mysqltest; + + +connection master; +DROP DATABASE IF EXISTS mysqltest; + +# +# BUG#47418 RBR fails, failure with mixup of base/temporary/view TABLE DDL +# +# Before the patch for this bug, 'CREATE TABLE IF NOT EXIST ... SELECT' +# statement was binlogged as a TEMPORARY table if the object existed as +# a temporary table. This was caused by that the temporary table was opened +# and the results of the 'SELECT' was inserted into the temporary table if +# a temporary table existed with the same name. +# +# After the patch for this bug, the base table is created and the results of +# the 'SELECT' are inserted into it, even though a temporary table exists with +# the same name, and the statement is still binlogged as a base table. +# + +echo -------------BUG#47418-------------; +connection master; +USE test; +DROP TABLE IF EXISTS t3; +--enable_warnings +CREATE TABLE t3(c1 INTEGER); +INSERT INTO t3 VALUES(33); + +CREATE TEMPORARY TABLE t1(c1 INTEGER); +CREATE TEMPORARY TABLE t2(c1 INTEGER); +INSERT INTO t1 VALUES(1); +INSERT INTO t2 VALUES(1); + +CREATE TABLE IF NOT EXISTS t1(c1 INTEGER) SELECT c1 FROM t3; +CREATE TABLE t2(c1 INTEGER) SELECT c1 FROM t3; + +# In these two statements, t1 and t2 are the temporary table. there is only +# value '1' in them. The records of t2 are not inserted into them. +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master; + +# In these two statements, t1 and t2 are the base table. The records of t2 +# are inserted into it when CREATE TABLE ... SELECT was executed. +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP TEMPORARY TABLE t1; +DROP TEMPORARY TABLE t2; +#In these two statements, t1 and t2 are the base table. +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--echo # WL#5370 +--echo # The behavior of statement 'CREATE TABLE SELECT IF NOT EXISTS' is changed. +--echo # After the worklog, it will insert nothing and the statement will not be +--echo # binlogged if the table already exists. +--echo # After the worklog, some bugs will disappear automotically. +--source include/rpl_reset.inc + +--echo +--echo # Case 1: BUG#47132 +connection master; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); + +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int); +INSERT INTO t1 VALUES (1), (1); +INSERT INTO t2 VALUES (2), (2); + +CREATE VIEW v1 AS SELECT id FROM t2; +--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE TABLE IF NOT EXISTS v1(a int, b int) SELECT id, id as di FROM t1; +--source include/show_binlog_events.inc + +SHOW CREATE TABLE v1; +SELECT * FROM t2; +SELECT * FROM v1; +DROP VIEW v1; + +# the warning only happens on SBR, so we disable it. +--disable_warnings +CREATE TEMPORARY TABLE tt1 AS SELECT id FROM t2; +--enable_warnings + +--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE TEMPORARY TABLE IF NOT EXISTS tt1(a int, b int) SELECT id, id FROM t1; +--source include/show_binlog_events.inc +SELECT * FROM t2; +SELECT * FROM tt1; +DROP TEMPORARY TABLE tt1; + +--echo +--echo # Case 1: BUG#47132 +--echo # RBR breaks on CREATE TABLE IF EXISTS <existing VIEW> AS SELECT +CREATE VIEW v1 AS SELECT 1 as a; +--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE TABLE IF NOT EXISTS v1 SELECT 2 as a; +--source include/show_binlog_events.inc +sync_slave_with_master; + +connection master; +DROP VIEW v1; + +DROP TABLE t1, t2; + + +--echo # +--echo # Test case which has failed on assertion after refactoring which was +--echo # made as part of fix for bug #27480 "Extend CREATE TEMPORARY TABLES +--echo # privilege to allow temp table operations". +--echo # +CREATE TEMPORARY TABLE t1 (id int); +CREATE TABLE IF NOT EXISTS t2 LIKE t1; +--echo # The below statement should succeed with warning and +--echo # should not crash due to failing assertion. +CREATE TABLE IF NOT EXISTS t2 LIKE t1; +--echo # Clean-up. +DROP TABLE t1, t2; +sync_slave_with_master; +connection master; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test new file mode 100644 index 00000000..8624d3c9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_or_replace_fail.test @@ -0,0 +1,56 @@ +# ==== Purpose ==== +# +# Test verifies that failed CREATE OR REPLACE TEMPORARY TABLE statement which +# dropped the table but failed at a later stage of creation of temporary table +# is written to binarylog in row based replication. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Have mixed based replication mode. +# 1 - Create a temporary table. It will be replicated as mixed replication +# mode is in use. +# 2 - Execute an unsafe statement which will switch current statement +# binlog format to 'ROW'. i.e If binlog_format=MIXED, there are open +# temporary tables, and an unsafe statement is executed, then subsequent +# statements are logged in row format. +# 3 - Execute a CREATE OR REPLACE TEMPORARY TABLE statement which tries to +# create partitions on temporary table. Since it is not supported it will +# fail. +# 4 - Check the binary log output to ensure that the failed statement is +# written to the binary log. +# 5 - Slave should be up and running and in sync with master. +# +# ==== References ==== +# +# MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log +# makes data on master and slave diverge +# + +--source include/have_partition.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +CREATE TEMPORARY TABLE t1 (a INT NOT NULL); + +# Execute an unsafe statement which switches replication mode internally from +# "STATEMENT" to "ROW". +--error ER_NO_SUCH_TABLE +LOAD DATA INFILE 'x' INTO TABLE x; + +--error ER_FEATURE_NOT_SUPPORTED_WITH_PARTITIONING +CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x); + +--echo "************** DROP TEMPORARY TABLE Should be present in Binary log **************" +--source include/show_binlog_events.inc + +CREATE TABLE t1 (b INT); +INSERT INTO t1 VALUES (NULL); +--sync_slave_with_master + +# Cleanup +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test new file mode 100644 index 00000000..3107fdfa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test @@ -0,0 +1,45 @@ +# BUG#45574: +# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists. +# +# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and +# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are +# binlogged even if either the DB, TABLE or EVENT does not exist. In +# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT +# exists. +# +# This problem caused some of the tests to fail randomly on PB or PB2. +# +# Test is implemented as follows: +# +# i) test each "CREATE TEMPORARY TABLE IF EXISTS" (DDL), found in MySQL +# 5.1 manual, on existent objects; +# ii) show binlog events; +# +# Note: +# rpl_create_if_not_exists.test tests other cases. +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# + +#CREATE TEMPORARY TABLE statements are not binlogged in row mode, +#So it must be test by itself. +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; +disable_warnings; + +DROP DATABASE IF EXISTS mysqltest; + +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +source include/show_binlog_events.inc; + +DROP TEMPORARY TABLE tmp; +DROP TEMPORARY TABLE tmp1; +DROP TEMPORARY TABLE tmp2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc b/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc new file mode 100644 index 00000000..b823ebf6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_xa_prepared.inc @@ -0,0 +1,9 @@ +# param $xid to name xa and take part in the connection name +# param $query to execute as the xa body +# param $db_ign the default database + +--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,) +--eval xa start '$xid' +--eval $query +--eval xa end '$xid' +--eval xa prepare '$xid'; diff --git a/mysql-test/suite/rpl/t/rpl_critical_errors.test b/mysql-test/suite/rpl/t/rpl_critical_errors.test new file mode 100644 index 00000000..bc0d7096 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_critical_errors.test @@ -0,0 +1,66 @@ +# Test for BUG#26551 +# + +# This test is unfortunately very fragile and very dependent on the +# load of the computer. The test is therefore disabled normally. It is +# entered here to demonstrate how to check that the bug is actually +# solved. + +--echo Turn on parsing to run this test + +disable_parsing; + +source include/master-slave.inc; + +connection master; +CREATE TABLE t1 (data LONGBLOB) ENGINE=MYISAM; +CREATE TABLE t2 (data LONGBLOB) ENGINE=MYISAM; + +INSERT INTO t1 (data) VALUES (repeat('a',1024*1024)); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +sync_slave_with_master; + +connection master; +send INSERT INTO t2 SELECT * FROM t1; + +connection master1; + +# This sleep is picked so that the query above has started to insert +# some rows into t2. If it hasn't the slave will not stop below. +let $wait_condition= SELECT COUNT(*) > 1000 FROM t1; +--source include/wait_condition.inc + +# SHOW PROCESSLIST; + +# Code for the 5.1 server to get the thread id of the thread executing +# the query above. +# +#SET @id = 0; +#SELECT id INTO @id +# FROM information_schema.processlist +# WHERE info LIKE 'INSERT INTO t2%'; + +# This is the connection that is executing the INSERT INTO t2... +KILL QUERY 2; + +connection slave; + +# Here the slave will only stop if the query above actually started +# inserting some rows into t2. Otherwise, it will hang forever. ... and there +# the error code should be 1317 (ER_QUERY_INTERRUPTED) +--let $slave_sql_errno= 1317 +--let $show_slave_sql_error= 1 +--source include/wait_for_slave_sql_error.inc + +# The following should be 0 +SELECT COUNT(*) FROM t2; + +--source include/rpl_end.inc +enable_parsing; diff --git a/mysql-test/suite/rpl/t/rpl_cross_version-master.opt b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt new file mode 100644 index 00000000..815a8f81 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_cross_version-master.opt @@ -0,0 +1 @@ +--replicate-same-server-id --relay-log=slave-relay-bin diff --git a/mysql-test/suite/rpl/t/rpl_cross_version.test b/mysql-test/suite/rpl/t/rpl_cross_version.test new file mode 100644 index 00000000..94c9f043 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_cross_version.test @@ -0,0 +1,48 @@ +# ==== Purpose ==== +# +# Verify cross-version replication from an old master to the up-to-date slave +# +# ==== Implementation ==== +# +# Feed to the slave server a binlog recorded on an old version master +# via setting up slave-to-slave replication. The latter is done by means of +# the opt file and include/setup_fake_relay_log.inc. +# The master's binlog is treated as a relay log that the SQL thread executes. +# + +--source include/master-slave.inc + +# +# Bug#31240 load data infile replication between (4.0 or 4.1) and 5.1 fails +# + +--echo ==== Initialize ==== +--connection slave + +--disable_query_log +# The binlog contains the function RAND which is unsafe. +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +--source include/stop_slave.inc +RESET SLAVE; + +# the relay log contains create t1, t3 tables and load data infile +--let $fake_relay_log = $MYSQL_TEST_DIR/suite/binlog/std_data/binlog_old_version_4_1.000001 +--source include/setup_fake_relay_log.inc + +--echo ==== Test ==== +start slave sql_thread; +--let $slave_param = Exec_Master_Log_Pos +# end_log_pos of the last event of the relay log +--let $slave_param_value = 149436 +--source include/wait_for_slave_param.inc +--echo ==== a prove that the fake has been processed successfully ==== +SELECT COUNT(*) - 17920 as zero FROM t3; + +--echo ==== Clean up ==== +--source include/stop_slave_sql.inc +--source include/cleanup_fake_relay_log.inc +drop table t1, t3; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ctype_latin1.test b/mysql-test/suite/rpl/t/rpl_ctype_latin1.test new file mode 100644 index 00000000..a8525421 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ctype_latin1.test @@ -0,0 +1,44 @@ +--source include/have_lowercase0.inc +--disable_warnings +--source include/master-slave.inc +--enable_warnings + +--echo # +--echo # Start of 10.2 tests +--echo # + + +--echo # +--echo # MDEV-14249 Wrong character set info of Query_log_event and the query in Query_log_event constructed by different charsets cause error when slave apply the event. +--echo # + +# +# The below tests uses a sequence of bytes 0xD191, +# which in a utf8 console looks like Ñ‘ (CYRILIC SMALL LETTER YO). +# Don't be mislead. This sequence is used in latin1 context and +# represents a sequence of two characters: +# U+00D1 CAPITAL LATIN LETTER N WITH TILDE (_latin1 0xD1) +# U+2018 LEFT SINGLE QUOTATION MARK (_latin1 0x91) +# + +SET NAMES latin1; +CREATE TABLE `tÑ‘` (`tÑ‘` INT); +CREATE VIEW `vÑ‘` AS SELECT 'vÑ‘'; +CREATE PROCEDURE `pÑ‘`() SELECT 'pÑ‘'; + +select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "t%"; +select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "v%"; + +--sync_slave_with_master +select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "t%"; +select hex(table_name) from information_schema.tables where table_schema="test" and table_name like "v%"; +--replace_column 5 ts 6 ts +SHOW PROCEDURE STATUS LIKE 'p%'; + +--connection master +DROP TABLE `tÑ‘`; +DROP VIEW `vÑ‘`; +DROP PROCEDURE `pÑ‘`; +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_current_user.cnf b/mysql-test/suite/rpl/t/rpl_current_user.cnf new file mode 100644 index 00000000..58b605ad --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.3] +log-slave-updates + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_current_user.test b/mysql-test/suite/rpl/t/rpl_current_user.test new file mode 100644 index 00000000..391606e3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.test @@ -0,0 +1,225 @@ +############################################################################## +# BUG#48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER, +# REVOKE, GRANT, ALTER EVENT +# +# Calling CURRENT_USER() results into inconsistency between slave and master, +# as the slave SQL thread has different user with common users. +# +# After the patch for bug#48321, session's user will be written into query log +# event if CURRENT_USER() is called in 'DROP/RENAME USER', 'REVOKE', 'GRANT', +# 'ALTER EVENT'. +# +############################################################################## + +source include/have_binlog_format_statement.inc; + +--let $rpl_topology= 1->2->3 +--source include/rpl_init.inc + +--let $rpl_connection_name= master +--let $rpl_server_number= 1 +--source include/rpl_connect.inc + +--let $rpl_connection_name= slave +--let $rpl_server_number= 2 +--source include/rpl_connect.inc + +--disable_query_log +--connection server_1 +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); +--connection server_2 +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); +--connection server_3 +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*"); +--enable_query_log + +--connection master + +CREATE TABLE t1(c1 char(100)); +CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; +CREATE PROCEDURE p1() SELECT 1; +--echo # bug48321_1-01234 has the max length(16) of user. +CREATE USER 'bug48321_1-01234'@'localhost'; +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; + +--echo +--echo # Test the max lengths of user and host names +--echo # the user name is too long +--error ER_WRONG_STRING_LENGTH +GRANT CREATE USER ON *.* TO '012345678901234567890123456789012345678901234567890123456789012345678901234567890'@'fakehost'; +--echo # the host name is too long +--error ER_WRONG_STRING_LENGTH +GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; + +--echo +--echo # User 'bug48321_1-01234' connects to master by conn1 +connect (conn1, 127.0.0.1, 'bug48321_1-01234'@'localhost',,); +connection conn1; +--echo # Verify 'REVOKE ALL' statement +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user; +source include/diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON TABLE ...' statement +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON PROCEDURE...' statement +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON *.* ...' statement +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON PROCEDURE...' statement +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_procs_priv, server_2:v_procs_priv, server_3:v_procs_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON *.* ...' statement +REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user; +source include/diff_tables.inc; + +--echo +--echo # Verify 'GRANT ...' statement in the procedure +CREATE PROCEDURE my_grant() + GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +call my_grant; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement in the procedure +CREATE PROCEDURE my_revoke() + REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +call my_revoke; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_tables_priv, server_2:v_tables_priv, server_3:v_tables_priv; +source include/diff_tables.inc; + +--echo +--echo # Verify 'RENAME USER ...' statement +RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user; +source include/diff_tables.inc; + +disconnect conn1; + +--echo +--echo # Verify 'DROP USER ...' statement +connection master; +GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; +connect (conn1, 127.0.0.1, 'bug48321_2'@'localhost',,); +connection conn1; +DROP USER CURRENT_USER(); +--source include/rpl_sync.inc +let $diff_tables= server_1:v_user, server_2:v_user, server_3:v_user; +source include/diff_tables.inc; + +--echo +--echo # Verify 'ALTER EVENT...' statement +connection master; +CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; + +--echo # Explicitly assign CURRENT_USER() to definer +ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_event, server_2:v_event, server_3:v_event; +source include/diff_tables.inc; + +--echo +--echo # Session user will be set as definer, if the statement does not assign +--echo # a definer +ALTER EVENT e1 ENABLE; +--source include/rpl_sync.inc +let $diff_tables= server_1:v_event, server_2:v_event, server_3:v_event; +source include/diff_tables.inc; + +--echo +--echo # Verify that this patch does not affect the calling of CURRENT_USER() +--echo # in the other statements +connection master; +INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); +SELECT * FROM t1; +sync_slave_with_master; +SELECT * FROM t1; +sync_slave_with_master server_3; +SELECT * FROM t1; + +connection master; +UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; +SELECT * FROM t1; +sync_slave_with_master; +SELECT * FROM t1; +sync_slave_with_master server_3; +SELECT * FROM t1; + +connection master; +DELETE FROM t1 WHERE c1=CURRENT_USER(); +SELECT * FROM t1; +sync_slave_with_master; +SELECT * FROM t1; +sync_slave_with_master server_3; +SELECT * FROM t1; + +connection master; +CREATE TABLE t2(c1 char(100)); + +DELIMITER |; +CREATE FUNCTION my_user() RETURNS VARCHAR(64) + SQL SECURITY INVOKER +BEGIN + INSERT INTO t2 VALUES(CURRENT_USER()); + RETURN CURRENT_USER(); +END | +DELIMITER ;| + +INSERT INTO t1 VALUES(my_user()); +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master server_3; +SELECT * FROM t1; +SELECT * FROM t2; + +--echo +--echo # END +connection master; +DROP TABLE t1, t2; +DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; +DROP PROCEDURE p1; +DROP PROCEDURE my_grant; +DROP PROCEDURE my_revoke; +DROP FUNCTION my_user; +DROP EVENT e1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ddl-slave.opt b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt new file mode 100644 index 00000000..21356507 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt @@ -0,0 +1 @@ +--loose-skip-innodb diff --git a/mysql-test/suite/rpl/t/rpl_ddl.test b/mysql-test/suite/rpl/t/rpl_ddl.test new file mode 100644 index 00000000..b11a6927 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ddl.test @@ -0,0 +1,32 @@ +######################## rpl_ddl.test ######################## +# # +# DDL statements (sometimes with implicit COMMIT) executed # +# by the master and it's propagation into the slave # +# # +############################################################## + +# +# NOTE, PLEASE BE CAREFUL, WHEN MODIFYING THE TESTS !! +# +# 1. !All! objects to be dropped, renamed, altered ... must be created +# in AUTOCOMMIT= 1 mode before AUTOCOMMIT is set to 0 and the test +# sequences start. +# +# 2. Never use a test object, which was direct or indirect affected by a +# preceding test sequence again. +# Except table d1.t1 where ONLY DML is allowed. +# +# If one preceding test sequence hits a (sometimes not good visible, +# because the sql error code of the statement might be 0) bug +# and these rules are ignored, a following test sequence might earn ugly +# effects like failing 'sync_slave_with_master', crashes of the slave or +# abort of the test case etc.. +# +--source include/have_innodb.inc +--source include/master-slave.inc +let $engine_type= InnoDB; +let $temp_engine_type= MEMORY; +let $show_binlog = 0; +let $manipulate = 0; +-- source include/rpl_ddl.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt new file mode 100644 index 00000000..f516b1b7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt @@ -0,0 +1 @@ +--loose-innodb-lock-wait-timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test new file mode 100644 index 00000000..e2311cb0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb.test @@ -0,0 +1,4 @@ +-- source include/have_innodb.inc +-- source include/long_test.inc +let $engine_type=innodb; +-- source include/rpl_deadlock.test diff --git a/mysql-test/suite/rpl/t/rpl_default.test b/mysql-test/suite/rpl/t/rpl_default.test new file mode 100644 index 00000000..9adf15c9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_default.test @@ -0,0 +1,29 @@ +# +# Test of replicating default values +# As the table is using non deterministic functions, replication must +# switch to binlog format. +# + +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/master-slave.inc + +connection master; + +create table t1 (a int DEFAULT (1+1), b bigint default uuid_short(), u blob default user()); +insert into t1 (a) values(1); + +let $b=query_get_value(select * from t1, b, 1); +let $u=query_get_value(select * from t1, u, 1); + +sync_slave_with_master; +connection slave; + +show create table t1; +--disable_query_log +eval select a,"$b"=b as uuid,"$u"=u as user from t1; +--enable_query_log +connection master; + +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations b/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations new file mode 100644 index 00000000..bac7cb33 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.combinations @@ -0,0 +1,4 @@ +[nonparallel] + +[parallel] +--slave-parallel-threads=10 diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave.test b/mysql-test/suite/rpl/t/rpl_delayed_slave.test new file mode 100644 index 00000000..7dd7b9cf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_delayed_slave.test @@ -0,0 +1,424 @@ +# ==== Purpose ==== +# +# Test the time-delayed replication feature, i.e., +# CHANGE MASTER TO MASTER_DELAY=X: +# +# - Verify that slave has executed the events after but not before the +# delay timeout. +# +# - Verify that delay is correct when slave is already lagging +# due to slow queries. +# +# - Verify that Seconds_Behind_Master is greater than or equal to the +# delay if the slave still has unprocessed events in the relay log +# and more time than the delay has elapsed since the last event was +# executed on the master. +# +# - Verify that STOP SLAVE works instantly even during a delay, and +# that it does not cause the waited-for event to be executed too +# early on slave. +# +# - Verify that changing back to no delay works. +# +# - Verify that RESET SLAVE sets the delay to 0. +# +# - Verify that setting a bad value for the delay gives an error. +# +# ==== Implementation ==== +# +# We run the slave with 10 seconds lag. +# +# In general, to test that a query has not been executed by the slave +# before this time, we wait until the slave IO thread has received the +# event, and then 5 seconds more, and check that the table has not +# been updated. To test that a query has been executed after this +# time, we wait 10 seconds more. +# +# To simulate that the slave lags due to slow queries, we invoke a +# stored function that executes SLEEP if @@gloval.server_id==2. This +# requires that we run with binlog_format=STATEMENT. +# +# ==== Related Bugs and Worklogs ==== +# +# WL#344: Time-delayed replication +# BUG#28760: Simulating a replication lag +# [duplicate] BUG#22072: configurable delayed replication +# [duplicate] BUG#21639: Add Replication Delay parameter +# BUG#56442: Slave executes delayed statements when STOP SLAVE is issued +# +# ==== Issues with this Test Case ==== +# +# The test is inherently timing-sensitive (i.e., contains races) and +# is likely to fail sporadically on a loaded host. +# +# The test takes a long time; it sleeps for around 20*10 seconds. + +--source include/big_test.inc +--source include/not_valgrind.inc +--source include/master-slave.inc +# Needed so that sleeps get executed in the slave SQL thread. +--source include/have_binlog_format_statement.inc + + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); +--connection slave +call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); +--connection master + + +# We assume that any simple operation takes zero time, with an error +# margin of $time1 seconds. Hence, if we run with a delay of $time2 +# seconds, we expect that: +# - If we execute a query on master and wait $time1 seconds, then the +# query has been copied to slave but not yet executed. +# - If we execute a query on master and wait $time3 seconds, then the +# query has been executed. +--let $time1= 10 +if (`SELECT '$max_query_execution_time' > 0`) { + --let $time1= $max_query_execution_time +} +--let $time2= `SELECT 2 * $time1` +--let $time3= `SELECT 3 * $time1` + + +--echo [on master] +CREATE TABLE t1 (a VARCHAR(100), b INT); +INSERT INTO t1 VALUES ("zero", 0); + + +--echo ==== Normal setup ==== + +--echo [on slave] +--sync_slave_with_master + +--source include/stop_slave.inc + +--echo # CHANGE MASTER TO MASTER_DELAY = 2*T +--disable_query_log +eval CHANGE MASTER TO MASTER_DELAY = $time2; +--enable_query_log + +--source include/start_slave.inc + +--let $assert_text= SHOW SLAVE STATUS should return the same delay that we set with CHANGE MASTER +--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = $time2 +--source include/rpl_assert.inc + +--echo [on master] +--connection master +INSERT INTO t1 VALUES ('normal setup', 1); + +--let $query_number= 1 +--source include/delayed_slave_wait_on_query.inc + + +--echo ==== Slave lags "naturally" after master ==== + +--echo [on master] +--connection master + +--disable_query_log +--echo # CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * T); ELSE RETURN 0; END IF; END +--eval CREATE FUNCTION delay_on_slave(time_units INT) RETURNS INT BEGIN IF @@GLOBAL.server_id = 2 THEN RETURN SLEEP(time_units * $time1); ELSE RETURN 0; END IF; END +--enable_query_log + +INSERT INTO t1 SELECT delay_on_slave(3), 2; + +--save_master_pos +INSERT INTO t1 VALUES ('slave is already lagging: this statement should execute immediately', 3); +INSERT INTO t1 SELECT delay_on_slave(2), 4; + +--echo [on slave] +--source include/sync_slave_io_with_master.inc +--echo # sleep 1*T +--sleep $time1 + +--let $assert_text= No query executed +--let $assert_cond= MAX(b) = 1 FROM t1 +--source include/rpl_assert.inc + +--let $assert_text= Status should be 'Waiting until MASTER_DELAY...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%" +--source include/rpl_assert.inc + +--echo # wait for first query to execute +--sync_with_master + +--echo # sleep 1*T +--sleep $time1 + +--let $assert_text= Second query executed +--let $assert_cond= MAX(b) = 3 FROM t1 +--source include/rpl_assert.inc + +let $parallel= `SELECT @@GLOBAL.slave_parallel_threads`; +if (!$parallel) +{ + let $assert_text= Status should be executing third query (i.e., 'User sleep'); + let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = "User sleep"; + source include/rpl_assert.inc; +} + +--echo # sleep 2*T +--sleep $time2 + +--let $assert_text= Third query executed +--let $assert_cond= MAX(b) = 4 FROM t1 +--source include/rpl_assert.inc + +--let $assert_text= Status should be 'Has read all relay log...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%" +--source include/rpl_assert.inc + + +--echo ==== Seconds_Behind_Master ==== + +--echo # Bring slave to sync. +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_DELAY = 0; +--source include/start_slave.inc + +--connection master +INSERT INTO t1 VALUES ('Syncing slave', 5); +--sync_slave_with_master + +--source include/stop_slave.inc +--echo # CHANGE MASTER TO MASTER_DELAY = 2*T +--disable_query_log +eval CHANGE MASTER TO MASTER_DELAY = $time2; +--enable_query_log +--source include/start_slave.inc + +--connection master +INSERT INTO t1 VALUES (delay_on_slave(1), 6); +--save_master_pos +--connection slave + +--echo # sleep 1*T +--sleep $time1 + +--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= 0 AND <1> < $time2 +--let $assert_text= Seconds_Behind_Master should be between 0 and the 2*T +--source include/rpl_assert.inc + +--echo # sleep 1*T +--sleep $time1 + +--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] >= $time2 +--let $assert_text= Seconds_Behind_Master should be at least 2*T +--source include/rpl_assert.inc + +--sync_with_master + + +--echo ==== STOP SLAVE / START SLAVE + DML ==== + +# Set up a longer delay. +--source include/stop_slave.inc + +--echo # CHANGE MASTER TO MASTER_DELAY = 3*T +--disable_query_log +eval CHANGE MASTER TO MASTER_DELAY = $time3; +--enable_query_log + +--source include/start_slave.inc + +--echo [on master] +--connection master +INSERT INTO t1 VALUES ('stop slave and start slave: DML', 7); + +--echo [on slave] +--connection slave +--echo # sleep 1*T +--sleep $time1 +--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()` +--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--source include/stop_slave.inc + +--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish +--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1 +--source include/rpl_assert.inc + +--let $assert_text= SQL thread position should not increase after STOP SLAVE +--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop +--source include/rpl_assert.inc + +--let $assert_text= Query should not be executed after STOP SLAVE +--let $assert_cond= MAX(b) = 6 FROM t1 +--source include/rpl_assert.inc + +--let $assert_text= Status should be '' after STOP SLAVE +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = "" +--source include/rpl_assert.inc + +--source include/start_slave.inc + +--let $assert_text= START SLAVE should finish quickly +--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1 +--source include/rpl_assert.inc + +--let $query_number= 7 +--source include/delayed_slave_wait_on_query.inc + + +--echo ==== STOP SLAVE / START SLAVE + DDL ==== + +--echo This verifies BUG#56442 + +--echo [on master] +--connection master +CREATE TABLE t_check_dml_not_executed_prematurely (a INT); +--source include/save_master_pos.inc + +--echo [on slave] +--connection slave +--echo # sleep 1*T +--sleep $time1 + +--let $timestamp_before_stop= `SELECT UNIX_TIMESTAMP()` +--let $relay_log_pos_before_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--source include/stop_slave.inc + +--let $assert_text= STOP SLAVE should finish quickly, not wait for the ongoing sleep to finish +--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1 +--source include/rpl_assert.inc + +--let $assert_text= SQL thread position should not increase after STOP SLAVE +--let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] = $relay_log_pos_before_stop +--source include/rpl_assert.inc + +--let $assert_text= Query should not be executed after STOP SLAVE +--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely" +--source include/rpl_assert.inc + +--let $assert_text= Status should be '' after STOP SLAVE +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" = "" +--source include/rpl_assert.inc + +--source include/start_slave.inc + +--let $assert_text= START SLAVE should finish quickly +--let $assert_cond= UNIX_TIMESTAMP() - $timestamp_before_stop < $time1 +--source include/rpl_assert.inc + +--echo # sleep 1*T +--sleep $time1 + +--let $assert_text= DDL Query should not be executed after START SLAVE +--let $assert_cond= COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely" +--source include/rpl_assert.inc + +--let $assert_text= Status should be 'Waiting until MASTER_DELAY...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Waiting until MASTER_DELAY%" +--source include/rpl_assert.inc + +--echo # sleep 1*T +--sleep $time1 + +--echo # sync with master (with timeout 1*T) +--source include/sync_with_master.inc + +--let $assert_text= DDL Query should be executed +--let $assert_cond= COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = "t_check_dml_not_executed_prematurely" +--source include/rpl_assert.inc + +--let $assert_text= Status should be 'Has read all relay log...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" LIKE "Slave has read all relay log%" +--source include/rpl_assert.inc + +--source include/check_slave_is_running.inc + + +--echo ==== Change back to no delay ==== + +--echo [on slave] +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_DELAY = 0; + +--let $assert_text= Delay should be 0 when we set it to 0 +--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0 +--source include/rpl_assert.inc + +--source include/start_slave.inc + +--echo [on master] +--connection master +INSERT INTO t1 VALUES ('change back to no delay', 8); + +--echo [on slave] +--source include/sync_slave_io_with_master.inc +--echo # sleep 1*T +--sleep $time1 + +--let $assert_text= Query should be executed +--let $assert_cond= MAX(b) = 8 FROM t1 +--source include/rpl_assert.inc + +--let $assert_text= Status should be 'Slave has read all relay log...' +--let $assert_cond= "[SHOW SLAVE STATUS, Slave_SQL_Running_State, 1]" Like "Slave has read all relay log%" +--source include/rpl_assert.inc + + +--echo ==== Reset delay with RESET SLAVE ==== + +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_DELAY = 71; +--source include/start_slave.inc + +--let $assert_text= Delay should be 71 when we set it to 71 +--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 71 +--source include/rpl_assert.inc + +--source include/stop_slave.inc +RESET SLAVE; +--echo [on master] +--connection master +RESET MASTER; +--echo [on slave] +--connection slave +--source include/start_slave.inc + +--let $assert_text= Delay should be 0 after RESET SLAVE +--let $assert_cond= [SHOW SLAVE STATUS, SQL_Delay, 1] = 0 +--source include/rpl_assert.inc + + +--echo ==== Set an invalid value for the delay ==== + +--source include/stop_slave.inc + +--echo # Expect error for setting negative delay +--error ER_PARSE_ERROR +CHANGE MASTER TO MASTER_DELAY = -1; + +--echo # Expect that it's ok to set delay of 2^31-1 +CHANGE MASTER TO MASTER_DELAY = 2147483647; +--echo # Expect error for setting delay between 2^31 and 2^32-1 +--error ER_MASTER_DELAY_VALUE_OUT_OF_RANGE +CHANGE MASTER TO MASTER_DELAY = 2147483648; + +--echo # Expect error for setting delay to nonsense +--error ER_PARSE_ERROR +CHANGE MASTER TO MASTER_DELAY = blah; + +# todo: CHANGE MASTER TO MASTER_DELAY = 999999999999999999999999999 +# should give error + +CHANGE MASTER TO MASTER_DELAY = 0; +--source include/start_slave.inc + + +--echo ==== Clean up ==== + +--echo [on master] +--connection master +DROP TABLE t1, t_check_dml_not_executed_prematurely; +DROP FUNCTION delay_on_slave; + +--echo [on slave] +--sync_slave_with_master +SELECT @@GLOBAL.slave_parallel_mode; +SELECT @@GLOBAL.slave_parallel_threads; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_delayed_slave2.test b/mysql-test/suite/rpl/t/rpl_delayed_slave2.test new file mode 100644 index 00000000..68e8f8e1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_delayed_slave2.test @@ -0,0 +1,65 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +# This test file tests delayed slave for parallel replication (and GTID). +# Uses a different approach from rpl_delayed_slave.test, setting @@timestamp +# to simulate events logged on master at different times. + +--connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100)); +INSERT INTO t1 VALUES (1, "a"); +--save_master_pos + +--connection slave +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=optimistic; +SET @old_threads= @@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=10; + +--connection master +INSERT INTO t1 VALUES (2, "b"); +INSERT INTO t1 VALUES (3, "b"); +INSERT INTO t1 VALUES (4, "b"); +--let $gtid1= `SELECT @@gtid_binlog_pos` +# Simulate an event a days in the future, for delayed slave to wait on. +SET timestamp= @@timestamp + 24*60*60; +INSERT INTO t1 VALUES (5, "c"); +INSERT INTO t1 VALUES (6, "c"); +SET timestamp= 0; +--let $gtid2= `SELECT @@gtid_binlog_pos` +--source include/save_master_gtid.inc + +--connection slave +CHANGE MASTER TO master_delay=1; +--source include/start_slave.inc +--replace_result $gtid1 GTID1 +# First sync halfways, to avoid timing-dependent test failures. +eval SELECT MASTER_GTID_WAIT('$gtid1'); +# Try to sync up, should timeout because slave is waiting for one day. +--replace_result $gtid2 GTID2 +eval SELECT MASTER_GTID_WAIT('$gtid2', 2); + +# Check that we can stop slave while delaying. +--source include/stop_slave.inc +SELECT * FROM t1 ORDER BY a; +CHANGE MASTER TO master_delay=0; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=no, master_delay=0; +SET GLOBAL slave_parallel_mode=@old_mode; +SET GLOBAL slave_parallel_threads=@old_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_delete_no_where.test b/mysql-test/suite/rpl/t/rpl_delete_no_where.test new file mode 100644 index 00000000..c07649cb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_delete_no_where.test @@ -0,0 +1,4 @@ +-- source include/master-slave.inc +let $engine_type=myisam; +-- source include/rpl_delete_no_where.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test new file mode 100644 index 00000000..1350585f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -0,0 +1,350 @@ +# Works in statement-based and row-based binlogging. +# Test that GRANT and other user management commands are replicated to the slave + +-- source include/master-slave.inc + +# test replication of GRANT +connection master; +create user rpl_do_grant@localhost; +grant select on *.* to rpl_do_grant@localhost; +grant drop on test.* to rpl_do_grant@localhost; +sync_slave_with_master; +show grants for rpl_do_grant@localhost; + +# test replication of SET PASSWORD +connection master; +set password for rpl_do_grant@localhost=password("does it work?"); +sync_slave_with_master; +select authentication_string<>'' from mysql.user where user='rpl_do_grant'; + +# +# Bug#24158 SET PASSWORD in binary log fails under ANSI_QUOTES +# +connection master; +update mysql.global_priv set priv=json_remove(priv, '$.authentication_string') where user='rpl_do_grant'; +flush privileges; +select authentication_string<>'' from mysql.user where user='rpl_do_grant'; +set sql_mode='ANSI_QUOTES'; +set password for rpl_do_grant@localhost=password('does it work?'); +set sql_mode=''; +sync_slave_with_master; +select authentication_string<>'' from mysql.user where user='rpl_do_grant'; + +# clear what we have done, to not influence other tests. +connection master; +drop user rpl_do_grant@localhost; +sync_slave_with_master; + +# End of 4.1 tests + +connection master; +--error 1141 +show grants for rpl_do_grant@localhost; +connection slave; +--error 1141 +show grants for rpl_do_grant@localhost; + +connection master; +create user rpl_do_grant@localhost; +show grants for rpl_do_grant@localhost; +--error 1141 +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +show grants for rpl_do_grant@localhost; +--error 1141 +show grants for rpl_do_grant2@localhost; + +connection master; +rename user rpl_do_grant@localhost to rpl_do_grant2@localhost; +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +show grants for rpl_do_grant2@localhost; + +connection master; +grant DELETE,INSERT on mysqltest1.* to rpl_do_grant2@localhost; +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +show grants for rpl_do_grant2@localhost; + +connection master; +revoke DELETE on mysqltest1.* from rpl_do_grant2@localhost; +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +show grants for rpl_do_grant2@localhost; + +connection master; +revoke all privileges, grant option from rpl_do_grant2@localhost; +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +show grants for rpl_do_grant2@localhost; + +connection master; +drop user rpl_do_grant2@localhost; +--error 1141 +show grants for rpl_do_grant2@localhost; +sync_slave_with_master; +--error 1141 +show grants for rpl_do_grant2@localhost; + +##################################################### +# Purpose +# Test whether mysql.procs_priv get replicated +# Related bugs: +# BUG42217 mysql.procs_priv does not get replicated +##################################################### +connection master; +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' error.* 1396"); +sync_slave_with_master; +connection master; + +--disable_warnings +DROP DATABASE IF EXISTS bug42217_db; +--enable_warnings +CREATE DATABASE bug42217_db; + +GRANT CREATE ROUTINE ON bug42217_db.* TO 'create_rout_db'@'localhost' + IDENTIFIED BY 'create_rout_db' WITH GRANT OPTION; + +-- sync_slave_with_master +-- connection master + +connect (create_rout_db_master, localhost, create_rout_db, create_rout_db, bug42217_db,$MASTER_MYPORT,); +connect (create_rout_db_slave, localhost, create_rout_db, create_rout_db, bug42217_db, $SLAVE_MYPORT,); + +connection create_rout_db_master; + + +USE bug42217_db; + +DELIMITER //; +CREATE FUNCTION upgrade_del_func() RETURNS CHAR(30) +BEGIN + RETURN "INSIDE upgrade_del_func()"; +END// + +DELIMITER ;// + +connection master; + +USE bug42217_db; +--replace_column 8 # +SELECT * FROM mysql.procs_priv; +SELECT upgrade_del_func(); + +sync_slave_with_master; +--replace_column 8 # +SELECT * FROM mysql.procs_priv; +SHOW GRANTS FOR 'create_rout_db'@'localhost'; + +USE bug42217_db; +SHOW CREATE FUNCTION upgrade_del_func; +SELECT upgrade_del_func(); + +--echo "Check whether the definer user will be able to execute the replicated routine on slave" +connection create_rout_db_slave; +USE bug42217_db; +SHOW CREATE FUNCTION upgrade_del_func; +SELECT upgrade_del_func(); + +connection slave; +DELETE FROM mysql.procs_priv; +FLUSH PRIVILEGES; +USE bug42217_db; +--echo "Can't execute the replicated routine on slave like before after procs privilege is deleted " +--error 1370 +SELECT upgrade_del_func(); + +--echo "Test the user who creates a function on master doesn't exist on slave." +--echo "Hence SQL thread ACL_GLOBAL privilege jumps in and no mysql.procs_priv is inserted" +DROP USER 'create_rout_db'@'localhost'; + +connection create_rout_db_master; +DELIMITER //; +CREATE FUNCTION upgrade_alter_func() RETURNS CHAR(30) +BEGIN + RETURN "INSIDE upgrade_alter_func()"; +END// +DELIMITER ;// + +connection master; +SELECT upgrade_alter_func(); + +sync_slave_with_master; +SHOW CREATE FUNCTION upgrade_alter_func; +--echo "Should no privilege record for upgrade_alter_func in mysql.procs_priv" +--replace_column 8 # +SELECT * FROM mysql.procs_priv; +--error 1449 +SELECT upgrade_alter_func(); + +###### CLEAN UP SECTION ############## +disconnect create_rout_db_master; +disconnect create_rout_db_slave; +connection master; +USE bug42217_db; +DROP FUNCTION upgrade_del_func; +DROP FUNCTION upgrade_alter_func; +DROP DATABASE bug42217_db; +-- sync_slave_with_master +-- connection master + +# user was already dropped in the slave before +# so we should not replicate this statement. +SET SQL_LOG_BIN= 0; +DROP USER 'create_rout_db'@'localhost'; +SET SQL_LOG_BIN= 1; + +# finish entire clean up (remove binlogs) +# so that we leave a pristine environment for the +# following tests +--let $rpl_only_running_threads= 1 +-- source include/rpl_reset.inc +USE test; + +# BUG#49119: Master crashes when executing 'REVOKE ... ON +# {PROCEDURE|FUNCTION} FROM ...' +# +# The tests are divided into two test cases: +# +# i) a test case that mimics the one in the bug report. +# +# - We show that, despite the fact, that a revoke command fails +# when binlogging is active, the master will not hit an +# assertion. +# +# ii) a test case that partially succeeds on the master will also +# partially succeed on the slave. +# +# - The revoke statement that partially succeeds tries to revoke +# an EXECUTE grant for two users, and only one of the user has +# the specific grant. This will cause mysql to drop one of the +# grants and report error for the statement. The slave should +# also drop the grants that the master succeed and the SQL +# thread should not stop on statement failure. + +-- echo ######## BUG#49119 ####### +-- echo ### i) test case from the 'how to repeat section' + +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost'; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; + +-- sync_slave_with_master + +-- echo ### ii) Test case in which REVOKE partially succeeds + +-- connection master +-- source include/rpl_reset.inc +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| + +CREATE USER 'user49119'@'localhost'; +GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master + +-- echo ## This statement will make the revoke fail because root has no +-- echo ## execute grant. However, it will still revoke the grant for +-- echo ## user49119. +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +-- echo ### after revoke statement failure +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################# +-- echo ### Showing grants for both users: root and user49119 (slave) +-- echo ### after revoke statement failure (should match +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; +DROP USER 'user49119'@'localhost'; + +-- sync_slave_with_master + +# +# Bug #51987 revoke privileges logs wrong error code +# + +-- source include/rpl_reset.inc +-- connection master + +grant all on *.* to foo@"1.2.3.4"; +-- error ER_REVOKE_GRANTS +revoke all privileges, grant option from "foo"; + +## assertion: revoke is logged +-- source include/show_binlog_events.inc + +-- sync_slave_with_master + +## assertion: slave replicates revoke and does not fail because master +## logged revoke with correct expected error code +--source include/check_slave_no_error.inc + +-- connection master +DROP USER foo@"1.2.3.4"; +-- sync_slave_with_master + +--echo +--echo # Bug#27606 GRANT statement should be replicated with DEFINER information +--source include/rpl_reset.inc +--connection master +GRANT SELECT, INSERT ON mysql.user TO user_bug27606@localhost; + +SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606'; +sync_slave_with_master; +SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606'; + +--connection master +REVOKE SELECT ON mysql.user FROM user_bug27606@localhost; +SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606'; +sync_slave_with_master; +SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606'; + +--connection master +DROP USER user_bug27606@localhost; +select priv into @root_priv from mysql.global_priv where user='root' and host='127.0.0.1'; +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter.test new file mode 100644 index 00000000..2b8ac17c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter.test @@ -0,0 +1,400 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +# +# Test for DO_DOMAIN_IDS=(M1, M2, ..) and IGNORE_DOMAIN_IDS=(N1, N2, ..) +# + +connection slave; +call mtr.add_suppression("Both DO_DOMAIN_IDS & IGNORE_DOMAIN_IDS lists can't be non-empty at the same time"); +call mtr.add_suppression("DO_DOMAIN_IDS or IGNORE_DOMAIN_IDS lists can't be non-empty in non-GTID mode.*"); + +connection master; +SET @@session.gtid_domain_id= 1; +SELECT @@session.gtid_domain_id; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +##### Case 0 : When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are empty. +SELECT * FROM t1; + +##### Case 1: When DO_DOMAIN_IDS is non-empty. +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Replicate events belonging to "domain_id 1". +CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +# Lets change the session domain_id to 2(not in DO_DOMAIN_IDS). +SET @@session.gtid_domain_id= 2; +# Should get filtered out on slave. +INSERT INTO t1 VALUES(2); +# Change it back to 1 (in DO_DOMAIN_IDS). +SET @@session.gtid_domain_id= 1; +# Should get applied on slave. +INSERT INTO t1 VALUES(3); + +SELECT * FROM t1; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1; + +##### Case 2: When IGNORE_DOMAIN_IDS is non-empty. +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Ignore events belonging to "domain_id 1". +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +# @@session.gtid_domain_id = 1 (in IGNORE_DOMAIN_IDS) +SELECT @@session.gtid_domain_id; +# Should get filtered out on slave. +INSERT INTO t1 VALUES(4); +# Change it to 2 (not in IGNORE_DOMAIN_IDS). +SET @@session.gtid_domain_id= 2; +# Should get applied on slave. +INSERT INTO t1 VALUES(5); + +SELECT * FROM t1; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1; + +##### Case 3: When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are non-empty + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +--error ER_MASTER_INFO +CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(2), MASTER_USE_GTID=slave_pos; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +##### Case 4: Multiple domain ids. + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Replicate events belonging to "domain_id 1". +CHANGE MASTER TO DO_DOMAIN_IDS=(4,4,5,1,7,7,7,1,1,2,6,8,1,4,5,5,9,3), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +# @@session.gtid_domain_id = 1 (in DO_DOMAIN_IDS) +SELECT @@session.gtid_domain_id; +# Should get applied on slave. +INSERT INTO t1 VALUES(8); +# Change it to 7 (in DO_DOMAIN_IDS). +SET @@session.gtid_domain_id= 7; +# Should get applied on slave. +INSERT INTO t1 VALUES(9); +# Change it to 10 (no in DO_DOMAIN_IDS). +SET @@session.gtid_domain_id= 10; +# Following should get filtered out on slave. +INSERT INTO t1 VALUES(10); +INSERT INTO t1 VALUES(11); +START TRANSACTION; +INSERT INTO t1 VALUES(12); +INSERT INTO t1 VALUES(13); +COMMIT; +INSERT INTO t1 VALUES(14); +INSERT INTO t1 VALUES(15); +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1; + +##### Case 5: Seconds_Behind_Master +connection slave; +--echo # Seconds_Behind_Master should be zero here because the slave is fully caught up and idle. +--let $status_items= Seconds_Behind_Master +--source include/show_slave_status.inc + +##### Case 6: Stop slave before a transaction (involving MyISAM and InnoDB +# table) being filtered commits. + +connection slave; +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# IGNORE_DOMAIN_IDS=(1) +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +# following statements should not get filtered. +SET @@session.gtid_domain_id=2; +CREATE TABLE t2(i int) ENGINE=MYISAM; +CREATE TABLE t3(i int) ENGINE=INNODB; + +SET @@session.gtid_domain_id=1; +BEGIN; +INSERT INTO t2 VALUES(1); +INSERT INTO t3 VALUES(1); + +# Now switch to slave to stop replication. +connection slave; +--source include/stop_slave.inc +--source include/wait_for_slave_to_stop.inc + +# Back to master to finish the transaction. +connection master; +INSERT INTO t2 VALUES(2); +INSERT INTO t3 VALUES(2); +COMMIT; +--source include/save_master_gtid.inc + +# On slave to start replication. +connection slave; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t2; +SELECT * FROM t3; + +##### Case 7: Stop slave before a transaction (involving MyISAM and InnoDB +# table) being filtered commits and start it back with filtering +# disabled. + +connection master; +SET @@session.gtid_domain_id=1; +BEGIN; +INSERT INTO t2 VALUES(3); +INSERT INTO t3 VALUES(3); +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Clear IGNORE_DOMAIN_IDS +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +INSERT INTO t2 VALUES(4); +INSERT INTO t3 VALUES(4); +COMMIT; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t2; +SELECT * FROM t3; + +##### Case 8: Stop slave into the middle of a transaction and start it back +# with filtering enabled. + +connection master; +SET @@session.gtid_domain_id=1; +BEGIN; +INSERT INTO t2 VALUES(5); +INSERT INTO t3 VALUES(5); +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# IGNORE_DOMAIN_IDS(1) +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +INSERT INTO t2 VALUES(6); +INSERT INTO t3 VALUES(6); +COMMIT; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t2; +SELECT * FROM t3; + +##### Case 9: Initially filter out events belonging to domain_id=2 and then +# remove the rule to check if event are not being filtered out. + +connection slave; +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# IGNORE_DOMAIN_IDS(2) +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(2), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +SET @@session.gtid_domain_id=2; +BEGIN; +INSERT INTO t2 VALUES(7); +INSERT INTO t3 VALUES(7); +COMMIT; +--source include/save_master_gtid.inc + +# Clear the filter +connection slave; +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# IGNORE_DOMAIN_IDS() +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +SET @@session.gtid_domain_id=2; +BEGIN; +INSERT INTO t2 VALUES(8); +INSERT INTO t3 VALUES(8); +COMMIT; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +SELECT * FROM t2; +SELECT * FROM t3; + +##### Case 10: Test CHANGE MASTER with various "incompatible" combinations. +connection slave; +--source include/stop_slave.inc + +# 10a: Both DO_DOMAIN_IDS & IGNORE_DOMAIN_IDS can't be non-empty at the same +# time. + +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +--error ER_MASTER_INFO +CHANGE MASTER TO DO_DOMAIN_IDS=(1), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS; +CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS; +--error ER_MASTER_INFO +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS; +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS; +--error ER_MASTER_INFO +CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=SLAVE_POS; + +# 10b: Neither DO_DOMAIN_IDS nor IGNORE_DOMAIN_IDS can be set when +# MASTER_USE_GTID=NO + +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# MASTER_USE_GTID can't be set to NO when either of IGNORE_DOMAIN_IDS or +# DO_DOMAIN_IDS is non-empty. +--error ER_MASTER_INFO +CHANGE MASTER TO MASTER_USE_GTID=NO; +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=NO; +--error ER_MASTER_INFO +CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=NO; +--error ER_MASTER_INFO +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=NO; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), DO_DOMAIN_IDS=(), MASTER_USE_GTID=SLAVE_POS; +--source include/start_slave.inc + +# Cleanup +connection master; +SET @@session.gtid_domain_id=2; +DROP TABLE t1, t2, t3; +--source include/save_master_gtid.inc + +connection slave; +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(); +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test new file mode 100644 index 00000000..a949da0c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test @@ -0,0 +1,384 @@ +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +connection master; +SET @@session.gtid_domain_id= 1; +SELECT @@session.gtid_domain_id; +CREATE TABLE t1(i INT) ENGINE=INNODB; +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; +sync_slave_with_master; + +connection slave; + +call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*"); + +--echo # Case 0 : Start slave with IGNORE_DOMAIN_IDS=(), then restart +--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit"). + +SELECT * FROM t1; + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@global.debug_dbug="d,kill_slave_io_before_commit"; + +connection master; + +START TRANSACTION; +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); +COMMIT; +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; +SET @@global.debug_dbug=@saved_dbug; + +START SLAVE io_thread; +--source include/wait_for_slave_io_to_start.inc +sync_with_master; +SELECT * FROM t1; + +--echo # Case 1 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart +--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit"). + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @@global.debug_dbug="d,kill_slave_io_before_commit"; + +connection master; + +START TRANSACTION; +INSERT INTO t1 VALUES(4); +INSERT INTO t1 VALUES(5); +COMMIT; + +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; +SET @@global.debug_dbug=@saved_dbug; + +START SLAVE io_thread; +--source include/wait_for_slave_io_to_start.inc +sync_with_master; +SELECT * FROM t1; + +--echo # Case 2 : Start slave with IGNORE_DOMAIN_IDS=(), then restart +--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit"). + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @@global.debug_dbug="d,kill_slave_io_before_commit"; + +connection master; + +START TRANSACTION; +INSERT INTO t1 VALUES(6); +INSERT INTO t1 VALUES(7); +COMMIT; # IO thread gets killed here. + +START TRANSACTION; +INSERT INTO t1 VALUES(8); +INSERT INTO t1 VALUES(9); +COMMIT; + +SET @@session.gtid_domain_id= 2; + +START TRANSACTION; +INSERT INTO t1 VALUES(10); +INSERT INTO t1 VALUES(11); +COMMIT; + +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; + +SET @@global.debug_dbug=@saved_dbug; + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SELECT * FROM t1; + +--echo # Case 3 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart +--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_before_commit"). + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @@global.debug_dbug="d,kill_slave_io_before_commit"; + +connection master; + +SET @@session.gtid_domain_id= 1; + +START TRANSACTION; +INSERT INTO t1 VALUES(12); +INSERT INTO t1 VALUES(13); +COMMIT; # IO thread gets killed here. + +START TRANSACTION; +INSERT INTO t1 VALUES(14); +INSERT INTO t1 VALUES(15); +COMMIT; + +SET @@session.gtid_domain_id= 2; +START TRANSACTION; +INSERT INTO t1 VALUES(16); +INSERT INTO t1 VALUES(17); +COMMIT; + +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; + +SET @@global.debug_dbug=@saved_dbug; + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SELECT * FROM t1; + +--echo # Case 4 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart +--echo # replication with IGNORE_DOMAIN_IDS=() after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_after_2_events"). + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @@global.debug_dbug="d,kill_slave_io_after_2_events"; + +connection master; + +SET @@session.gtid_domain_id= 1; + +START TRANSACTION; +INSERT INTO t1 VALUES(18); +INSERT INTO t1 VALUES(19); # IO thread gets killed here. +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES(20); +INSERT INTO t1 VALUES(21); +COMMIT; + +SET @@session.gtid_domain_id= 2; +START TRANSACTION; +INSERT INTO t1 VALUES(22); +INSERT INTO t1 VALUES(23); +COMMIT; + +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; + +SET @@global.debug_dbug=@saved_dbug; + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SELECT * FROM t1; + +--echo # Case 5 : Start slave with IGNORE_DOMAIN_IDS=(), then restart +--echo # replication with IGNORE_DOMAIN_IDS=(1) after IO thread is +--echo # killed due to DBUG_EXECUTE_IF("+d,kill_slave_io_after_2_events"). + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SET @@global.debug_dbug="d,kill_slave_io_after_2_events"; + +connection master; + +SET @@session.gtid_domain_id= 1; + +START TRANSACTION; +INSERT INTO t1 VALUES(24); +INSERT INTO t1 VALUES(25); # IO thread gets killed here. +COMMIT; + +START TRANSACTION; +INSERT INTO t1 VALUES(26); +INSERT INTO t1 VALUES(27); +COMMIT; + +SET @@session.gtid_domain_id= 2; +START TRANSACTION; +INSERT INTO t1 VALUES(28); +INSERT INTO t1 VALUES(29); +COMMIT; + +save_master_pos; +SELECT * FROM t1; + +connection slave; +--let $slave_io_errno= 1595 +--source include/wait_for_slave_io_error.inc +SELECT * FROM t1; + +SET @@global.debug_dbug=@saved_dbug; + +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SELECT * FROM t1; + +# Cleanup +connection master; +DROP TABLE t1; +sync_slave_with_master; + +connection slave; +--source include/stop_slave.inc +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(); +--source include/start_slave.inc +SET @@GLOBAL.debug_dbug = @saved_dbug; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test new file mode 100644 index 00000000..6dafab19 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -0,0 +1,87 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc +--source include/master-slave.inc + +connection master; + +call mtr.add_suppression("mysqld: Table '.*gtid_slave_pos' is marked as crashed and should be repaired"); +call mtr.add_suppression("Checking table: './mysql/gtid_slave_pos'"); +call mtr.add_suppression("mysql.gtid_slave_pos: 1 client is using or hasn't closed the table properly"); +SET @@session.gtid_domain_id= 0; + +create table ti (a int auto_increment primary key) engine=innodb; +create table tm (a int auto_increment primary key) engine=myisam; + +insert into ti set a=null; +insert into tm set a=null; + +save_master_pos; + +connection slave; +sync_with_master; +--source include/stop_slave.inc + +select * from ti; +select * from tm; + +connection master; +SET @@session.gtid_domain_id= 1; + +begin; +insert into ti set a=null; +insert into tm set a=null; +commit; + +SET @@session.gtid_domain_id= 0; +insert into ti set a=null; +insert into tm set a=null; + +set @@global.debug_dbug="+d,crash_before_send_xid"; +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +connection slave; +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# IGNORE_DOMAIN_IDS=(1) +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +--source include/wait_until_disconnected.inc +--enable_reconnect +--let $rpl_server_number=1 +--source include/rpl_start_server.inc +#--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/wait_until_connected_again.inc +--echo # Master has restarted successfully +save_master_pos; + +--connection slave +--source include/stop_slave.inc +--source include/start_slave.inc +sync_with_master; +select * from ti; +select * from tm; + +# Cleanup +--connection master +drop table ti; +drop table tm; +sync_slave_with_master; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=NO; +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test new file mode 100644 index 00000000..902f6b52 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_parallel.test @@ -0,0 +1,196 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; + +##### Case 0 : When both DO_DOMAIN_IDS and IGNORE_DOMAIN_IDS are empty. + +--connection server_2 +CHANGE MASTER TO master_use_gtid=slave_pos, DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(); +--source include/start_slave.inc + +--connection server_1 +SELECT @@session.gtid_domain_id; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master + +# Block the table t1 to simulate a replicated query taking a long time. +--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,) +LOCK TABLE t1 WRITE; + +--connection server_1 +SET @@session.gtid_domain_id=1; +# This query will be blocked on the slave until UNLOCK TABLES. +INSERT INTO t1 VALUES (2); +SET @@session.gtid_domain_id=0; +# These t2 queries can be replicated in parallel with the prior t1 query, as +# they are in a separate replication domain. +INSERT INTO t2 VALUES (2); +INSERT INTO t2 VALUES (3); +BEGIN; +INSERT INTO t2 VALUES (4); +INSERT INTO t2 VALUES (5); +COMMIT; +INSERT INTO t2 VALUES (6); + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 6 FROM t2 +--source include/wait_condition.inc + +SELECT * FROM t2 ORDER by a; + +--connection con_temp1 +SELECT * FROM t1; +UNLOCK TABLES; + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 2 FROM t1 +--source include/wait_condition.inc + +SELECT * FROM t1 ORDER BY a; + +##### Case 1 : When DO_DOMAIN_IDS=(1) + +--connection server_2 +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Replicate events belonging to "domain_id 1". +CHANGE MASTER TO DO_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +--connection server_2 +--sync_with_master + +# Block the table t1 to simulate a replicated query taking a long time. +--connection con_temp1 +LOCK TABLE t1 WRITE; + +--connection server_1 +SET @@session.gtid_domain_id=0; +# This query will be blocked on the slave until UNLOCK TABLES. +# But, since DO_DOMAIN_IDS=(1), it will be filtered out on slave. +INSERT INTO t1 VALUES (3); + +SET @@session.gtid_domain_id=1; +# These t2 queries can be replicated in parallel with the prior t1 query, as +# they are in a separate replication domain. +INSERT INTO t2 VALUES (7); +INSERT INTO t2 VALUES (8); +BEGIN; +INSERT INTO t2 VALUES (9); +INSERT INTO t2 VALUES (10); +COMMIT; +INSERT INTO t2 VALUES (11); + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 11 FROM t2 +--source include/wait_condition.inc + +SELECT * FROM t2 ORDER by a; + +--connection con_temp1 +SELECT * FROM t1; +UNLOCK TABLES; + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 2 FROM t1 +--source include/wait_condition.inc + +SELECT * FROM t1 ORDER BY a; + +##### Case 2 : When IGNORE_DOMAIN_IDS=(1) + +--connection server_2 +--source include/stop_slave.inc +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Replicate events belonging to "domain_id 1". +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +--source include/start_slave.inc +sync_with_master; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +--connection server_2 +--sync_with_master + +# Block the table t1 to simulate a replicated query taking a long time. +--connection con_temp1 +LOCK TABLE t1 WRITE; + +--connection server_1 +SET @@session.gtid_domain_id=1; +# This query will be blocked on the slave until UNLOCK TABLES. However, since +# IGNORE_DOMAIN_IDS=(1), it will be filtered out on slave. +INSERT INTO t1 VALUES (4); +SET @@session.gtid_domain_id=0; +# These t2 queries can be replicated in parallel with the prior t1 query, as +# they are in a separate replication domain. +INSERT INTO t2 VALUES (12); +INSERT INTO t2 VALUES (13); +BEGIN; +INSERT INTO t2 VALUES (14); +INSERT INTO t2 VALUES (15); +COMMIT; +INSERT INTO t2 VALUES (16); + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 16 FROM t2 +--source include/wait_condition.inc + +SELECT * FROM t2 ORDER by a; + +--connection con_temp1 +SELECT * FROM t1; +UNLOCK TABLES; + +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 2 FROM t1 +--source include/wait_condition.inc + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2; + +--echo # Restore original settings. +--connection server_1 +SET @@session.gtid_domain_id=0; +DROP TABLE t1, t2; +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads= @old_parallel_threads; +CHANGE MASTER TO DO_DOMAIN_IDS=(), IGNORE_DOMAIN_IDS=(); +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test new file mode 100644 index 00000000..8083b8f2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test @@ -0,0 +1,73 @@ +--source include/master-slave.inc + +# +# Test for domain-id based filter on slave restart in GTID-mode. +# + + +connection slave; + +source include/stop_slave.inc; +let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (BEFORE) : $do_domain_ids_before +--echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before + +# Ignore events belonging to "domain_id 1". +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; +source include/start_slave.inc; + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +connection master; +SET @@session.gtid_domain_id= 0; +CREATE TABLE t1(i INT); +CREATE TABLE t2(i INT); + +INSERT INTO t1 VALUES(1); +SELECT * FROM t1; + +SET @@session.gtid_domain_id= 1; +# the following will get filtered out. +INSERT INTO t2 VALUES(1); +SELECT * FROM t2; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t1; +SELECT * FROM t2; + +# restart the slave +--let $rpl_server_number= 2 +--source include/rpl_restart_server.inc + +# Replicate_Do_Domain_Ids/Replicate_Ignore_Domain_Ids should reinitialize +# properly on restart. +connection slave; +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER RESTART) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER RESTART) : $ignore_domain_ids_after + +# Now, lets clear IGNORE_DOMAIN_IDS. +CHANGE MASTER TO IGNORE_DOMAIN_IDS=(); +--source include/start_slave.inc + +let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); +let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); +--echo DO_DOMAIN_IDS (AFTER) : $do_domain_ids_after +--echo IGNORE_DOMAIN_IDS (AFTER) : $ignore_domain_ids_after + +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +SET @@session.gtid_domain_id= 0; +DROP TABLE t1, t2; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop.test b/mysql-test/suite/rpl/t/rpl_drop.test new file mode 100644 index 00000000..7b887334 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop.test @@ -0,0 +1,12 @@ +# Testcase for BUG#4552 (DROP on two tables, one of which does not +# exist, must be binlogged with a non-zero error code) +source include/master-slave.inc; + +create table t1 (a int); +--error 1051 +drop table t1, t2; +--sync_slave_with_master + +# End of 4.1 tests + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_db.test b/mysql-test/suite/rpl/t/rpl_drop_db.test new file mode 100644 index 00000000..372afaa6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_db.test @@ -0,0 +1,62 @@ +# test case for BUG#4680 -- if there are extra files in the db directory +# dropping the db on the master causes replication problems + +-- source include/master-slave.inc +connection master; + +--disable_warnings +drop database if exists mysqltest1; +--enable_warnings +create database mysqltest1; +create table mysqltest1.t1 (n int); +insert into mysqltest1.t1 values (1); +select * from mysqltest1.t1 into outfile 'mysqltest1/f1.txt'; +create table mysqltest1.t2 (n int); +create table mysqltest1.t3 (n int); +--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty" +--error ER_DB_DROP_RMDIR +drop database mysqltest1; +use mysqltest1; +show tables; + +# test the branch of the code that deals with the query buffer overflow + +--disable_query_log +let $1=50; +while ($1) +{ + eval create table mysqltest1.mysqltest_long_table_name$1 (n int); + dec $1; +} +--enable_query_log + +--replace_result \\ / 66 39 93 39 17 39 247 39 41 39 "File exists" "Directory not empty" +--error ER_DB_DROP_RMDIR +drop database mysqltest1; +use mysqltest1; +show tables; +use test; +create table t1 (n int); +insert into t1 values (1234); +sync_slave_with_master; + +connection slave; +use mysqltest1; +show tables; +use test; +select * from t1; + +#cleanup +connection master; + +# Remove the "extra" file created above +let $MYSQLD_DATADIR= `select @@datadir`; +remove_file $MYSQLD_DATADIR/mysqltest1/f1.txt; + +use test; +drop table t1; +drop database mysqltest1; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_db_fail.test b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test new file mode 100644 index 00000000..c13bae1c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_db_fail.test @@ -0,0 +1,34 @@ +############################################################################### +# Bug#20041860: SLAVE ERROR WHEN DROP DATABASE +# +# Test: +# ===== +# Create two databases such that one database has a dependency over the other +# database and try to drop the database which has a dependency. This should +# not cause slave to break. +############################################################################### +--source include/have_innodb.inc +--source include/master-slave.inc + +connection master; +CREATE DATABASE IF NOT EXISTS db1; +CREATE DATABASE IF NOT EXISTS db2; + +use db1; +CREATE TABLE a(id INT); +CREATE VIEW v AS SELECT * FROM a; +CREATE TABLE table_father(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)) ENGINE=INNODB; +--sync_slave_with_master + +connection master; +use db2; +CREATE TABLE table_child(id INT PRIMARY KEY, info VARCHAR(20), father_id INT) ENGINE=INNODB; +ALTER TABLE table_child ADD CONSTRAINT aaa FOREIGN KEY (father_id) REFERENCES db1.table_father(id); + +--error ER_ROW_IS_REFERENCED_2 +DROP DATABASE db1; +DROP DATABASE db2; +--sync_slave_with_master +--connection master +DROP DATABASE db1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt b/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt new file mode 100644 index 00000000..2f9244c6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_temp-slave.opt @@ -0,0 +1,2 @@ +--replicate-ignore-table=mysqltest.t2 + diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp.test b/mysql-test/suite/rpl/t/rpl_drop_temp.test new file mode 100644 index 00000000..7158e2a8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_temp.test @@ -0,0 +1,94 @@ +############################################## +# Change Author: JBM +# Change Date: 2006-02-07 +# Change: Added ENGINE=MyISAM +############################################## +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; + +--disable_warnings +create database if not exists mysqltest; +--enable_warnings + +connect (con_temp,127.0.0.1,root,,test,$MASTER_MYPORT,); + +connection con_temp; +use mysqltest; +create temporary table mysqltest.t1 (n int)ENGINE=MyISAM; +create temporary table mysqltest.t2 (n int)ENGINE=MyISAM; + +disconnect con_temp; +--source include/wait_until_disconnected.inc + +connection master; +-- let $wait_binlog_event= DROP +-- source include/wait_for_binlog_event.inc +sync_slave_with_master; + +connection slave; +show status like 'Slave_open_temp_tables'; +# Cleanup +connection master; +drop database mysqltest; +sync_slave_with_master; + +# +# Bug#49137 +# This test verifies if DROP MULTI TEMPORARY TABLE +# will cause different errors on master and slave, +# when one or more of these tables do not exist. +# + +connection master; +DROP TEMPORARY TABLE IF EXISTS tmp1; +CREATE TEMPORARY TABLE t1 ( a int ); +--error 1051 +DROP TEMPORARY TABLE t1, t2; +--error 1051 +DROP TEMPORARY TABLE tmp2; +sync_slave_with_master; + +connection slave; +stop slave; +wait_for_slave_to_stop; + +connection master; +CREATE TEMPORARY TABLE tmp3 (a int); +DROP TEMPORARY TABLE tmp3; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; + +connection master; +sync_slave_with_master; + + +# +# BUG#54842: DROP TEMPORARY TABLE not binlogged after manual switching binlog format to ROW +# + +--source include/rpl_reset.inc +--connection master + +CREATE TABLE t1 ( i INT ); +--sync_slave_with_master +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +--connect(con1,localhost,root,,) +CREATE TEMPORARY TABLE ttmp1 ( i INT ); +SET SESSION binlog_format=ROW; +--disconnect con1 + +-- connection master +--let $wait_binlog_event= DROP +--source include/wait_for_binlog_event.inc +--sync_slave_with_master +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +--connection master +--source include/show_binlog_events.inc +DROP TABLE t1; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test b/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test new file mode 100644 index 00000000..475afef1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_temp_table_invalid_lex.test @@ -0,0 +1,41 @@ +# ==== Purpose ==== +# +# Test verifies that no ASAN issues are reported at the time of writing DROP +# TEMPORARY TABLE statements to binary log as part of session cleanup. +# +# ==== Implementation ==== +# +# Steps: +# 1 - Create a new connection named 'con1'. +# 2 - Create a temporary table named 'tmp' as part of connection 'con1'. +# 3 - Try to disconnect the current session when a CREATE .. SELECT +# statement is in the middle of execution. +# 4 - Observe that no ASAN issue is reported. +# +# ==== References ==== +# +# MDEV-19716: ASAN use-after-poison in Query_log_event::Query_log_event / +# THD::log_events_and_free_tmp_shares + +--source include/have_binlog_format_mixed_or_statement.inc +--source include/master-slave.inc + +--connect (con1,localhost,root,,) +CREATE TEMPORARY TABLE tmp (a INT); + +--send CREATE TABLE non_existing_db.t SELECT 1 AS b +--disconnect con1 +--source include/wait_until_disconnected.inc + +--connection master +--let $wait_binlog_event= DROP +--source include/wait_for_binlog_event.inc +sync_slave_with_master; + +--connection slave +--let $open_temp_tbl_count=query_get_value(show status like 'Slave_open_temp_tables', Value, 1) +--let $assert_cond= "open_temp_tbl_count" = 0 +--let $assert_text= "Slave_open_temp_tables count should be 0" +--source include/assert.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_drop_view.test b/mysql-test/suite/rpl/t/rpl_drop_view.test new file mode 100644 index 00000000..1893dd21 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_view.test @@ -0,0 +1,35 @@ +# test case for bug#30998 +# Drop View breaks replication if view does not exist +# + +source include/master-slave.inc; +--disable_warnings +drop table if exists t1, t2; +drop view if exists v1, v2, v3, not_exist_view; +--enable_warnings +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create view v1 as select * from t1; +create view v2 as select * from t2; +create view v3 as select * from t3; +--error ER_UNKNOWN_VIEW +drop view not_exist_view; +--error ER_UNKNOWN_VIEW +drop view v1, not_exist_view; +--error 1146 +select * from v1; +drop view v2, v3; +sync_slave_with_master; +--error 1146 +select * from v1; +--error 1146 +select * from v2; +--error 1146 +select * from v3; + +--echo ==== clean up ==== +connection master; +drop table t1, t2, t3; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test b/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test new file mode 100644 index 00000000..618576f5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_dual_pos_advance.test @@ -0,0 +1,97 @@ +# This test checks that in a dual-head setup +# A->B->A, where A has --log-slave-updates (why would it? +# assume that there is a C as slave of A), +# then the Exec_master_log_pos of SHOW SLAVE STATUS does +# not stay too low on B(BUG#13023 due to events ignored because +# of their server id). +# It also will test BUG#13861. + +source include/have_innodb.inc; + +--let $rpl_topology= 1->2->1 +--source include/rpl_init.inc + +# now we test it + +connection server_2; + +create table t1 (n int); +let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $master_log_pos_1= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_log_pos_1= `SELECT $master_log_pos_1 + 3`; + +--sync_slave_with_master server_1 + +# +# BUG#13861 - START SLAVE UNTIL may stop 1 evnt too late if +# log-slave-updates and circul repl +# +source include/stop_slave.inc; + +create table t2 (n int); # create one ignored event + +--sync_slave_with_master server_2 + +show tables; + +create table t3 (n int) engine=innodb; +let $master_log_pos_2= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_log_pos_2= `SELECT $master_log_pos_2 + 5`; +set @a=1; +insert into t3 values(@a); +let $master_log_pos_3= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_log_pos_3= `SELECT $master_log_pos_3 + 5`; +begin; +insert into t3 values(2); +insert into t3 values(3); +commit; +insert into t3 values(4); + + +connection server_1; + +# bug is that START SLAVE UNTIL may stop too late, we test that by +# asking it to stop before creation of t3. + +--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_1 MASTER_LOG_POS +eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_1; +--source include/wait_for_slave_sql_to_stop.inc + +# then BUG#13861 causes t3 to show up below (because stopped too +# late). + +show tables; + +# ensure that we do not break set @a=1; insert into t3 values(@a); +--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_2 MASTER_LOG_POS +eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_2; +--source include/wait_for_slave_sql_to_stop.inc +select * from t3; + +# ensure that we do not break transaction +--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_3 MASTER_LOG_POS +eval start slave until master_log_file="$master_log_file",master_log_pos=$master_log_pos_3; +--source include/wait_for_slave_sql_to_stop.inc +select * from t3; + +source include/start_slave.inc; + +# BUG#13023 is that Exec_master_log_pos may stay too low "forever": + +connection server_1; + +create table t4 (n int); # create 3 ignored events +create table t5 (n int); +create table t6 (n int); + +--sync_slave_with_master server_2 + +# then BUG#13023 caused hang below ("master" looks behind, while it's +# not in terms of updates done). +--sync_slave_with_master server_1 + +show tables; + +# cleanup +drop table t1, t2, t3, t4, t5, t6; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test new file mode 100644 index 00000000..d750d44a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test @@ -0,0 +1,60 @@ +# ==== Purpose ==== +# +# Test verifies that, due to a temporary network error, if request dump +# command specific packet write operation fails then the write error gets +# handled appropriately. Further retry will be initiated with appropriate +# slave registration on master. This will ensure that master has all the +# details of slave and no warnings are reported on the master side. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Skip the slave start. +# 1 - Enable debug simulation which will simulate packet write error during +# dump request command execution. +# 2 - Start the slave. Observe that slave is able to reconnect post +# temporary network write error. +# +# ==== References ==== +# +# MDEV-14203: rpl.rpl_extra_col_master_myisam, +# rpl.rpl_slave_load_tmpdir_not_exist failed in buildbot with a +# warning +# +# MDEV-13258: rpl.rpl_skip_replication, rpl.rpl_set_statement_default_master +# failed in buildbot +# + +--source include/have_debug.inc +--source include/have_debug_sync.inc +--let $rpl_skip_start_slave=1 +--source include/master-slave.inc + +# Do an insert on master +CREATE TABLE t1(a int); +INSERT INTO t1 VALUES(1); + +# Add a debug point and start the slave so that dump request fails. +connection slave; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@global.debug_dbug= 'd,simulate_error_on_packet_write'; + +START SLAVE; +SET DEBUG_SYNC= 'now WAIT_FOR parked'; +SET @@GLOBAL.debug_dbug = @saved_dbug; +SET DEBUG_SYNC= 'now SIGNAL continue'; +SET DEBUG_SYNC= 'RESET'; + +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_start.inc + +# Sync the slave and verify that slave has caught up with the master. +connection master; +--source include/sync_slave_sql_with_master.inc +SELECT * FROM t1; + +# Cleanup +connection master; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_empty_master_host.test b/mysql-test/suite/rpl/t/rpl_empty_master_host.test new file mode 100644 index 00000000..0fc2d11a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_empty_master_host.test @@ -0,0 +1,53 @@ +# +# BUG +# --- +# BUG#28796: CHANGE MASTER TO MASTER_HOST="" leads to invalid master.info +# +# Description +# ----------- +# +# This test aims at: +# i) verifying that an error is thrown when setting MASTER_HOST='' +# ii) no error is thrown when setting non empty MASTER_HOST +# iii) replication works after setting a correct host name/ip +# +# Implementation is performed by feeding different values (according +# to i), ii) and iii) ) to CHANGE MASTER TO MASTER_HOST= x and checking +# along the way if error/no error is thrown and/or if replication starts +# working when expected. + +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +connection slave; +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc + +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master_Host = '$master_host' (expected '127.0.0.1') + +# attempt to change to an empty master host should +# result in error ER_WRONG_ARGUMENTS: "Incorrect arguments to ..." +error ER_WRONG_ARGUMENTS; +CHANGE MASTER TO MASTER_HOST=""; + +# show slave status still holds previous information +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master_Host = '$master_host' (expected '127.0.0.1') + +# changing master to other than empty master host succeeds +CHANGE MASTER TO MASTER_HOST="foo"; + +# show slave status should hold "foo" as master host +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master_Host = '$master_host' (expected 'foo') + +# changing back to localhost +CHANGE MASTER TO MASTER_HOST="127.0.0.1"; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master_Host = '$master_host' (expected '127.0.0.1') + +# start slave must succeed. +START SLAVE; +--source include/wait_for_slave_to_start.inc +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt b/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt new file mode 100644 index 00000000..cb49119b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test new file mode 100644 index 00000000..9aee3582 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test @@ -0,0 +1,70 @@ +# Test for +# Bug #797: If a query is ignored on slave (replicate-ignore-table) the slave +# still checks that it has the same error as on the master. +########################################################################## + +-- source include/master-slave.inc + +-- disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); +-- enable_query_log + +connection master; +create table t1 (a int primary key); +create table t4 (a int primary key); +# generate an error that goes to the binlog +--error 1022, ER_DUP_ENTRY +insert into t1 values (1),(1); +insert into t4 values (1),(2); +# as the t1 table is ignored on the slave, the slave should be able to sync +sync_slave_with_master; +# check that the table has been ignored, because otherwise the test is nonsense +show tables like 't1'; +show tables like 't4'; +SELECT * FROM test.t4 ORDER BY a; +connection master; +drop table t1; +sync_slave_with_master; + +# Now test that even critical errors (connection killed) +# are ignored if rules allow it. +# The "kill" idea was copied from rpl000001.test. + +connection master1; +select get_lock('crash_lock%20C', 10); + +connection master; +create table t2 (a int primary key); +insert into t2 values(1); +create table t3 (id int); +insert into t3 values(connection_id()); +send update t2 set a = a + 1 + get_lock('crash_lock%20C', 10); + +connection master1; +let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE info LIKE 'update%' AND state='User lock'; +source include/wait_condition.inc; +select (@id := id) - id from t3; +kill @id; +let $id= `SELECT @id`; +let $wait_condition= SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = $id; +source include/wait_condition.inc; +drop table t2,t3; +insert into t4 values (3),(4); +connection master; +# The get_lock function causes warning for unsafe statement. +--disable_warnings +--error 0,1317,2013 +reap; +--enable_warnings +connection master1; +sync_slave_with_master; +SELECT * FROM test.t4 ORDER BY a; + +connection master1; +DROP TABLE test.t4; +sync_slave_with_master; +# End of 4.1 tests +# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test new file mode 100644 index 00000000..3e73fc7a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_events.test @@ -0,0 +1,244 @@ +################################################################## +# Author: Giuseppe # +# Date: 2006-12-20 # +# Purpose: To test that event effects are replicated. # +################################################################## + +--source include/master-slave.inc + +SET @old_event_scheduler = @@global.event_scheduler; +set global event_scheduler=1; + +# first, we need a table to record something from an event + +eval CREATE TABLE `t1` ( + `id` INT(10) UNSIGNED NOT NULL, + `c` VARCHAR(50) NOT NULL, + `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) DEFAULT CHARSET=utf8; + +INSERT INTO t1 (id, c) VALUES (1, 'manually'); + +# We create the event so that it inserts exactly 1 row in the table +# A recuring event is used so that we can be sure the event will +# fire regardless of timing delays on the server. Otherwise, it is +# possible for the event to timeout before it has inserted a row. +--echo "Creating event test.justonce on the master" +CREATE EVENT test.justonce ON SCHEDULE EVERY 2 SECOND DO + INSERT IGNORE INTO t1 (id, c) VALUES (2, 'from justonce'); + +# Show the event is alive and present on master +--echo "Checking event is active on master" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; + +# Wait until event has fired. We know this because t1 will contain +# the row from the event. +let $wait_condition= + SELECT COUNT(*) = 1 FROM t1 WHERE c = 'from justonce'; +--source include/wait_condition.inc + +# check that table t1 contains something +--echo "Checking event data on the master" +let $events_done=`SELECT count(*) FROM t1 id`; +--disable_query_log +eval SELECT $events_done > 0 as ONE; +--enable_query_log + +sync_slave_with_master; + +--echo "Checking event data on the slave" +--disable_query_log +eval SELECT count(*) - $events_done as ZERO FROM t1 id; +--enable_query_log + +--echo "Checking event is inactive on slave" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; + +# Create an event on the slave and check to see what the originator is. +--echo "Dropping event test.slave_once on the slave" +--disable_warnings +DROP EVENT IF EXISTS test.slave_once; +--enable_warnings + +# Create an event on slave and check its state. An event shouldn't be executed +# so set start time in 1 hour. +CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO + INSERT IGNORE INTO t1(id, c) VALUES (3, 'from slave_once'); + +--echo "Checking event status on the slave for originator value = slave's server_id" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_once'; + +--echo "Dropping event test.slave_once on the slave" +--disable_warnings +DROP EVENT IF EXISTS test.slave_once; +--enable_warnings + +connection master; + +# BUG#20384 - disable events on slave +--echo "Dropping event test.justonce on the master" +--disable_warnings +DROP EVENT IF EXISTS test.justonce; +--enable_warnings + +# Create an event on master and check its state on slave. An event shouldn't be executed +# so set start time in 1 hour. Check that changes of event statement replicated to slave + +--echo "Creating event test.er on the master" +CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO + INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er'); + +--echo "Checking event status on the master" +SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; + +sync_slave_with_master; + +--echo "Checking event status on the slave" +SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; + +connection master; +--echo "Altering event test.er on the master" +ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO + INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er'); + +--echo "Checking event status on the master" +SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; + +sync_slave_with_master; + +--echo "Checking event status on the slave" +SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; + +connection master; +--echo "Dropping event test.er on the master" +DROP EVENT test.er; + +--echo "Checking event status on the master" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; + +--disable_info + +sync_slave_with_master; + +--echo "Checking event status on the slave" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; + +# test the DISABLE ON SLAVE for setting event SLAVESIDE_DISABLED as status +# on CREATE EVENT + +# Create an event on slave and check its status. An event shouldn't be executed +# so set start time in 1 hour. + +--echo "Creating event test.slave_terminate on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO + INSERT IGNORE INTO t1(id, c) VALUES (6, 'from slave_terminate'); + +--echo "Checking event status on the slave" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; + +--echo "Dropping event test.slave_terminate on the slave" +DROP EVENT test.slave_terminate; + +--echo "Creating event test.slave_terminate with DISABLE ON SLAVE on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DISABLE ON SLAVE DO + INSERT IGNORE INTO t1(c) VALUES (7, 'from slave_terminate'); + +--echo "Checking event status on the slave" +SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; + +--echo "Dropping event test.slave_terminate on the slave" +DROP EVENT test.slave_terminate; + +--echo "Cleanup" + +connection master; +DROP TABLE t1; +sync_slave_with_master; +connection master; + +# +# Bug #28953 Using events in a replication let the slave crash. +# + +CREATE TABLE t28953 (a INT); + +DELIMITER |; +CREATE EVENT event1 ON SCHEDULE EVERY 1 YEAR +DO BEGIN + select * from t28953; +END;| +DELIMITER ;| + +ALTER EVENT event1 RENAME TO event2; + +sync_slave_with_master; + +connection master; + +DROP EVENT event2; + +# +# BUG#44331 +# This test verifies if the definer is consistent between master and slave, +# when the event is created without the DEFINER clause set explicitly or the +# DEFINER is set to CURRENT_USER +# +CREATE TABLE test.t1(details CHAR(30)); + +CREATE EVENT /*!50000 event44331_1 */ + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer'); + +CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */ + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER'); + +CREATE DEFINER=CURRENT_USER() EVENT event44331_3 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function'); + +DELIMITER |; +CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1'); +# Test for bug#50095 Multi-statement including CREATE EVENT causes rotten +# binlog entry + SELECT 'ABC'; + SELECT '123'| +DELIMITER ;| + +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_1'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_2'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_3'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_4'; + +sync_slave_with_master; +connection slave; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_1'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_2'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_3'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_4'; + +connection master; +SET @@global.event_scheduler= @old_event_scheduler; +DROP TABLE t28953; +DROP TABLE t1; +DROP EVENT event44331_1; +DROP EVENT event44331_2; +DROP EVENT event44331_3; +DROP EVENT event44331_4; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test b/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test new file mode 100644 index 00000000..63ae0fce --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_extra_col_master_innodb.test @@ -0,0 +1,11 @@ +############################################################# +# Purpose: To test having extra columns on the master WL#3915 +############################################################# +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +let $engine_type = 'InnoDB'; +--source include/rpl_extra_col_master.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test b/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test new file mode 100644 index 00000000..72a35992 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_extra_col_master_myisam.test @@ -0,0 +1,10 @@ +############################################################# +# Purpose: To test having extra columns on the master WL#3915 +############################################################# +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +let $engine_type = 'MyISAM'; +--source include/rpl_extra_col_master.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test b/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test new file mode 100644 index 00000000..e16e1dba --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_extra_col_slave_innodb.test @@ -0,0 +1,7 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +let $engine_type = 'InnoDB'; +-- source include/rpl_extra_col_slave.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test b/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test new file mode 100644 index 00000000..f1e9fa24 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_extra_col_slave_myisam.test @@ -0,0 +1,6 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +let $engine_type = 'MyISAM'; +-- source include/rpl_extra_col_slave.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_fail_register.test b/mysql-test/suite/rpl/t/rpl_fail_register.test new file mode 100644 index 00000000..d95a5c5f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_fail_register.test @@ -0,0 +1,33 @@ +source include/have_debug.inc; +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +connection slave; + +set @old_dbug=@@global.debug_dbug; +set global debug_dbug='d,fail_com_register_slave'; + +stop slave; +reset slave; +source include/wait_for_slave_to_stop.inc; +start slave; +stop slave; +source include/wait_for_slave_to_stop.inc; +set global debug_dbug=@old_dbug; + +connection master; + +let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`; + +if ($id) { + replace_result $id DUMP_THREAD; + eval kill $id; + let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed'; + source include/wait_condition.inc; +} + +show slave hosts; + +connection slave; +start slave; +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt b/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt new file mode 100644 index 00000000..14fe8f7b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_failed_drop_tbl_binlog.opt @@ -0,0 +1 @@ +--loose-innodb-adaptive-hash-index diff --git a/mysql-test/suite/rpl/t/rpl_failed_optimize.test b/mysql-test/suite/rpl/t/rpl_failed_optimize.test new file mode 100644 index 00000000..a65c19cb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_failed_optimize.test @@ -0,0 +1,3 @@ +-- source include/have_innodb.inc +let $engine_type=InnoDB; +-- source include/rpl_failed_optimize.test diff --git a/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test new file mode 100644 index 00000000..05590a0a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test @@ -0,0 +1,63 @@ +# +# Test if dynamic replication database filter rules are properly evaluated. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_do_db="db1"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_ignore_db="db2"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_do_db="db1"; +SET @@GLOBAL.replicate_ignore_db="db2"; +source include/start_slave.inc; +connection master; + +CREATE DATABASE db1; +CREATE DATABASE db2; +CREATE DATABASE db3; + +# db is mentioned in do-db rules +USE db1; +CREATE TABLE t1 (a INT); + +# db is mentioned in ignore-db rules +USE db2; +CREATE TABLE t2 (a INT); + +# db is not mentioned in do-db or ignore-db rules +USE db3; +CREATE TABLE t3 (a INT); + +USE db1; +INSERT INTO t1 VALUES (1); + +USE db2; +INSERT INTO t2 VALUES (2); + +USE db3; +INSERT INTO t3 VALUES (3); + +# Only db1 should be replicated to slave +sync_slave_with_master; +echo [on slave]; +SHOW DATABASES LIKE 'db%'; +SHOW TABLES IN db1 LIKE 't%'; + +connection master; + +# Clean up +connection master; +DROP DATABASE IF EXISTS db1; +DROP DATABASE IF EXISTS db2; +DROP DATABASE IF EXISTS db3; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_do_db=""; +SET @@GLOBAL.replicate_ignore_db=""; diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test new file mode 100644 index 00000000..529613b3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test @@ -0,0 +1,217 @@ +# Test evaluation of replication table filter rules +# +# ==== Purpose ==== +# +# Test if dynamic replication table filter rules are properly evaluated +# when some of the tables referenced by the multiple-table update do not +# exist on slave. +# +# ==== Method ==== +# +# Master creates tables t1, t2, t3, t4, t5, t6, t7, t8, t9 and the +# slave is started with the following replication table filter rules: +# +# SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +# +# and +# +# SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +# +# So the slave only replicate changes to tables t1, t2 and t3 and only +# these tables exist on slave. +# +# From now on, tables t1, t2, and t3 are referenced as do tables, +# tables t4, t5, t6 are referenced as ignore tables, and tables t7, +# t8, t9 are referenced as other tables. +# +# All multi-table update tests reference tables that are not do +# tables, which do not exist on slave. And the following situations +# of multi-table update will be tested: +# +# 1. Do tables are not referenced at all +# 2. Do tables are not referenced for update +# 3. Ignore tables are referenced for update before do tables +# 4. Only do tables are referenced for update +# 5. Do tables and other tables are referenced for update +# 6. Do tables are referenced for update before ignore tables +# +# For 1, 2 and 3, the statement should be ignored by slave, for 4, 5 +# and 6 the statement should be accepted by slave and cause an error +# because of non-exist tables. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +source include/start_slave.inc; +connection master; + +# These tables are mentioned in do-table rules +CREATE TABLE t1 (id int, a int); +CREATE TABLE t2 (id int, b int); +CREATE TABLE t3 (id int, c int); + +# These tables are mentioned in ignore-table rules +CREATE TABLE t4 (id int, d int); +CREATE TABLE t5 (id int, e int); +CREATE TABLE t6 (id int, f int); + +# These tables are not mentioned in do-table or ignore-table rules +CREATE TABLE t7 (id int, g int); +CREATE TABLE t8 (id int, h int); +CREATE TABLE t9 (id int, i int); + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3); + +# Only t1, t2, t3 should be replicated to slave +sync_slave_with_master; +SHOW TABLES LIKE 't%'; + +connection master; + +# +# Do tables are not referenced, these statements should be ignored by +# slave. +# +UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1; +UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1; + +# +# Do tables are not referenced for update, these statements should be +# ignored by slave. +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1; +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1; + +# +# Ignore tables are referenced for update before do tables, these +# statements should be ignore by slave. +# +UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1; + +# Sync slave to make sure all above statements are correctly ignored, +# if any of the above statement are not ignored, it would cause error +# and stop slave sql thread. +sync_slave_with_master; +connection slave; +call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* error.* 1146"); +connection master; + +# Parameters for include/wait_for_slave_sql_error_and_skip.inc: +# Ask it to show SQL error message. +let $show_slave_sql_error= 1; +# The expected error will always be 1146 (ER_NO_SUCH_TABLE). +let $slave_sql_errno= 1146; + +# +# Only do tables are referenced for update, these statements should +# cause error on slave +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables and other tables are referenced for update, these +# statements should cause error on slave +# +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables are referenced for update before ignore tables +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +sync_slave_with_master; +echo [on slave]; + +# We should only have tables t1, t2, t3 on slave +show tables like 't%'; + +# The rows in these tables should remain untouched +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +# Clean up +connection master; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt new file mode 100644 index 00000000..42acd3ea --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist-slave.opt @@ -0,0 +1 @@ +--replicate-do-table=test.t1 --replicate-do-table=test.t2 --replicate-do-table=test.t3 --replicate-ignore-table=test.t4 --replicate-ignore-table=test.t5 --replicate-ignore-table=test.t6 diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test new file mode 100644 index 00000000..ee6daac7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test @@ -0,0 +1,267 @@ +# Test evaluation of replication table filter rules +# +# ==== Purpose ==== +# +# Test if replication table filter rules are properly evaluated when +# some of the tables referenced by the multiple-table update do not +# exist on slave. +# +# ==== Method ==== +# +# Master creates tables t1, t2, t3, t4, t5, t6, t7, t8, t9 and the +# slave is started with the following replication table filter rules: +# +# --replicate-do-table=t1 +# --replicate-do-table=t2 +# --replicate-do-table=t3 +# +# and +# +# --replicate-ignore-table=t4 +# --replicate-ignore-table=t5 +# --replicate-ignore-table=t6 +# +# So the slave only replicate changes to tables t1, t2 and t3 and only +# these tables exist on slave. +# +# From now on, tables t1, t2, and t3 are referenced as do tables, +# tables t4, t5, t6 are referenced as ignore tables, and tables t7, +# t8, t9 are referenced as other tables. +# +# All multi-table update tests reference tables that are not do +# tables, which do not exist on slave. And the following situations +# of multi-table update will be tested: +# +# 1. Do tables are not referenced at all +# 2. Do tables are not referenced for update +# 3. Ignore tables are referenced for update before do tables +# 4. Only do tables are referenced for update +# 5. Do tables and other tables are referenced for update +# 6. Do tables are referenced for update before ignore tables +# +# For 1, 2 and 3, the statement should be ignored by slave, for 4, 5 +# and 6 the statement should be accepted by slave and cause an error +# because of non-exist tables. +# +# ==== Related bugs ==== +# +# BUG#37051 Replication rules not evaluated correctly + + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +# These tables are mentioned in do-table rules +CREATE TABLE t1 (id int, a int); +CREATE TABLE t2 (id int, b int); +CREATE TABLE t3 (id int, c int); + +# These tables are mentioned in ignore-table rules +CREATE TABLE t4 (id int, d int); +CREATE TABLE t5 (id int, e int); +CREATE TABLE t6 (id int, f int); + +# These tables are not mentioned in do-table or ignore-table rules +CREATE TABLE t7 (id int, g int); +CREATE TABLE t8 (id int, h int); +CREATE TABLE t9 (id int, i int); + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3); + +# Only t1, t2, t3 should be replicated to slave +sync_slave_with_master; +SHOW TABLES LIKE 't%'; + +connection master; + +# +# Do tables are not referenced, these statements should be ignored by +# slave. +# +UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1; +UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1; + +# +# Do tables are not referenced for update, these statements should be +# ignored by slave. +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1; +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1; + +# +# Ignore tables are referenced for update before do tables, these +# statements should be ignore by slave. +# +UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1; + +# Sync slave to make sure all above statements are correctly ignored, +# if any of the above statement are not ignored, it would cause error +# and stop slave sql thread. +sync_slave_with_master; +connection slave; +call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* error.* 1146"); +connection master; + +# Parameters for include/wait_for_slave_sql_error_and_skip.inc: +# Ask it to show SQL error message. +let $show_slave_sql_error= 1; +# The expected error will always be 1146 (ER_NO_SUCH_TABLE). +let $slave_sql_errno= 1146; + +# +# Only do tables are referenced for update, these statements should +# cause error on slave +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables and other tables are referenced for update, these +# statements should cause error on slave +# +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables are referenced for update before ignore tables +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +sync_slave_with_master; +echo [on slave]; + +# We should only have tables t1, t2, t3 on slave +show tables like 't%'; + +# The rows in these tables should remain untouched +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +# Clean up +connection master; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; + +--sync_slave_with_master + +# +# BUG#11754117 - 45670: INTVAR_EVENTS FOR FILTERED-OUT QUERY_LOG_EVENTS ARE EXECUTED +# Int-, Rand- and User- var events accompaning a filtered out Query-log-event should +# be filtered as well. +# +connection master; +# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D. +CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT); # ignored on slave +CREATE TABLE test.t1 (a INT); # accepted on slave +INSERT INTO test.t1 VALUES(1); + +--sync_slave_with_master +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +# Although RAND() is from 0 to 1.0, DECIMAL(M,D), requires that M must be >= D. +CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b DECIMAL(20,20), c INT); +CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW + INSERT INTO test.t_slave VALUES(NULL, RAND(), @c); + +connection master; +SET INSERT_ID=2; +SET @c=2; +SET @@rand_seed1=10000000, @@rand_seed2=1000000; +INSERT INTO t5 VALUES (NULL, RAND(), @c); # to be ignored +SELECT b into @b FROM test.t5; +--let $b_master=`select @b` +UPDATE test.t1 SET a=2; # to run trigger on slave + +--sync_slave_with_master + +# The proof: +SELECT a AS 'ONE' into @a FROM test.t_slave; +SELECT c AS 'NULL' into @c FROM test.t_slave; + +let $count= 1; +let $table= test.t_slave; +source include/wait_until_rows_count.inc; + +if (`SELECT @a != 2 and @c != NULL`) +{ + SELECT * FROM test.t_slave; + --die Intvar or user var from replication events unexpetedly escaped out to screw a following query applying context. +} + +SELECT b into @b FROM test.t_slave; +--let $b_slave=`select @b` + +--let $assert_text= Random values from master and slave must be different +--let $assert_cond= $b_master != $b_slave +--source include/assert.inc + +# cleanup BUG#11754117 +connection master; +drop table test.t5; +drop table test.t1; + +--sync_slave_with_master +drop table test.t_slave; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test new file mode 100644 index 00000000..657a95ce --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test @@ -0,0 +1,49 @@ +# +# Test if dynamic replication wild table filter rules are properly evaluated. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_wild_do_table=""; +SET @@GLOBAL.replicate_wild_ignore_table=""; +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; +source include/start_slave.inc; +connection master; + +# Table is mentioned in wild-do-table rules +CREATE TABLE a1 (a INT); + +# Table is mentioned in wild-ignore-table rules +CREATE TABLE b1 (a INT); + +# Table is not mentioned in wild-do-table or wild-ignore-table rules +CREATE TABLE c1 (a INT); + +INSERT INTO a1 VALUES (1); +INSERT INTO b1 VALUES (2); +INSERT INTO c1 VALUES (3); + +# Only a1 should be replicated to slave +sync_slave_with_master; +SHOW TABLES LIKE '%1'; + +connection master; + +# Clean up +connection master; +DROP TABLE IF EXISTS a1,b1,c1; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_wild_do_table=""; +SET @@GLOBAL.replicate_wild_ignore_table=""; diff --git a/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt b/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt new file mode 100644 index 00000000..36eab1d6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_flush_logs-master.opt @@ -0,0 +1 @@ +--log-error=$MYSQLTEST_VARDIR/tmp/master_log.err diff --git a/mysql-test/suite/rpl/t/rpl_flush_logs.test b/mysql-test/suite/rpl/t/rpl_flush_logs.test new file mode 100644 index 00000000..6dad588f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test @@ -0,0 +1,141 @@ +# +# WL#5124 +# This test verifies if the 'flush individual logs' statement +# works fine. +# + +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +connection master; + +# Test 'flush error logs' statement. + +--echo # Test if support 'flush error logs' statement. +flush error logs; + +file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; + +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush error logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + +sync_slave_with_master; +--echo # Make sure relay logs was not be flushed +--echo # after execute 'flush error logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000003; + +connection master; +--echo # Test if support 'flush relay logs' statement. +flush relay logs; + +sync_slave_with_master; +--echo # Check the 'slave-relay-bin.000003' file is not created +--echo # after executed 'flush relay logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000003; + +connection master; +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush relay logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + + +# Test 'flush slow logs' statement. +--echo # Test if support 'flush slow logs' statement. +flush slow logs; + +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush slow logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + + +# Test 'flush general logs' statement. +--echo # Test if support 'flush general logs' statement. +flush general logs; + +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush general logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + + +# Test 'flush engine logs' statement. +--echo # Test if support 'flush engine logs' statement. +flush engine logs; + +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush engine logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + + +# Test 'flush binary logs' statement. +--echo # Make sure the 'master-bin.000002' file does not +--echo # exist before execute 'flush binary logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; + +--echo # Test if support 'flush binary logs' statement. +flush binary logs; + +--echo # Check the 'master-bin.000002' file is created +--echo # after executed 'flush binary logs' statement. +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000002; +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000001; + + +# Test 'flush error logs, relay logs' statement +sync_slave_with_master; +--echo # Make sure the 'slave-relay-bin.000005' file does not exist +--echo # exist before execute 'flush error logs, relay logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; + +connection master; + +--echo # Test if support to combine all kinds of logs into one statement. +flush error logs, relay logs; + +file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; + +--echo # Make sure binary logs was not be flushed +--echo # after execute 'flush error logs, relay logs' statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003; + +sync_slave_with_master; +--echo # Check the 'slave-relay-bin.000004' file is created after +--echo # execute 'flush error logs, relay logs' statement. +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000004; + +# Test 'flush logs' statement +--echo # Make sure the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' +--echo # files do not exist before execute 'flush error logs, relay logs' +--echo # statement. +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; +--error 1 +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; + +connection master; + +--echo # Test if 'flush logs' statement works fine and flush all the logs. +flush logs; + +file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; + +--echo # Check 'master-bin.000003' is created +--echo # after execute 'flush logs' statement. +file_exists $MYSQLTEST_VARDIR/mysqld.1/data/master-bin.000003; + +sync_slave_with_master; +--echo # Check the 'slave-relay-bin.000005' and 'slave-relay-bin.000006' +--echo # files are created after execute 'flush logs' statement. +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000005; +file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000006; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt b/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt new file mode 100644 index 00000000..3b5d41d4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop-master.opt @@ -0,0 +1 @@ +--max_binlog_size=1M diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt b/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt new file mode 100644 index 00000000..3b5d41d4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop-slave.opt @@ -0,0 +1 @@ +--max_binlog_size=1M diff --git a/mysql-test/suite/rpl/t/rpl_flushlog_loop.test b/mysql-test/suite/rpl/t/rpl_flushlog_loop.test new file mode 100644 index 00000000..d5d362ba --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_flushlog_loop.test @@ -0,0 +1,46 @@ +# Testing if "flush logs" command bouncing resulting in logs created in a loop +# in case of bi-directional replication +--let $rpl_topology= 1->2->1 +--source include/rpl_init.inc + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR/ +show variables like 'relay_log%'; + +# +# Flush logs of slave +# +# Create full loop by following way: +# 1. Insert into t1 on master (1st). +# 2. Insert into t1 on slave (2nd) when the event (1st) for t1 replicated. +# 3. Master waits until the event (2nd) for t1 will be replicated. + +CREATE TABLE t1 (a INT KEY) ENGINE= MyISAM; +let $wait_binlog_event= CREATE TABLE t1; +--source include/wait_for_binlog_event.inc +sync_slave_with_master server_2; + +connection server_1; +INSERT INTO t1 VALUE(1); +FLUSH LOGS; +sync_slave_with_master server_2; + +INSERT INTO t1 VALUE(2); +let $slave_param_value= query_get_value(SHOW MASTER STATUS, Position, 1); +sync_slave_with_master server_1; + +# +# Check that the master server's slave threads are still running and show +# Relay_Log_File +# +--source include/check_slave_is_running.inc +--let status_items= Relay_Log_File +--source include/show_slave_status.inc + +--disable_query_log +connection server_1; +DROP TABLE t1; +sync_slave_with_master server_2; +--enable_query_log + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test b/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test new file mode 100644 index 00000000..2c4af75e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_foreign_key_innodb.test @@ -0,0 +1,78 @@ +-- source include/have_innodb.inc + +# Check the replication of the FOREIGN_KEY_CHECKS variable. + +-- source include/master-slave.inc + +CREATE TABLE t1 (a INT AUTO_INCREMENT KEY) ENGINE=INNODB; +CREATE TABLE t2 (b INT AUTO_INCREMENT KEY, c INT, FOREIGN KEY(b) REFERENCES t1(a)) ENGINE=INNODB; + +SET FOREIGN_KEY_CHECKS=0; +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL); +INSERT INTO t2 VALUES (5,0); +INSERT INTO t2 VALUES (NULL,LAST_INSERT_ID()); +SET FOREIGN_KEY_CHECKS=1; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY b; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY b; + +connection master; +SET TIMESTAMP=1000000000; +CREATE TABLE t3 ( a INT UNIQUE ); +SET FOREIGN_KEY_CHECKS=0; +--error ER_DUP_ENTRY +INSERT INTO t3 VALUES (1),(1); +sync_slave_with_master; + +connection master; +SET FOREIGN_KEY_CHECKS=0; +DROP TABLE IF EXISTS t1,t2,t3; +SET FOREIGN_KEY_CHECKS=1; +sync_slave_with_master; + +# +# Bug #32468 delete rows event on a table with foreign key constraint fails +# + +connection master; + +create table t1 (b int primary key) engine = INNODB; +create table t2 (a int primary key, b int, foreign key (b) references t1(b)) engine = INNODB; + +insert into t1 set b=1; +insert into t2 set a=1, b=1; + +set foreign_key_checks=0; +delete from t1; + +--echo must sync w/o a problem (could not with the buggy code) +sync_slave_with_master; +select count(*) from t1 /* must be zero */; + + +# cleanup for bug#32468 + +connection master; +drop table t2,t1; +set foreign_key_checks=1; + +--echo # +--echo # MDEV-25530 Error 1451 on slave: Cannot delete or update a parent row: a foreign key constraint fails +--echo # + +create table t1 (id int primary key)engine=innodb; +create table t2 (id int not null primary key auto_increment, + id2 int default null, key f1 (id2), + constraint f1 foreign key (id2) references t1 (id) on delete cascade) engine=innodb; +error ER_ROW_IS_REFERENCED_2; +drop table t1,t2; +sync_slave_with_master; +show tables; +connection master; +drop table t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_free_items-slave.opt b/mysql-test/suite/rpl/t/rpl_free_items-slave.opt new file mode 100644 index 00000000..b828d03f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_free_items-slave.opt @@ -0,0 +1 @@ +--replicate-wild-ignore-table=test.% diff --git a/mysql-test/suite/rpl/t/rpl_free_items.test b/mysql-test/suite/rpl/t/rpl_free_items.test new file mode 100644 index 00000000..581409cf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_free_items.test @@ -0,0 +1,23 @@ +source include/master-slave.inc; +create table t1 (a int); +create table t2 (a int); +disable_query_log; +SET @query="INSERT INTO t2 SELECT * FROM t1 WHERE a REGEXP \"0\""; +let $1 = 2000; +while ($1) +{ + eval SET @query=concat(@query, " OR a REGEXP '$1'"); + dec $1; +} +let $1=`select @query`; +eval $1; +enable_query_log; +# I have seen the slave crash either now or at shutdown +sync_slave_with_master; +connection master; +drop table t1; +drop table t2; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_function_defaults.test b/mysql-test/suite/rpl/t/rpl_function_defaults.test new file mode 100644 index 00000000..f2413299 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_function_defaults.test @@ -0,0 +1,86 @@ +--echo # +--echo # Test of function defaults on replicated tables. +--echo # + +source include/master-slave.inc; + +connection master; +SET TIME_ZONE="+10:30"; +SET TIMESTAMP=123456.789123; +SELECT CURRENT_TIMESTAMP; + +connection slave; +SET TIME_ZONE="+00:00"; +SET TIMESTAMP=987654321.123456; +SELECT CURRENT_TIMESTAMP; + +connection master; +CREATE TABLE t1 ( + a TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + b TIMESTAMP(1) NOT NULL DEFAULT CURRENT_TIMESTAMP(1), + c TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP(2), + d TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + e TIMESTAMP(4) NOT NULL DEFAULT CURRENT_TIMESTAMP(4), + f TIMESTAMP(5) NOT NULL DEFAULT CURRENT_TIMESTAMP(5), + g TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + h DATETIME DEFAULT CURRENT_TIMESTAMP, + i DATETIME(1) DEFAULT CURRENT_TIMESTAMP(1), + j DATETIME(2) DEFAULT CURRENT_TIMESTAMP(2), + k DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), + l DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4), + m DATETIME(5) DEFAULT CURRENT_TIMESTAMP(5), + n DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6), + o INT +); + +INSERT INTO t1 ( o ) VALUES ( 1 ); + +CREATE TABLE t2 ( + a TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + b TIMESTAMP(1) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(1), + c TIMESTAMP(2) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(2), + d TIMESTAMP(3) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(3), + e TIMESTAMP(4) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(4), + f TIMESTAMP(5) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(5), + g TIMESTAMP(6) NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP(6), + h DATETIME ON UPDATE CURRENT_TIMESTAMP, + i DATETIME(1) ON UPDATE CURRENT_TIMESTAMP(1), + j DATETIME(2) ON UPDATE CURRENT_TIMESTAMP(2), + k DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), + l DATETIME(4) ON UPDATE CURRENT_TIMESTAMP(4), + m DATETIME(5) ON UPDATE CURRENT_TIMESTAMP(5), + n DATETIME(6) ON UPDATE CURRENT_TIMESTAMP(6), + o INT +); + +INSERT INTO t2 ( o ) VALUES ( 1 ); + +--echo sync_slave_with_master +sync_slave_with_master; + +connection slave; + +query_vertical SELECT * FROM t1; +query_vertical SELECT * FROM t2; + +connection master; + +SET TIMESTAMP=1234567890.123456; +SELECT CURRENT_TIMESTAMP; + +UPDATE t1 SET o = 2; +UPDATE t2 SET o = 2; + +--echo sync_slave_with_master +sync_slave_with_master; + +connection slave; + +query_vertical SELECT * FROM t1; +query_vertical SELECT * FROM t2; + +connection master; + +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_geometry.test b/mysql-test/suite/rpl/t/rpl_geometry.test new file mode 100644 index 00000000..415732a0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_geometry.test @@ -0,0 +1,26 @@ +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +# +# Bug#48776, Bug#43784 +# +create table t1(a varchar(100), + b multipoint not null, + c varchar(256)); + +insert into t1 set + a='hello', + b=geomfromtext('multipoint(1 1)'), + c='geometry'; + +create table t2 (a int(11) not null auto_increment primary key, + b geometrycollection default null, + c decimal(10,0)); + +insert into t2(c) values (null); + +sync_slave_with_master; + +connection master; +drop table t1, t2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_get_lock.test b/mysql-test/suite/rpl/t/rpl_get_lock.test new file mode 100644 index 00000000..b5c08858 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_get_lock.test @@ -0,0 +1,47 @@ +source include/master-slave.inc; + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +create table t1(n int); +# Use of get_lock gives a warning for unsafeness if binlog_format=statement +--disable_warnings +insert into t1 values(get_lock("lock",2)); +--enable_warnings +dirty_close master; +connection master1; +select get_lock("lock",2); + +select release_lock("lock"); +#ignore +disable_query_log; +let $1=2000; +while ($1) +{ + do get_lock("lock",2); + do release_lock("lock"); + dec $1; +} +enable_query_log; +sync_slave_with_master; +select get_lock("lock",3); +select * from t1; +# There is no point in testing REPLICATIION of the IS_*_LOCK +# functions; slave does not run with the same concurrency context as +# master (generally in slave we can't know that on master this lock +# was already held by another connection and so that the the +# get_lock() we're replicating timed out on master hence returned 0, +# or that the is_free_lock() we're playing returned 0 etc. +# But here all we do is test these functions outside of replication. +select is_free_lock("lock"), is_used_lock("lock") = connection_id(); +explain extended select is_free_lock("lock"), is_used_lock("lock"); +# Check lock functions +select is_free_lock("lock2"); +select is_free_lock(NULL); +connection master1; +drop table t1; +sync_slave_with_master; + + +--source include/rpl_end.inc + +# End of 4.1 tests diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt new file mode 100644 index 00000000..f9aa8c03 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt @@ -0,0 +1 @@ +--master-retry-count=60 diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test new file mode 100644 index 00000000..02665c70 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test @@ -0,0 +1,50 @@ +# +# BUG#45214 +# This test verifies if the slave I/O tread tries to reconnect to +# master when it tries to get the values of the UNIX_TIMESTAMP, SERVER_ID, +# COLLATION_SERVER and TIME_ZONE from master under network disconnection. +# The COLLATION_SERVER and TIME_ZONE are got only on master server version 4. +# So they can't be verified by test case here. +# Finish the following tests by calling its common test script: +# include/rpl_get_master_version_and_clock.test. + +source include/have_debug.inc; +source include/have_debug_sync.inc; +source include/master-slave.inc; + +# +# The test is not supposed to have any binglog affairs. +# Hence it's enough it to run only with one binlog format +# +source include/have_binlog_format_mixed.inc; + +connection slave; + +call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*"); +call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'"); +call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); +call mtr.add_suppression("Slave I/O thread .* register on master"); + +#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection +SET @saved_dbug = @@GLOBAL.debug_dbug; + +# set up two parameters to pass into include/rpl_get_master_version_and_clock +let $dbug_sync_point= 'debug_lock.before_get_UNIX_TIMESTAMP'; +let $debug_sync_action= 'now SIGNAL signal.get_unix_timestamp'; +source include/rpl_get_master_version_and_clock.test; + +#Test case 2: Try to get the value of the SERVER_ID from master under network disconnection +connection slave; + +let $dbug_sync_point= 'debug_lock.before_get_SERVER_ID'; +let $debug_sync_action= 'now SIGNAL signal.get_server_id'; +source include/rpl_get_master_version_and_clock.test; + + +# cleanup +SET @@GLOBAL.debug_dbug = @saved_dbug; +# is not really necessary but avoids mtr post-run env check warnings +SET DEBUG_SYNC= 'RESET'; + +# End of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_grant.test b/mysql-test/suite/rpl/t/rpl_grant.test new file mode 100644 index 00000000..02206453 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_grant.test @@ -0,0 +1,37 @@ +# Tests of grants and users + +source include/not_embedded.inc; +source include/master-slave.inc; + +connection master; + +CREATE USER dummy@localhost; +CREATE USER dummy1@localhost, dummy2@localhost; + +SELECT user, host FROM mysql.user WHERE user like 'dummy%'; +SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; +sync_slave_with_master; +--echo **** On Slave **** +SELECT user,host FROM mysql.user WHERE user like 'dummy%'; +SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; + +connection master; + +# No user exists +error ER_CANNOT_USER; +DROP USER nonexisting@localhost; + +# At least one user exists, but not all +error ER_CANNOT_USER; +DROP USER nonexisting@localhost, dummy@localhost; + +# All users exist +DROP USER dummy1@localhost, dummy2@localhost; + +SELECT user, host FROM mysql.user WHERE user like 'dummy%'; +SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; +sync_slave_with_master; +SELECT user,host FROM mysql.user WHERE user like 'dummy%'; +SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf b/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf new file mode 100644 index 00000000..3ff94e45 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.cnf @@ -0,0 +1,24 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[mysqld.4] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test new file mode 100644 index 00000000..004003ea --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -0,0 +1,36 @@ +--source include/rpl_gtid_basic.inc + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-10134 Add full support for DEFAULT +--echo # + +--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED +CREATE TABLE t1 (a VARCHAR(100) DEFAULT BINLOG_GTID_POS("master-bin.000001", 600)); + +--echo # +--echo # End of 10.2 tests +--echo # + + +--echo # +--echo # Start of 10.3 tests +--echo # + +--echo # +--echo # MDEV-13967 Parameter data type control for Item_long_func +--echo # + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT MASTER_GTID_WAIT(ROW(1,1),'str'); + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT MASTER_GTID_WAIT('str',ROW(1,1)); + + +--echo # +--echo # End of 10.3 tests +--echo # diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt new file mode 100644 index 00000000..590d44a6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash-master.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --skip-core-file diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt new file mode 100644 index 00000000..69c1a64e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt @@ -0,0 +1 @@ +--master-retry-count=100 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test new file mode 100644 index 00000000..d0af69a6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test @@ -0,0 +1,668 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test crashing master, causing slave IO thread to reconnect while SQL thread is running *** + +--connection server_1 +call mtr.add_suppression("Checking table:"); +call mtr.add_suppression("client is using or hasn't closed the table properly"); +call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); +flush tables; + +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); +--save_master_pos + +--connection server_2 +--sync_with_master +SET sql_log_bin=0; +call mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again'); +SET sql_log_bin=1; +--source include/stop_slave.inc +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_USE_GTID=CURRENT_POS; + +--connection server_1 +INSERT INTO t1 VALUES (2,1); +INSERT INTO t1 VALUES (3,1); + +--connection server_2 +--source include/start_slave.inc + +--connection server_1 + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-rpl_gtid_crash.test +EOF + +let $1=200; +--disable_query_log +while ($1) +{ + eval INSERT INTO t1 VALUES ($1 + 10, 2); + dec $1; +} +--enable_query_log +--source include/save_master_gtid.inc + +SET SESSION debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +SELECT 1; +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-rpl_gtid_crash.test +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +--connection server_1 +INSERT INTO t1 VALUES (1000, 3); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +--connection server_1 +DROP TABLE t1; +--save_master_pos + +--echo *** Test crashing the master mysqld and check that binlog state is recovered. *** +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +RESET MASTER; +SET GLOBAL gtid_slave_pos=''; + +--connection server_1 +RESET MASTER; +--replace_column 2 # 4 # 5 # +SHOW BINLOG EVENTS IN 'master-bin.000001' LIMIT 1,1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; + +--connection server_2 +--source include/start_slave.inc + +--connection server_1 +SET gtid_domain_id= 1; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +FLUSH LOGS; +SET gtid_domain_id= 2; +INSERT INTO t1 VALUES (3); +FLUSH LOGS; +--source include/show_binary_logs.inc +--replace_column 2 # 4 # 5 # 6 # +SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET SESSION debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +SELECT 1; +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/show_binary_logs.inc +--replace_column 2 # 4 # 5 # 6 # +SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1; +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test crashing slave at various points and check that it recovers crash-safe. *** + +# Crash the slave just before updating mysql.gtid_slave_pos table. +--source include/stop_slave.inc +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +# We do not have to save @@GLOBAL.debug_dbug, it is reset when slave crashes. +SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state"; +START SLAVE; + +--connection server_1 +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc + +# Crash the slave just before committing. +--source include/stop_slave.inc +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +START SLAVE; +--error 0,2006,2013 +SET GLOBAL debug_dbug="+d,crash_commit_before"; + +--connection server_1 +INSERT INTO t1 VALUES (5); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc + +# Crash the slave just after committing. +--source include/stop_slave.inc +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +START SLAVE; +--error 0,2006,2013 +SET GLOBAL debug_dbug="+d,crash_commit_after"; + +--connection server_1 +INSERT INTO t1 VALUES (6); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc + +# Crash the slave just before updating relay-log.info +--source include/stop_slave.inc +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli"; +--error 0,2006,2013 +START SLAVE; + +--connection server_1 +INSERT INTO t1 VALUES (7); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc + +# Crash the slave just after updating relay-log.info +--source include/stop_slave.inc +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli"; +--error 0,2006,2013 +START SLAVE; + +--connection server_1 +INSERT INTO t1 VALUES (8); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc + + +# Check that everything was replicated correctly. +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4725: Incorrect recovery when crash in the middle of writing an event group *** + +--connection server_2 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF + +--let $old_gtid_strict= `SELECT @@gtid_strict_mode` +SET GLOBAL debug_dbug="+d,crash_before_writing_xid"; + +--connection server_1 +INSERT INTO t1 VALUES (9), (10); +--let $saved_gtid=`SELECT @@last_gtid` +--save_master_pos + +--connection server_2 +--source include/wait_until_disconnected.inc + +# The bug was that during crash recovery we would update the binlog state +# with the GTID of the half-written event group at the end of the slaves +# binlog, even though this event group was not committed. +# We restart the server with gtid_strict_mode; this way, we get an error +# about duplicate gtid when the slave re-executes the event group, if the +# binlog crash recovery is incorrect. +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --gtid_strict_mode=1 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +SHOW VARIABLES like 'gtid_strict_mode'; +--source include/start_slave.inc +--sync_with_master +--disable_query_log +eval SET GLOBAL gtid_strict_mode= $old_gtid_strict; +--enable_query_log + + +--echo *** MDEV-6462: Incorrect recovery on a slave reconnecting to crashed master *** + +--connection server_1 +set sql_log_bin= 0; +call mtr.add_suppression("Error writing file 'master-bin'"); +set sql_log_bin= 1; +--connection server_2 +set sql_log_bin= 0; +call mtr.add_suppression("The server_id of master server changed in the middle of GTID"); +call mtr.add_suppression("Unexpected change of master binlog file name in the middle of GTID"); +set sql_log_bin= 1; + +--connection server_1 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL debug_dbug="+d,inject_error_writing_xid"; +BEGIN; +INSERT INTO t1 VALUES (11); +--error ER_ERROR_ON_WRITE +COMMIT; +SET GLOBAL debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +COMMIT; + +--source include/wait_until_disconnected.inc + +# Simulate that we reconnect to a different server (new server_id). +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart: --server-id=3 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +SELECT @@GLOBAL.server_id; +SELECT * from t1 WHERE a > 10 ORDER BY a; +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log + +--echo # Wait 30 seconds for SQL thread to catch up with IO thread +--connection server_2 +--let $wait_timeout= 300 +while ($wait_timeout != 0) +{ + --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1) + --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1) + if ($read_log_pos == $exec_log_pos) + { + --let $wait_timeout= 0 + } + if ($read_log_pos != $exec_log_pos) + { + --sleep 0.1 + --dec $wait_timeout + } +} +if ($read_log_pos != $exec_log_pos) +{ + --die Timeout wait for SQL thread to catch up with IO thread +} + +SELECT * from t1 WHERE a > 10 ORDER BY a; +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log + +--echo # Repeat this with additional transactions on the master + +--connection server_1 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL debug_dbug="+d,inject_error_writing_xid"; +BEGIN; +INSERT INTO t1 VALUES (12); +--error ER_ERROR_ON_WRITE +COMMIT; +SET GLOBAL debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +COMMIT; + +--source include/wait_until_disconnected.inc + +# Simulate that we reconnect to a different server (new server_id). +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart: --server-id=1 +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +SELECT @@GLOBAL.server_id; +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +--let $saved_gtid=`SELECT @@last_gtid` +SELECT * from t1 WHERE a > 10 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +SELECT * from t1 WHERE a > 10 ORDER BY a; + +--connection server_1 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL debug_dbug="+d,inject_error_writing_xid"; +BEGIN; +INSERT INTO t1 VALUES (21); +--error ER_ERROR_ON_WRITE +COMMIT; +SET GLOBAL debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +COMMIT; + +--source include/wait_until_disconnected.inc + +# Simulate that we reconnect to the same server (same server_id). +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +SELECT @@GLOBAL.server_id; +SELECT * from t1 WHERE a > 10 ORDER BY a; +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log + +--echo # Wait 30 seconds for SQL thread to catch up with IO thread +--connection server_2 +--let $wait_timeout= 300 +while ($wait_timeout != 0) +{ + --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1) + --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1) + if ($read_log_pos == $exec_log_pos) + { + --let $wait_timeout= 0 + } + if ($read_log_pos != $exec_log_pos) + { + --sleep 0.1 + --dec $wait_timeout + } +} +if ($read_log_pos != $exec_log_pos) +{ + --die Timeout wait for SQL thread to catch up with IO thread +} + +SELECT * from t1 WHERE a > 10 ORDER BY a; +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log + +--echo # Repeat this with additional transactions on the master + +--connection server_1 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL debug_dbug="+d,inject_error_writing_xid"; +BEGIN; +INSERT INTO t1 VALUES (22); +--error ER_ERROR_ON_WRITE +COMMIT; +SET GLOBAL debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +COMMIT; + +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (23); +INSERT INTO t1 VALUES (24); +--let $saved_gtid=`SELECT @@last_gtid` +SELECT * from t1 WHERE a > 10 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +SELECT * from t1 WHERE a > 10 ORDER BY a; + +--echo # Repeat this with slave restart + +--connection server_1 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +SET GLOBAL debug_dbug="+d,inject_error_writing_xid"; +BEGIN; +INSERT INTO t1 VALUES (25); +--error ER_ERROR_ON_WRITE +COMMIT; +SET GLOBAL debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +COMMIT; + +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_2 +--echo # Wait 30 seconds for IO thread to connect and SQL thread to catch up +--echo # with IO thread. +--let $wait_timeout= 300 +while ($wait_timeout != 0) +{ + --let $connected=`SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE State = 'Waiting for master to send event'` + if ($connected) + { + --let $read_log_pos= query_get_value('SHOW SLAVE STATUS', Read_Master_Log_Pos, 1) + --let $exec_log_pos= query_get_value('SHOW SLAVE STATUS', Exec_Master_Log_Pos, 1) + if ($read_log_pos == $exec_log_pos) + { + --let $wait_timeout= 0 + } + if ($read_log_pos != $exec_log_pos) + { + --sleep 0.1 + --dec $wait_timeout + } + } + if (!$connected) + { + --sleep 0.1 + --dec $wait_timeout + } +} +if (`SELECT NOT $connected OR $read_log_pos != $exec_log_pos`) +{ + --die Timeout wait for IO thread to connect and SQL thread to catch up with IO thread +} + +--source include/stop_slave.inc + +--connection server_1 +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log +INSERT INTO t1 VALUES (26); +INSERT INTO t1 VALUES (27); +SELECT * from t1 WHERE a > 10 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--disable_query_log +eval SELECT IF(INSTR(@@gtid_binlog_pos, '$saved_gtid'), "Binlog pos ok", CONCAT("Unexpected binlog pos: ", @@gtid_binlog_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_slave_pos, '$saved_gtid'), "Slave pos ok", CONCAT("Unexpected slave pos: ", @@gtid_slave_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +eval SELECT IF(INSTR(@@gtid_current_pos, '$saved_gtid'), "Current pos ok", CONCAT("Unexpected current pos: ", @@gtid_current_pos, "; does not contain the GTID $saved_gtid.")) AS gtid_check; +--enable_query_log +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * from t1 WHERE a > 10 ORDER BY a; + + +--echo *** MDEV-6391: GTID binlog state not recovered if mariadb-bin.state is removed *** + +--connection server_2 +--source include/stop_slave.inc + +# Do some misc. transactions, stop the master, drop the master-bin.state file. +# Start the master back up, check that binlog state is correct. + +--connection server_1 + +INSERT INTO t1 VALUES (30); +SET @old_server_id= @@server_id; +SET @old_domain_id= @@gtid_domain_id; + +SET SESSION server_id= 10; +INSERT INTO t1 VALUES (31); +INSERT INTO t1 VALUES (32); +SET SESSION gtid_domain_id= 1; +SET SESSION server_id=11; +INSERT INTO t1 VALUES (33); +SET SESSION gtid_domain_id= 2; +INSERT INTO t1 VALUES (34); +SET SESSION server_id= 10; +INSERT INTO t1 VALUES (35); +INSERT INTO t1 VALUES (36); +SET SESSION gtid_domain_id= 0; +SET SESSION server_id= 12; +INSERT INTO t1 VALUES (37); +SET SESSION gtid_domain_id= @old_domain_id; +SET SESSION server_id= @old_server_id; +INSERT INTO t1 VALUES (38); +INSERT INTO t1 VALUES (39); +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +--source include/save_master_gtid.inc + +--let OLD_STATE= `SELECT @@gtid_binlog_state` + +--let $datadir= `SELECT @@datadir` + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF +shutdown_server; +--source include/wait_until_disconnected.inc + +--remove_file $datadir/master-bin.state + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--let NEW_STATE= `SELECT @@gtid_binlog_state` + +--perl +my $old= $ENV{'OLD_STATE'}; +my $new= $ENV{'NEW_STATE'}; +# Make them order-independent, for easy comparison. +$old= join(",", sort(split(",", $old))); +$new= join(",", sort(split(",", $new))); +die "ERROR: new binlog state '$new' differs from old '$old'\n" + unless $old eq $new; +EOF + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + + +--connection server_1 +DROP TABLE t1; + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt new file mode 100644 index 00000000..16d8af5b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam-master.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --skip-core-file --skip-innodb diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test new file mode 100644 index 00000000..faf388f5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test @@ -0,0 +1,64 @@ +--source include/have_debug.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test crashing master with InnoDB disabled, the binlog gtid state should still be correctly recovered. *** + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=MyISAM; +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--connection server_1 + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +FLUSH TABLES; +SET SESSION debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +SELECT 1; + +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-rpl_gtid_crash.test +EOF + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (3); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--connection server_1 +DROP TABLE t1; + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test new file mode 100644 index 00000000..5537b6fb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test @@ -0,0 +1,101 @@ +# In case master's gtid binlog state is divergent from the slave's gtid_slave_pos +# slave may not be able to connect. +# For instance when slave is more updated in some of domains, see +# MDEV-12012 as example, the master's state may require adjustment. +# In a specific case of an "old" divergent domain, that is there +# won't be no more event groups from it generated, the states can be +# made compatible with wiping the problematic domain away. After that slave +# becomes connectable. +# +# Notice that the slave applied gtid state is not really required to +# be similarly cleaned in order for replication to flow. +# However this could lead to an expected error when the master +# resumes binlogging of such domain which the test demonstrate. + +--source include/master-slave.inc + +--connection master +# enforce the default domain_id binlogging explicitly +SET @@SESSION.gtid_domain_id=0; +CREATE TABLE t (a INT); +--sync_slave_with_master + +--connection slave +call mtr.add_suppression("connecting slave requested to start from.*which is not in the master's binlog"); + +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; + +--connection master +# create extra gtid domains for binlog state +--let $extra_domain_id=11 +--let $extra_domain_server_id=111 +--let $extra_gtid_seq_no=1 +--eval SET @@SESSION.gtid_domain_id=$extra_domain_id +--eval SET @@SESSION.server_id=$extra_domain_server_id +--eval SET @@SESSION.gtid_seq_no=$extra_gtid_seq_no +INSERT INTO t SET a=1; + +# +# Set up the slave replication state as if slave knows more events from the extra +# domain. +# +--connection slave +SET @save.gtid_slave_pos=@@global.gtid_slave_pos; +--eval SET @@global.gtid_slave_pos=concat(@@global.gtid_slave_pos, ",", $extra_domain_id, "-", $extra_domain_server_id, "-", $extra_gtid_seq_no + 1) + +# unsuccessful attempt to start slave +START SLAVE IO_THREAD; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc + +--connection master +# adjust the master binlog state +FLUSH BINARY LOGS; +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--let $purge_binlogs_to=$purge_to_binlog +--source include/wait_for_purge.inc + +# with final removal of the extra domain +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id) +SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state; + +--connection slave +SELECT @@global.gtid_slave_pos; +# start the slave sucessfully +--let rpl_debug=1 +--source include/start_slave.inc +--let rpl_debug=0 + +--connection master +# but the following gtid from the *extra* domain will break replication +INSERT INTO t SET a=1; + +# take note of the slave io thread error due to being dismissed +# extra domain at connection to master which tried becoming active; +# slave is to stop. +--connection slave +--let $errno=1236 +--source include/wait_for_slave_io_error.inc + +# let's apply the very same medicine +--connection master +FLUSH BINARY LOGS; +--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +--eval PURGE BINARY LOGS TO '$purge_to_binlog'; +# with final removal of the extra domain +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id) + +--connection slave +--source include/start_slave.inc + +# +# cleanup +# +--connection master +SET @@SESSION.gtid_domain_id=0; +DROP TABLE t; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test new file mode 100644 index 00000000..c02e2670 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorhandling.test @@ -0,0 +1,290 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--echo *** Test that we check against incorrect table definition for mysql.gtid_slave_pos *** +--connection master +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +--sync_slave_with_master + +--connection slave +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no VARCHAR(20); +START SLAVE; + +--connection master +INSERT INTO t1 VALUES (1); + +--connection slave +CALL mtr.add_suppression("Slave: Failed to open mysql.gtid_slave_pos"); +--let $slave_sql_errno=1944 +--source include/wait_for_slave_sql_error.inc + +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos CHANGE seq_no seq_no BIGINT UNSIGNED NOT NULL; +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id, domain_id); +START SLAVE; +--let $slave_sql_errno=1944 +--source include/wait_for_slave_sql_error.inc + +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +START SLAVE; +--let $slave_sql_errno=1944 +--source include/wait_for_slave_sql_error.inc + +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (sub_id); +START SLAVE; +--let $slave_sql_errno=1944 +--source include/wait_for_slave_sql_error.inc + +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos DROP PRIMARY KEY; +ALTER TABLE mysql.gtid_slave_pos ADD PRIMARY KEY (domain_id, sub_id); +--source include/start_slave.inc + +--connection master +--sync_slave_with_master + +--connection slave +SELECT * FROM t1; + + +--echo *** Test that setting @@gtid_domain_id or @@gtid_seq_no is not allowed inside a transaction. *** +BEGIN; +INSERT INTO t1 VALUES (100); +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO +SET SESSION gtid_domain_id= 100; +--error ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO +SET SESSION gtid_seq_no= 100; +SET @old_domain= @@GLOBAL.gtid_domain_id; +SET GLOBAL gtid_domain_id= 100; +SELECT @@SESSION.gtid_domain_id; +SET GLOBAL gtid_domain_id= @old_domain; +INSERT INTO t1 VALUES (101); +SELECT * FROM t1 ORDER BY a; +ROLLBACK; +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test requesting an explicit GTID position that conflicts with newer GTIDs of our own in the binlog. *** +--connection slave +--source include/stop_slave.inc + +--connection master +RESET MASTER; +# This insert will be GTID 0-1-1 +INSERT INTO t1 VALUES (2); +# And this will be GTID 0-1-2 +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection slave +SET sql_log_bin = 0; +INSERT INTO t1 VALUES (2); +SET sql_log_bin = 1; +INSERT INTO t1 VALUES (3); + +CHANGE MASTER TO master_use_gtid=current_pos; +# Most not change @@GLOBAL.gtid_slave_pos in the middle of a transaction. +BEGIN; +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL gtid_slave_pos = "100-100-100"; +INSERT INTO t1 VALUES (100); +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET GLOBAL gtid_slave_pos = "100-100-100"; +ROLLBACK; + +# In gtid non-strict mode, we get warnings for setting @@gtid_slave_pos back +# to earlier than what is in the binlog. In strict mode, we get an error. +SET GLOBAL gtid_strict_mode= 1; +--error ER_MASTER_GTID_POS_CONFLICTS_WITH_BINLOG +SET GLOBAL gtid_slave_pos = "0-1-1"; +--error ER_MASTER_GTID_POS_MISSING_DOMAIN +SET GLOBAL gtid_slave_pos = ""; +SET GLOBAL gtid_strict_mode= 0; +SET GLOBAL gtid_slave_pos = "0-1-1"; +SET GLOBAL gtid_slave_pos = ""; +RESET MASTER; +SET GLOBAL gtid_slave_pos = "0-1-1"; + +START SLAVE; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--echo *** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos *** +# The problem was that record_gtid() deleted too much of the in-memory state, +# leaving the state empty until after commit when we add the newly committed +# GTID. Test this by forcing an error after the delete of the old data but +# before the add of new data. + +--source include/stop_slave.inc + +--connection master +# This will be GTID 0-1-3 +INSERT INTO t1 VALUES (5); +--source include/save_master_gtid.inc + +--connection slave +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output"; +SET GLOBAL debug_dbug="+d,gtid_fail_after_record_gtid"; +SET sql_log_bin=0; +CALL mtr.add_suppression('Got error 131 "Command not supported by the engine" during COMMIT'); +SET sql_log_bin=1; +START SLAVE; +--let $slave_sql_errno= 1180 +--source include/wait_for_slave_sql_error.inc +# The bug was that @@GLOBAL.gtid_slave_pos was empty here. +SELECT @@GLOBAL.gtid_slave_pos; +SELECT * FROM t1 ORDER BY a; +SET GLOBAL debug_dbug= @old_dbug; +START SLAVE SQL_THREAD; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test slave requesting a GTID that is not present in the master's binlog *** +--source include/stop_slave.inc +SET GLOBAL gtid_slave_pos = "0-1-4"; +START SLAVE; + +SET sql_log_bin=0; +CALL mtr.add_suppression("Got fatal error .* from master when reading data from binary log: 'Error: connecting slave requested to start from GTID .*, which is not in the master's binlog'"); +SET sql_log_bin=1; +--let $slave_io_errno= 1236 +--source include/wait_for_slave_io_error.inc +--let $status_items= Slave_IO_State, Last_IO_Errno, Last_IO_Error, Using_Gtid +--source include/show_slave_status.inc + +--let $rpl_only_running_threads= 1 +--source include/stop_slave.inc +SET GLOBAL gtid_slave_pos = "0-1-3"; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +--connection master +INSERT INTO t1 VALUES (6); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4278: Slave does not detect that master is not GTID-aware *** + +--connection slave +--source include/stop_slave.inc + +--connection master +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,simulate_non_gtid_aware_master"; + +--connection slave +START SLAVE; +--let $slave_io_errno= 1233 +--source include/wait_for_slave_io_error.inc + +--connection master +SET GLOBAL debug_dbug= @old_dbug; +INSERT INTO t1 VALUES (7); +--save_master_pos + +--connection slave +START SLAVE; +--sync_with_master +SET sql_log_bin=0; +CALL mtr.add_suppression("The slave I/O thread stops because master does not support MariaDB global transaction id"); +SET sql_log_bin=1; + + +--echo *** Test error during record_gtid() (non-xid cases) *** + +--connection slave +--source include/stop_slave.inc + +--connection master +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1); +--save_master_pos + +--connection slave +SET @old_dbug= @@global.DEBUG_DBUG; +SET GLOBAL debug_dbug="+d,gtid_inject_record_gtid"; + +START SLAVE; +--let $slave_sql_errno= 1942 +--source include/wait_for_slave_sql_error.inc + +SET GLOBAL debug_dbug= @old_dbug; + +START SLAVE SQL_THREAD; +--sync_with_master + +SELECT * FROM t2; +SET sql_log_bin=0; +CALL mtr.add_suppression("Slave: Could not update replication slave gtid state"); +SET sql_log_bin=1; + + +--echo *** MDEV-4906: When event apply fails, next SQL thread start erroneously commits the failing GTID to gtid_slave_pos *** + +--connection slave +--source include/stop_slave.inc +SET sql_log_bin=0; +DELETE FROM t2; +SET sql_log_bin=1; +SET @old_format=@@binlog_format; +SET GLOBAL binlog_format='row'; +--source include/start_slave.inc + +--connection master +SET @old_format=@@binlog_format; +SET binlog_format='row'; +--let $gtid_pos1=`SELECT @@GLOBAL.gtid_binlog_pos` +DELETE FROM t2; +SET binlog_format=@old_format; +--save_master_pos + +--connection slave +--let $slave_sql_errno= 1032 +--source include/wait_for_slave_sql_error.inc +# Disable query to avoid result file update if precise GTID value changes. +--disable_query_log +SET @x=@@GLOBAL.gtid_slave_pos; +eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result; +--enable_query_log + +# The bug was that upon restarting the SQL thread, the GTID for the +# failing event group was not cleared, so we would update it in the +# gtid_slave_pos as part of the first rotate event, corrupting the +# replication. +STOP SLAVE IO_THREAD; +START SLAVE; +--let $slave_sql_errno= 1032 +--source include/wait_for_slave_sql_error.inc +# Disable query to avoid result file update if precise GTID value changes. +--disable_query_log +SET @x=@@GLOBAL.gtid_slave_pos; +eval SELECT IF(@x='$gtid_pos1', "OK", CONCAT("ERROR: expected $gtid_pos1 got ", @x)) AS result; +--enable_query_log + +STOP SLAVE IO_THREAD; +SET sql_log_bin=0; +INSERT INTO t2 VALUES (1); +CALL mtr.add_suppression("Slave: Can't find record in 't2' Error_code: 1032"); +SET sql_log_bin=1; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL binlog_format=@old_format; + +--connection master +DROP TABLE t1; +DROP TABLE t2; + +call mtr.add_suppression("Can't find record in 't2'"); + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test new file mode 100644 index 00000000..ea321062 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test @@ -0,0 +1,85 @@ +--source include/have_debug.inc +--source include/master-slave.inc + +connection master; +SET GLOBAL BINLOG_CHECKSUM=NONE; +connection slave; +SET GLOBAL BINLOG_CHECKSUM=NONE; + +--echo *** Test MDEV-6120, output of current GTID when a replication error is logged to the errorlog *** +--connection master +CREATE TABLE t1(a INT PRIMARY KEY); +--sync_slave_with_master + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; + +--connection master +INSERT INTO t1 VALUES (1); +SET gtid_seq_no=100; +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +--save_master_pos + +--connection slave +SET sql_log_bin=0; +INSERT INTO t1 VALUES (2); +SET sql_log_bin=1; + +START SLAVE; +--let $slave_sql_errno=1062 +--source include/wait_for_slave_sql_error.inc + +--source include/stop_slave.inc +# Skip the problem event from the master. +SET GLOBAL gtid_slave_pos= "0-1-100"; +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t1 ORDER BY a; + +--connection master + +SET @dbug_save= @@debug_dbug; +SET debug_dbug= '+d,incident_database_resync_on_replace'; +REPLACE INTO t1 VALUES (5); +SET debug_dbug= @dbug_save; +--save_master_pos + +--connection slave +--let $slave_sql_errno=1590 +--source include/wait_for_slave_sql_error.inc +--source include/stop_slave.inc +SET sql_slave_skip_counter=1; +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t1 ORDER BY a; + + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Slave SQL: Error 'Duplicate entry .* on query\. .*Query: '.*', Gtid 0-1-100, Internal MariaDB error code:|Slave SQL: Could not execute Write_rows.*table test.t1; Duplicate entry.*, Gtid 0-1-100, Internal MariaDB error +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: <none>, Internal MariaDB error code: 1590 +--source include/search_pattern_in_file.inc + + +--connection master +DROP TABLE t1; + +connection master; +SET GLOBAL BINLOG_CHECKSUM=default; +connection slave; +SET GLOBAL BINLOG_CHECKSUM=default; +connection master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test b/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test new file mode 100644 index 00000000..d840b67e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_excess_initial_delay.test @@ -0,0 +1,58 @@ +# ==== Purpose ==== +# +# Test verifies that when "Master_Delay" is specified on slave with GTIDS there +# will not be any extra delay initially. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Stop the slave and execute CHANGE MASTER command with +# master_use_gtid= curren_pos and master_delay= 10 +# 1 - On slave introduce a sleep of 15 seconds and check that the +# Seconds_Behind_Master is within specified master_delay limit. It should +# not be more that "10" seconds. +# +# ==== References ==== +# +# MDEV-13895: GTID and Master_Delay causes excessive initial delay + +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +CREATE TABLE t1 (i INT); +--sync_slave_with_master + +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_USE_GTID= current_pos, MASTER_DELAY= 10; +--source include/start_slave.inc + +--connection master +INSERT INTO t1 VALUES (1); +--source include/sync_slave_io_with_master.inc + +--connection slave +--let $actual_delay= query_get_value(SHOW SLAVE STATUS, SQL_Delay, 1) +--let $sleep_time= `SELECT 5 + $actual_delay` +--echo "Sleeping for $sleep_time" +--sleep $sleep_time + +--let $assert_cond= [SHOW SLAVE STATUS, Seconds_Behind_Master, 1] <= 10 +--let $assert_text= Seconds_Behind_Master should be less than MASTER_DELAY +--source include/rpl_assert.inc + +# The row should be available in table after master_delay=20 seconds. +--let $assert_text= One row shoule be found in table t1. +--let $assert_cond= COUNT(*) = 1 FROM t1 +--source include/rpl_assert.inc + +--echo "======= Clean up ========" +STOP SLAVE; +CHANGE MASTER TO MASTER_USE_GTID=no, MASTER_DELAY=0; +START SLAVE; + +--connection master +DROP TABLE t1; +--sync_slave_with_master + +--connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_ignored.test b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test new file mode 100644 index 00000000..3c1324b2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test @@ -0,0 +1,141 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; + +--connection server_2 +--source include/stop_slave.inc +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode=1; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master + +--echo **** MDEV-4488: GTID position should be updated for events that are ignored due to server id *** +--source include/stop_slave.inc +CHANGE MASTER TO ignore_server_ids=(1); +--source include/start_slave.inc + +--connection server_1 +# These inserts should be ignored (not applied) on the slave, but the +# gtid_slave_pos should still be updated. +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +--save_master_pos +--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos` + +--connection server_2 +--sync_with_master +--let $wait_condition= SELECT @@GLOBAL.gtid_slave_pos = '$gtid_pos' +--source include/wait_condition.inc +--disable_query_log +eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT; +--enable_query_log + +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +CHANGE MASTER TO ignore_server_ids=(); +--source include/start_slave.inc +--sync_with_master +--disable_query_log +eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT; +--enable_query_log + +SELECT * FROM t1 ORDER BY a; + +--connection server_1 +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos` +--save_master_pos + +--connection server_2 +--sync_with_master +--disable_query_log +eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT; +SELECT * FROM t1 ORDER BY a; +--enable_query_log + + +--echo *** Test the same thing when IO thread exits before SQL thread reaches end of log. *** +--connection server_2 +--source include/stop_slave.inc +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug= "+d,inject_slave_sql_before_apply_event"; +CHANGE MASTER TO ignore_server_ids=(1); +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +--let gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos` +--save_master_pos + +--connection server_2 +# Wait for IO thread to have read all events from master, and for SQL thread to +# sit in the debug_sync point. + +--let $slave_param= Read_Master_Log_Pos +--let $slave_param_value= $master_pos +--source include/wait_for_slave_param.inc + +# Now stop the IO thread, and let the SQL thread continue. The IO thread +# should write a Gtid_list event that the SQL thread can use to update the +# gtid_slave_pos with the GTIDs of the skipped events. +STOP SLAVE IO_THREAD; +SET debug_sync = "now SIGNAL continue"; + +--sync_with_master +--let $wait_condition= SELECT @@GLOBAL.gtid_slave_pos = '$gtid_pos' +--source include/wait_condition.inc +--disable_query_log +eval SELECT IF(@@GLOBAL.gtid_slave_pos = '$gtid_pos', 'OK', CONCAT("ERROR: Expected $gtid_pos got ", @@GLOBAL.gtid_slave_pos)) AS RESULT; +--let $slave_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +eval SELECT IF('$slave_pos' = '$master_pos', 'OK', "ERROR: Expected $master_pos got $slave_pos") AS RESULT; +--enable_query_log + + +--source include/stop_slave.inc +CHANGE MASTER TO ignore_server_ids=(); +SET GLOBAL debug_dbug= @old_dbug; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Clean up. +--connection server_1 +DROP TABLE t1; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +SET debug_sync = "reset"; + +--connection server_2 +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +SET debug_sync = "reset"; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf new file mode 100644 index 00000000..4eafa897 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.cnf @@ -0,0 +1,35 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.3] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.4] +log-slave-updates +skip-slave-start +loose-innodb + +[mysqld.5] +log-slave-updates +skip-slave-start +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket + +SERVER_MYPORT_5= @mysqld.5.port +SERVER_MYSOCK_5= @mysqld.5.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test new file mode 100644 index 00000000..bd5343d7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_master_promote.test @@ -0,0 +1,270 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2, 1->3, 1->4, 1->5 +--source include/rpl_init.inc + +# Set up a topology with one master and 4 slaves. +# +# Replicate some events leaving the four slaves at different points +# in different domains. +# +# Then promote one slave as new master, bringing it ahead of all others +# using START SLAVE UNTIL master_gtid_pos. + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t4 (a INT, b INT, PRIMARY KEY (a,b)) Engine=InnoDB; + +# Function to extract one GTID from a list. +delimiter |; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) + RETURNS VARCHAR(100) DETERMINISTIC +BEGIN + SET s= CONCAT(",", s, ","); + SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); + SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); + RETURN s; +END| +delimiter ;| + +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_3 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_4 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_5 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=current_pos; + + +# Create three separate replication streams on master server_1. +# +# Then use START SLAVE UNTIL to get the different streams interleaved +# differently spread over multiple binlogs on the different slaves, to +# test that new master promotion is able to deal with this. + +--connection server_1 + +SET gtid_domain_id= 1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d1_begin= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t4 VALUES (1, 1); +--let $d1_mid= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t4 VALUES (1, 3); +--let $d1_end= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` + +SET gtid_domain_id= 2; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d2_begin= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t4 VALUES (2, 1); +--let $d2_mid= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t2 VALUES (3); +INSERT INTO t2 VALUES (4); +INSERT INTO t4 VALUES (2, 3); +--let $d2_end= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` + +SET gtid_domain_id= 3; +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=InnoDB; +--let $d3_begin= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +INSERT INTO t4 VALUES (3, 1); +--let $d3_mid= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` +INSERT INTO t3 VALUES (3); +INSERT INTO t3 VALUES (4); +INSERT INTO t4 VALUES (3, 3); +--let $d3_end= `SELECT extract_gtid("3", @@GLOBAL.gtid_binlog_pos)` + + +# Slave server_2 (that will be promoted to master) is in the middle +# of each stream. +--connection server_2 +eval START SLAVE UNTIL master_gtid_pos= "$d1_mid,$d2_mid,$d3_mid"; + +# The remaining slaves sit at different points each in different domains. +--connection server_3 +eval START SLAVE UNTIL master_gtid_pos= "$d1_begin,$d2_mid,$d3_end"; +--connection server_4 +eval START SLAVE UNTIL master_gtid_pos= "$d2_begin,$d3_mid,$d1_end"; +--connection server_5 +eval START SLAVE UNTIL master_gtid_pos= "$d3_begin,$d1_mid,$d2_end"; +--connection server_2 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_3 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_4 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Now replicate all extra changes from 3,4,5 to 2, in preparation for making 2 the new master. *** + +--connection server_3 +--let $server3_pos= `SELECT @@GLOBAL.gtid_slave_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3; +--replace_result $server3_pos SERVER3_POS +eval START SLAVE UNTIL master_gtid_pos = "$server3_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--connection server_4 +--let $server4_pos= `SELECT @@GLOBAL.gtid_slave_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4; +--replace_result $server4_pos SERVER4_POS +eval START SLAVE UNTIL master_gtid_pos = "$server4_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--connection server_5 +--let $server5_pos= `SELECT @@GLOBAL.gtid_slave_pos` +--connection server_2 +--replace_result $SERVER_MYPORT_5 SERVER_MYPORT_5 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_5; +--replace_result $server5_pos SERVER5_POS +eval START SLAVE UNTIL master_gtid_pos = "$server5_pos"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + +--echo *** Now make 2 master and point 3,4,5 to the new master 2 +--connection server_2 +SET gtid_domain_id= 1; +INSERT INTO t1 values (5); +INSERT INTO t4 values (1,5); +SET gtid_domain_id= 2; +INSERT INTO t2 values (5); +INSERT INTO t4 values (2,5); +SET gtid_domain_id= 3; +INSERT INTO t3 values (5); +INSERT INTO t4 values (3,5); + +--connection server_3 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc +--connection server_4 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc +--connection server_5 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2; +--source include/start_slave.inc + +--connection server_2 +--save_master_pos + +--connection server_3 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; +--connection server_5 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Now let the old master join up as slave. *** +--connection server_1 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + master_user = "root", master_use_gtid = current_pos; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a,b; + + +--echo *** Finally move things back and clean up. *** +--connection server_1 +--source include/stop_slave.inc +RESET SLAVE ALL; + +--connection server_2 +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_3 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_4 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc +--connection server_5 +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1; +--source include/start_slave.inc + +--connection server_1 +SET gtid_domain_id = 0; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE t4; +DROP FUNCTION extract_gtid; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf new file mode 100644 index 00000000..4fe90e6a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.cnf @@ -0,0 +1,18 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test new file mode 100644 index 00000000..01259eb5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4473.test @@ -0,0 +1,72 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc + +--let $rpl_topology=1->2,1->3 +--source include/rpl_init.inc + +connection server_1; +create table t1 (n int); +insert into t1 values (1); +insert into t1 values (2); +save_master_pos; + +connection server_3; +sync_with_master; +source include/stop_slave.inc; +source include/wait_for_slave_to_stop.inc; + +connection server_2; +sync_with_master; +source include/stop_slave.inc; +source include/wait_for_slave_to_stop.inc; +reset slave all; + +connection server_1; +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + master_user='root', MASTER_USE_GTID=CURRENT_POS; +source include/start_slave.inc; +source include/wait_for_slave_to_start.inc; + +connection server_2; +flush logs; +insert into t1 values (3); +insert into t1 values (4); +flush logs; +save_master_pos; + +connection server_3; +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + MASTER_USE_GTID=CURRENT_POS; +source include/start_slave.inc; +sync_with_master; + +select * from t1 order by n; +source include/show_binary_logs.inc; +let $binlog_file=LAST; +source include/show_binlog_events.inc; + +connection server_1; +--sync_with_master +source include/stop_slave.inc; +source include/wait_for_slave_to_stop.inc; +reset slave all; + +connection server_2; +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + master_user = 'root', MASTER_USE_GTID=CURRENT_POS; +source include/start_slave.inc; + +connection server_3; +source include/stop_slave.inc; +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + MASTER_USE_GTID=CURRENT_POS; +source include/start_slave.inc; + +connection server_1; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf new file mode 100644 index 00000000..2b9e70c5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.cnf @@ -0,0 +1,11 @@ +!include suite/rpl/rpl_1slave_base.cnf +!include include/default_client.cnf + + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test new file mode 100644 index 00000000..064f7b8a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4474.test @@ -0,0 +1,72 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_statement.inc +--let $rpl_topology=1->2->1 +--source include/rpl_init.inc + +--echo # +--echo # For now we'll only have 1->2 running + +--echo # +--echo # Server 1 +--echo # Stop replication 2->1 +--connection server_1 +--source include/stop_slave.inc + +--echo # +--echo # Server 2 +--echo # Use GTID for replication 1->2 +--connection server_2 +--source include/stop_slave.inc +change master to master_use_gtid=slave_pos; +--source include/start_slave.inc + +--echo # +--echo # Create some 0-1-* and 0-2-* events in binlog of server 2 + +--connection server_1 +create table t1 (i int) engine=InnoDB; +insert into t1 values (1); +--save_master_pos + +--connection server_2 +--sync_with_master +create table t2 (i int) engine=InnoDB; +--save_master_pos + +--connection server_1 +insert into t1 values (2); +--save_master_pos + +--connection server_2 +--sync_with_master +insert into t2 values (1); +--save_master_pos + +--echo # +--echo # All events are present in the binlog of server 2 + +--source include/show_binlog_events.inc + +--echo # +--echo # Server 1 +--echo # Start replication 2->1 using GTID, + +--connection server_1 +change master to master_use_gtid=slave_pos; +--source include/start_slave.inc +--sync_with_master + +select * from t1 order by i; +select * from t2 order by i; + +--connection server_2 +select * from t1 order by i; +select * from t2 order by i; + +--connection server_1 +drop table t1; + +--connection server_2 +drop table t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test new file mode 100644 index 00000000..5c17653d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test @@ -0,0 +1,106 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc +# Since we inject an error updating mysql.gtid_slave_pos, we will get different +# output depending on whether it is InnoDB or MyISAM (roll back or no roll +# back). So fix it to make sure we are consistent, in case an earlier test case +# left it as InnoDB. +SET sql_log_bin=0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +SET sql_log_bin=1; +--source include/start_slave.inc + +--connection master +CREATE TABLE t1 (i int) ENGINE=InnoDB; + +--sync_slave_with_master + +--echo *** MDEV-4484, incorrect error handling when entries in gtid_slave_pos not found. *** +TRUNCATE TABLE mysql.gtid_slave_pos; + +--connection master +INSERT INTO t1 VALUES (1); +--sync_slave_with_master + +# Inject an artificial error deleting entries, and check that the error handling code works. +--connection slave +--source include/stop_slave.inc +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 2; +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,gtid_slave_pos_simulate_failed_delete"; +SET sql_log_bin= 0; +CALL mtr.add_suppression("<DEBUG> Error deleting old GTID row"); +SET sql_log_bin= 1; +--source include/start_slave.inc + +--connection master +--disable_query_log +let $i = 20; +while ($i) { + eval INSERT INTO t1 VALUES ($i+10); + dec $i; +} +--enable_query_log +--save_master_pos + +--connection slave +--sync_with_master + +# Now wait for the slave background thread to try to delete old rows and +# hit the error injection. +--let _TEST_MYSQLD_ERROR_LOG=$MYSQLTEST_VARDIR/log/mysqld.2.err +--perl + open F, '<', $ENV{'_TEST_MYSQLD_ERROR_LOG'} or die; + outer: while (1) { + inner: while (<F>) { + last outer if /<DEBUG> Error deleting old GTID row/; + } + # Easy way to do sub-second sleep without extra modules. + select(undef, undef, undef, 0.1); + } +EOF + +# Since we injected error in the cleanup code, the rows should remain in +# mysql.gtid_slave_pos. Check that we have at least 20 (more robust against +# non-deterministic cleanup and future changes than checking for exact number). +SELECT COUNT(*), MAX(seq_no) INTO @pre_count, @pre_max_seq_no + FROM mysql.gtid_slave_pos; +SELECT IF(@pre_count >= 20, "OK", CONCAT("Error: too few rows seen while errors injected: ", @pre_count)); +SET GLOBAL debug_dbug= @old_dbug; + +--connection master +--disable_query_log +let $i = 20; +while ($i) { + eval INSERT INTO t1 VALUES ($i+40); + dec $i; +} +--enable_query_log +--sync_slave_with_master + +--connection slave +# Now check that 1) rows are being deleted again after removing error +# injection, and 2) old rows are left that failed their delete while errors +# where injected (again compensating for non-deterministic deletion). +# Deletion is async and slightly non-deterministic, so we wait for at +# least 10 of the 20 new rows to be deleted. +let $wait_condition= + SELECT COUNT(*) <= 20-10 + FROM mysql.gtid_slave_pos + WHERE seq_no > @pre_max_seq_no; +--source include/wait_condition.inc +SELECT IF(COUNT(*) >= 1, "OK", CONCAT("Error: too few rows seen after errors no longer injected: ", COUNT(*))) + FROM mysql.gtid_slave_pos + WHERE seq_no <= @pre_max_seq_no; + +# Clean up +--connection master +DROP TABLE t1; +--connection slave +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf new file mode 100644 index 00000000..fccef215 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.cnf @@ -0,0 +1,18 @@ +!include suite/rpl/rpl_1slave_base.cnf +!include include/default_client.cnf + +[mysqld.1] +log-slave-updates +gtid-domain-id=1 + +[mysqld.2] +log-slave-updates +gtid-domain-id=2 + +[mysqld.3] +log-slave-updates +gtid-domain-id=3 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test new file mode 100644 index 00000000..6c37ceaf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4485.test @@ -0,0 +1,41 @@ +--let $rpl_topology= 1->3 +--source include/rpl_init.inc + +--echo *** MDEV-4485. Master did not allow slave to connect from the very start (empty GTID pos) if GTIDs from other multi_source master was present *** + +--connection server_1 +create table t1 (i int); + +--connection server_2 +create table t2 (i int); + +--connection server_3 + +set default_master_connection = 'm2'; +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval change master to master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_2 +insert into t2 values (1); +--save_master_pos + +--connection server_3 +--sync_with_master 0,'m2' + +--connection server_1 +drop table t1; + +--connection server_2 +drop table t2; +--save_master_pos + +--connection server_3 +--sync_with_master 0,'m2' +set default_master_connection = 'm2'; +--source include/stop_slave.inc +RESET SLAVE ALL; +set default_master_connection = ''; + +--connection server_1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test new file mode 100644 index 00000000..7f4d851f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4820.test @@ -0,0 +1,118 @@ +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_2 +--source include/stop_slave.inc +SET @slave_old_strict= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +SET @master_old_strict= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +--let $old_gtid_pos= `SELECT @@GLOBAL.gtid_current_pos` +RESET MASTER; +--replace_result $old_gtid_pos OLD_GTID_POS +eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos'; + +--connection server_2 +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection server_2 +SET sql_log_bin= 0; +CALL mtr.add_suppression("The binlog on the master is missing the GTID"); +SET sql_log_bin= 1; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc + +STOP SLAVE SQL_THREAD; +--replace_result $old_gtid_pos OLD_GTID_POS +eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos'; + +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +RESET SLAVE ALL; +RESET MASTER; +SET GLOBAL gtid_slave_pos= '0-2-10'; + +--connection server_1 +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_2, + master_user= 'root', master_use_gtid=CURRENT_POS; +START SLAVE; + +--connection server_2 +INSERT INTO t1 VALUES (11); +--save_master_pos + +--connection server_1 +SET sql_log_bin= 0; +CALL mtr.add_suppression("which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged"); +SET sql_log_bin= 1; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc + +--connection server_1 +STOP SLAVE SQL_THREAD; +SET GLOBAL gtid_slave_pos= '0-2-10'; +SET GLOBAL gtid_strict_mode= 0; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +RESET SLAVE ALL; +--let $old_gtid_pos= `SELECT @@GLOBAL.gtid_current_pos` +INSERT INTO t1 VALUES (12); +--save_master_pos + +--connection server_2 +INSERT INTO t1 VALUES (22); +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + master_user= 'root', master_use_gtid=CURRENT_POS; +START SLAVE; +SET sql_log_bin= 0; +CALL mtr.add_suppression("which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged"); +SET sql_log_bin= 1; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc +STOP SLAVE SQL_THREAD; +SET GLOBAL gtid_strict_mode= 0; +CHANGE MASTER TO master_use_gtid=SLAVE_POS; +--replace_result $old_gtid_pos OLD_GTID_POS +eval SET GLOBAL gtid_slave_pos= '$old_gtid_pos'; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Clean up. +--connection server_2 +SET GLOBAL gtid_strict_mode= @slave_old_strict; + +--connection server_1 +DROP TABLE t1; +SET GLOBAL gtid_strict_mode= @master_old_strict; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf new file mode 100644 index 00000000..80b66498 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.cnf @@ -0,0 +1,20 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb +gtid_domain_id=1 + +[mysqld.2] +log-slave-updates +loose-innodb +gtid_domain_id=2 + +[mysqld.3] +log-slave-updates +loose-innodb +gtid_domain_id=3 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test new file mode 100644 index 00000000..f8e8642a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev9033.test @@ -0,0 +1,72 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +--connection server_2 +--source include/stop_slave.inc +eval CHANGE MASTER TO + MASTER_USE_GTID = SLAVE_POS, IGNORE_DOMAIN_IDS = (2,3); +START SLAVE; + +--connection server_3 +--source include/stop_slave.inc +eval CHANGE MASTER TO + MASTER_USE_GTID = SLAVE_POS, IGNORE_DOMAIN_IDS = (2,3); +START SLAVE; + +connection server_1; + +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, "m1"); +INSERT INTO t1 VALUES (2, "m2"), (3, "m3"), (4, "m4"); + +SET @@session.gtid_domain_id=2; +--echo # The following should get filetered on slave. +CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1, "m1"); +INSERT INTO t2 VALUES (2, "m2"), (3, "m3"), (4, "m4"); + +--source include/save_master_gtid.inc + +connection server_2; +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +--echo # Only 't1' should have replicated to slaves. +SHOW TABLES; + +--source include/save_master_gtid.inc + +connection server_3; +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +--echo # Only 't1' should have replicated to slaves. +SHOW TABLES; + +--echo # Cleanup +--connection server_1 +SET @@session.gtid_domain_id=1; +DROP TABLE t1; +SET @@session.gtid_domain_id=2; +DROP TABLE t2; + +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +--source include/save_master_gtid.inc + +--connection server_3 +--source include/sync_with_master_gtid.inc + +--connection server_2 +STOP SLAVE; +CHANGE MASTER TO MASTER_USE_GTID = NO, IGNORE_DOMAIN_IDS = (); + +--connection server_3 +STOP SLAVE; +CHANGE MASTER TO MASTER_USE_GTID = NO, IGNORE_DOMAIN_IDS = (); + +--echo # End of test. diff --git a/mysql-test/suite/rpl/t/rpl_gtid_misc.test b/mysql-test/suite/rpl/t/rpl_gtid_misc.test new file mode 100644 index 00000000..66d98ec8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_misc.test @@ -0,0 +1,50 @@ +--source include/master-slave.inc + +--echo *** MDEV-6403: Temporary tables lost at STOP SLAVE in GTID mode if master has not rotated binlog since restart *** + +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY); +--sync_slave_with_master + +--connection slave +--source include/stop_slave.inc +# Inject a duplicate key error that will make the slave stop in the middle of +# a sequence of transactions that use a temporary table. +SET sql_log_bin= 0; +INSERT INTO t1 VALUES (1); +SET sql_log_bin= 1; +CHANGE MASTER TO master_use_gtid= current_pos; + +--connection master + +# Make some queries that use a temporary table. +CREATE TEMPORARY TABLE t2 LIKE t1; +INSERT INTO t2 VALUE (1); +INSERT INTO t1 SELECT * FROM t2; +DROP TEMPORARY TABLE t2; +--save_master_pos + +--connection slave +START SLAVE; +--let $slave_sql_errno=1062 +--source include/wait_for_slave_sql_error.inc + +# Restart the slave. +# The bug was that the IO thread would receive again the restart +# format_description event at the start of the master's binlog, and this +# event would cause the SQL thread to discard all active temporary tables. + +STOP SLAVE IO_THREAD; + +SET sql_log_bin= 0; +DELETE FROM t1 WHERE a=1; +SET sql_log_bin= 1; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf new file mode 100644 index 00000000..0ea0d951 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.cnf @@ -0,0 +1,9 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates=0 +loose-innodb + +[mysqld.2] +log-slave-updates=0 +loose-innodb diff --git a/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test new file mode 100644 index 00000000..a5caebf0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_nobinlog.test @@ -0,0 +1,66 @@ +--let $rpl_topology=1->2 +--source include/rpl_init.inc +--source include/have_binlog_format_statement.inc + +--connection server_1 +SET @old_strict= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +select @@global.log_slave_updates; + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 1); +--save_master_pos + +--connection server_2 +SET @old_strict= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +select @@global.log_slave_updates; + +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--connection server_1 +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT, + master_user = 'root', master_use_gtid = current_pos; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +--connection server_2 +INSERT INTO t1 VALUES (3, 2); +INSERT INTO t1 VALUES (4, 2); +--source include/save_master_gtid.inc + +--source include/show_binlog_events.inc + +--connection server_1 +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +RESET SLAVE; +INSERT INTO t1 VALUES (5, 1); +INSERT INTO t1 VALUES (6, 1); +--source include/save_master_gtid.inc + +--connection server_2 +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + master_use_gtid = current_pos; +START SLAVE; +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; + +# Cleanup. +SET GLOBAL gtid_strict_mode= @old_strict; + +--connection server_1 +SET GLOBAL gtid_strict_mode= @old_strict; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test b/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test new file mode 100644 index 00000000..bc28ebdd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_reconnect.test @@ -0,0 +1,206 @@ +--let $rpl_topology=1->2 +--source include/rpl_init.inc +--source include/have_innodb.inc +--source include/have_debug.inc + + +--connection server_2 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid= current_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT); +FLUSH LOGS; +--save_master_pos + +--connection server_2 +--sync_with_master + + +# Prepare a string of events and have the slave replicate all of it. +--connection server_1 +SET gtid_domain_id=10; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +SET gtid_seq_no=100; +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +SELECT * FROM t1 ORDER BY a; + +# Now start the slave again, but force a reconnect. There was a bug that this +# reconnect would cause duplicate events. + +--connection server_1 +# Make sure to get rid of any old binlog dump thread so it does not +# interfere with our DBUG error injection. +--source include/kill_binlog_dump_threads.inc +INSERT INTO t1 VALUES (10); +SET @old_debug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output"; +SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100"; +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +TRUNCATE t1; +RESET MASTER; +SET GLOBAL gtid_slave_pos= ""; + +--connection server_1 +SET GLOBAL debug_dbug= @old_debug; +TRUNCATE t1; +RESET MASTER; + +# A1 B1 A2 B2 A3 B3, slave reached A1 and B3 and stopped. Slave starts, +# reconnects at A2. There was a bug that B2 would be duplicated. + +SET gtid_domain_id=10; +SET gtid_seq_no=50; +INSERT INTO t1 VALUES (1); +SET gtid_domain_id=11; +INSERT INTO t1 VALUES (11); +SET gtid_domain_id=10; +SET gtid_seq_no=100; +INSERT INTO t1 VALUES (2); +SET gtid_domain_id=11; +INSERT INTO t1 VALUES (12); +SET gtid_domain_id=10; +INSERT INTO t1 VALUES (3); +SET gtid_domain_id=11; +SET gtid_seq_no=200; +INSERT INTO t1 VALUES (13); + +--connection server_2 +START SLAVE UNTIL master_gtid_pos="10-1-50,11-1-200"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; + +--connection server_1 +--source include/kill_binlog_dump_threads.inc +INSERT INTO t1 VALUES (20); +SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output"; +SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100"; +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc +TRUNCATE t1; +RESET MASTER; +SET GLOBAL gtid_slave_pos= ""; + +--connection server_1 +SET GLOBAL debug_dbug= @old_debug; +TRUNCATE t1; +RESET MASTER; + +# A1 B1 A2 B2 A3 B3. START SLAVE UNTIL A1,B3, gets reconnect at B2. +# There was a bug that the UNTIL would be ignored, and A2 would be lost. + +--source include/kill_binlog_dump_threads.inc +SET gtid_domain_id= 9; +SET gtid_seq_no= 50; +INSERT INTO t1 VALUES (1); +SET gtid_domain_id= 10; +INSERT INTO t1 VALUES (11); +SET gtid_domain_id= 9; +INSERT INTO t1 VALUES (2); +SET gtid_domain_id= 10; +SET gtid_seq_no= 100; +INSERT INTO t1 VALUES (12); +SET gtid_domain_id= 9; +INSERT INTO t1 VALUES (3); +SET gtid_domain_id= 10; +SET gtid_seq_no= 200; +INSERT INTO t1 VALUES (13); +SET gtid_domain_id= 10; + +SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output"; +SET GLOBAL debug_dbug="+d,gtid_force_reconnect_at_10_1_100"; + +--connection server_2 +START SLAVE UNTIL master_gtid_pos="9-1-50,10-1-200"; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; + +--connection server_1 +SET GLOBAL debug_dbug= @old_debug; +INSERT INTO t1 VALUES (20); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test when slave IO thread needs to reconnect in the middle of an event group. *** +--connection server_2 +--source include/stop_slave.inc + +TRUNCATE t1; +RESET MASTER; +SET GLOBAL gtid_slave_pos= ""; + +--connection server_1 +SET GLOBAL debug_dbug= @old_debug; +TRUNCATE t1; +RESET MASTER; + +--source include/kill_binlog_dump_threads.inc +SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output"; +SET GLOBAL debug_dbug="+d,binlog_force_reconnect_after_22_events"; + +# 4 events for FD, fake rotate, gtid list, binlog checkpoint. +# 2 events for GTID, create table +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +# 3 events for BEGIN/query/COMMIT +INSERT INTO t2 VALUES (1); +# 4 events for BEGIN/query/query/COMMIT +BEGIN; +INSERT INTO t2 VALUES (10); +INSERT INTO t2 VALUES (11); +COMMIT; +# So this event group starts after 4+2+4+3=13 events. Or 16 in row-based. +BEGIN; +INSERT INTO t2 VALUES (20); +INSERT INTO t2 VALUES (21); +INSERT INTO t2 VALUES (22); +INSERT INTO t2 VALUES (23); +INSERT INTO t2 VALUES (24); +INSERT INTO t2 VALUES (25); +INSERT INTO t2 VALUES (26); +INSERT INTO t2 VALUES (27); +INSERT INTO t2 VALUES (28); +INSERT INTO t2 VALUES (29); +COMMIT; +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t2 ORDER BY a; + +--connection server_1 +SET GLOBAL debug_dbug= @old_debug; + + +# Clean up. +--connection server_1 +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_sort.test b/mysql-test/suite/rpl/t/rpl_gtid_sort.test new file mode 100644 index 00000000..dc3b18aa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_sort.test @@ -0,0 +1,77 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test connecting with empty GTID state to start from very beginning of binlog *** +--connection server_2 +--source include/stop_slave.inc +RESET MASTER; +RESET SLAVE; +SHOW VARIABLES LIKE 'gtid_binlog_pos'; +SHOW VARIABLES LIKE 'gtid_current_pos'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SHOW VARIABLES LIKE 'gtid_binlog_state'; + +--connection server_1 +RESET MASTER; +FLUSH LOGS; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @@SESSION.gtid_domain_id=1; +INSERT INTO t1 VALUES(1); + +SET @@SESSION.gtid_domain_id=99999; +INSERT INTO t1 VALUES(3); + +SET @@SESSION.gtid_domain_id=10; +INSERT INTO t1 VALUES(4); + +SET @@SESSION.gtid_domain_id=100; +INSERT INTO t1 VALUES(5); + +SET @@SESSION.gtid_domain_id=2147483648; # 0x80000000 +INSERT INTO t1 VALUES(6); + +SET @@SESSION.gtid_domain_id=4294967295; # 0xFFFFFFFF +INSERT INTO t1 VALUES(7); + +SHOW VARIABLES LIKE 'gtid_binlog_pos'; +SHOW VARIABLES LIKE 'gtid_current_pos'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SHOW VARIABLES LIKE 'gtid_binlog_state'; +--save_master_pos + +--connection server_2 +SHOW VARIABLES LIKE 'gtid_binlog_pos'; +SHOW VARIABLES LIKE 'gtid_current_pos'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SHOW VARIABLES LIKE 'gtid_binlog_state'; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_USE_GTID=CURRENT_POS; +--source include/start_slave.inc +--sync_with_master +SHOW VARIABLES LIKE 'gtid_binlog_pos'; +SHOW VARIABLES LIKE 'gtid_current_pos'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SHOW VARIABLES LIKE 'gtid_binlog_state'; +SELECT * FROM t1; + +SET @@SESSION.gtid_domain_id=1000; +INSERT INTO t1 VALUES(8); + +SET @@SESSION.gtid_domain_id=89; +INSERT INTO t1 VALUES(9); + +SET @@SESSION.gtid_domain_id=10100000; +INSERT INTO t1 VALUES(10); + +SHOW VARIABLES LIKE 'gtid_binlog_pos'; +SHOW VARIABLES LIKE 'gtid_current_pos'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SHOW VARIABLES LIKE 'gtid_binlog_state'; + +# Clean up. +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_startpos.test b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test new file mode 100644 index 00000000..100d75a8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_startpos.test @@ -0,0 +1,358 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test connecting with empty GTID state to start from very beginning of binlog *** +--connection server_2 +--source include/stop_slave.inc +RESET MASTER; +RESET SLAVE; + +--connection server_1 +RESET MASTER; +# Create an empty binlog file, to check that empty binlog state is handled correctly. +FLUSH LOGS; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +SET GLOBAL gtid_slave_pos=""; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_USE_GTID=CURRENT_POS; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1; + +--connection server_1 +INSERT INTO t1 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1; +--source include/stop_slave.inc + +--echo *** Test that master gives error when slave asks for empty gtid pos and binlog files have been purged. *** +--connection server_1 +FLUSH LOGS; +INSERT INTO t1 VALUES (2); +--save_master_pos +--let $purge_binlogs_to=master-bin.000003 +--source include/wait_for_purge.inc +--source include/show_binary_logs.inc + +--connection server_2 +SET GLOBAL gtid_slave_pos=""; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_USE_GTID=CURRENT_POS; +START SLAVE; +--let $slave_io_errno= 1236 +--source include/wait_for_slave_io_error.inc +--source include/stop_slave.inc + +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_LOG_FILE="master-bin.000003", MASTER_LOG_POS=4; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SET sql_log_bin=0; +call mtr.add_suppression('Could not find GTID state requested by slave in any binlog files'); +SET sql_log_bin=1; + +--echo *** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log *** +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES(3); +--source include/save_master_gtid.inc + +--connection server_2 +SET GLOBAL gtid_slave_pos='0-1-3'; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_USE_GTID=CURRENT_POS; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER by a; +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection server_2 +# Now add some local transactions that conflict with the GTID position +# being set for @@gtid_slave_pos. +INSERT INTO t1 VALUES (10); +DELETE FROM t1 WHERE a=10; +SET GLOBAL gtid_slave_pos='0-1-4'; + +# Try again after RESET MASTER to remove the conflicting binlog. +RESET MASTER; +SET GLOBAL gtid_slave_pos='0-1-4'; +START SLAVE; +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER by a; + +--connection server_1 +DROP TABLE t1; +--save_master_pos + +--connection server_2 +--sync_with_master + + +--echo *** MDEV-4275: I/O thread restart duplicates events in relay log *** + +--connection server_2 +--source include/stop_slave.inc +RESET SLAVE ALL; +RESET MASTER; + +--connection server_1 +RESET MASTER; + +--connection server_2 +SET GLOBAL gtid_slave_pos=''; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=current_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1; + +--source include/stop_slave_io.inc +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection server_1 +INSERT INTO t1 VALUES (2); +--save_master_pos + +--connection server_2 +--sync_with_master + +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4329: GTID_SLAVE_POS='' is not checked for conflicts with binlog *** + +# Test starting the slave completely from scratch, deleting all tables and +# replicating from the start of the master's binlog. This requires RESET +# MASTER is run on the slave to avoid old junk in the binlog. The bug was +# that the code did not catch the error of missing RESET MASTER when an +# empty GTID_SLAVE_POS='' was specified. + +--connection server_2 +--source include/stop_slave.inc +DROP TABLE t1; +RESET SLAVE; +SET GLOBAL gtid_slave_pos=""; +RESET MASTER; +SET GLOBAL gtid_slave_pos=""; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +# Same thing, but this time using SQL_LOG_BIN=0 to avoid polluting the +# slave binlog. + +--connection server_2 +--source include/stop_slave.inc +SET SQL_LOG_BIN=0; +DROP TABLE t1; +SET SQL_LOG_BIN=1; +RESET SLAVE; +SET GLOBAL gtid_slave_pos=""; +# Ensure that the slave fails because of missing table to be dropped +SET @save_slave_ddl_exec_mode=@@global.slave_ddl_exec_mode; +SET GLOBAL slave_ddl_exec_mode=STRICT; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--echo *** Test that RESET SLAVE clears the Using_Gtid flag. *** +--source include/stop_slave.inc +RESET SLAVE; +--let $status_items= Using_Gtid +--source include/show_slave_status.inc + +# Starting the slave now reverts to old-style position which defaults to +# the first non-purged binlog file on the master. +# This should give error due to table already existing. +START SLAVE; +--let $slave_sql_errno= 1050 +--source include/wait_for_slave_sql_error.inc + +# Going back to using GTID should fix things. +STOP SLAVE IO_THREAD; +CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES(3); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SET SQL_LOG_BIN=0; +call mtr.add_suppression("Slave: Table 't1' already exists error.* 1050"); +SET SQL_LOG_BIN=1; + + +--echo *** Test reconnecting slave with GTID after purge logs on master. *** + +--connection server_1 +FLUSH LOGS; +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc + +--connection server_1 +FLUSH LOGS; +FLUSH LOGS; +--let $purge_binlogs_to=master-bin.000004 +--source include/wait_for_purge.inc +--source include/show_binary_logs.inc +INSERT INTO t1 VALUES (5); +--source include/save_master_gtid.inc + +--connection server_2 +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test modifying binlog on slave and the effect on GTID state. *** + +--connection server_2 +--source include/stop_slave.inc +RESET MASTER; +SET GLOBAL gtid_slave_pos=""; + +--connection server_1 +RESET MASTER; +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES (10); # Will be GTID 0-1-2 +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1; +--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1) +eval SELECT '$value' AS Using_Gtid; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; + +UPDATE t1 SET a=9 WHERE a=10; +UPDATE t1 SET a=10 WHERE a=9; + +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; + +--source include/stop_slave.inc +SET GLOBAL gtid_slave_pos='0-1-2'; +RESET MASTER; +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; +SET GLOBAL gtid_slave_pos='0-1-2'; +--source include/start_slave.inc +--let $value= query_get_value(SHOW ALL SLAVES STATUS, "Gtid_Slave_Pos", 1) +eval SELECT '$value' AS Gtid_Slave_Pos; + + +--echo *** MDEV-4483: Slave loses traditional master coordinates immediately on CHANGE MASTER TO MASTER_USE_GTID = 1 *** +--connection server_2 +--source include/stop_slave.inc +DROP TABLE t1; +RESET SLAVE ALL; +RESET MASTER; +SET GLOBAL gtid_slave_pos= ""; + +# Set up old-style replication. The bug was that CHANGE MASTER would clear +# out the old-style binlog/relaylog coordinates when it should not. + +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root', master_use_gtid=no, master_log_file="", master_log_pos= 4; + +--connection server_1 +DROP TABLE t1; +RESET MASTER; + +CREATE TABLE t1 (a INT PRIMARY KEY); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master + +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (1); +--let $log_file1= query_get_value(SHOW MASTER STATUS, "File", 1) +--let $log_pos1= query_get_value(SHOW MASTER STATUS, "Position", 1) +INSERT INTO t1 VALUES (2); +--let $log_file2= query_get_value(SHOW MASTER STATUS, "File", 1) +--let $log_pos2= query_get_value(SHOW MASTER STATUS, "Position", 1) +--save_master_pos + +--connection server_2 +# Get the slave to a point where the IO thread has fetched one event ahead +# of the SQL thread (we want to test that CHANGE MASTER does not mess with +# existing relay logs). +--replace_result $log_file1 LOG_FILE1 $log_pos1 LOG_POS1 +eval START SLAVE UNTIL master_log_file='$log_file1', master_log_pos=$log_pos1; +--source include/wait_for_slave_sql_to_stop.inc +SELECT * FROM t1; +--let $slave_param= Read_Master_Log_Pos +--let $slave_param_value= $log_pos2 +--source include/wait_for_slave_param.inc +--source include/stop_slave_io.inc + +# Test that we can change to GTID and back without loosing our +# old-style slave position. +CHANGE MASTER TO master_use_gtid=slave_pos; +# Unknown GTID, so slave will fail to connect. +SET GLOBAL gtid_slave_pos="0-42-42"; +SET sql_log_bin=0; +call mtr.add_suppression("Error: connecting slave requested to start from GTID"); +SET sql_log_bin=1; +START SLAVE; +--let $slave_io_errno= 1236 +--source include/wait_for_slave_io_error.inc +STOP SLAVE SQL_THREAD; +--source include/wait_for_slave_sql_to_stop.inc +CHANGE MASTER TO master_use_gtid=no; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Clean up. +--connection server_1 +DROP TABLE t1; +--connection server_2 +set @@global.slave_ddl_exec_mode=@save_slave_ddl_exec_mode; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf new file mode 100644 index 00000000..c7247a80 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.cnf @@ -0,0 +1,5 @@ +!include ../my.cnf + +[mysqld.2] +# Needed because depending on load on test machine the master restart can take long. +master_retry_count = 120 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test new file mode 100644 index 00000000..fd4cdf71 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -0,0 +1,351 @@ +--let $rpl_topology=1->2 +--source include/rpl_init.inc +--source include/have_innodb.inc + +--echo *** Test normal shutdown/restart of slave server configured as a GTID slave. *** + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc + +--let $status_items= Master_Log_File,Using_Gtid +--source include/show_slave_status.inc + +CHANGE MASTER TO master_use_gtid=current_pos; + +# Now try to restart the slave mysqld server without starting the slave first +# threads after the CHANGE MASTER. +# When the slave restarts, it should reconnect using GTID. +# We test that it really uses GTID by purging on the master the +# old binlog the slave would need if connecting with old style +# file name/offset. + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +FLUSH LOGS; +--shutdown_server +--source include/wait_until_disconnected.inc + +--connection server_1 +FLUSH LOGS; +--let $purge_binlogs_to=master-bin.000002 +--source include/wait_for_purge.inc +--source include/show_binary_logs.inc +INSERT INTO t1 VALUES (2); +FLUSH LOGS; +INSERT INTO t1 VALUES (3); +--source include/save_master_gtid.inc +--source include/show_binary_logs.inc + +# Let the slave mysqld server start again. +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test normal shutdown/restart of master server, check binlog state is preserved. *** + +--connection server_1 +SET SESSION gtid_domain_id= 1; +INSERT INTO t1 VALUES (4); +--replace_column 2 # 4 # 5 # +SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1; +FLUSH LOGS; +--replace_column 2 # 4 # 5 # 6 # +SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_column 2 # 4 # 5 # 6 # +SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1; +--source include/show_binary_logs.inc + +INSERT INTO t1 VALUES(5); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +--echo *** Test that @@gtid_slave_pos and @@gtid_current_pos are correctly loaded even if slave threads have not started. *** +--let $slave_pos1= `SELECT @@GLOBAL.gtid_slave_pos` +--let $current_pos1= `SELECT @@GLOBAL.gtid_current_pos` + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=1 --skip-log-bin +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_query_log +eval SET @slave_pos1= "$slave_pos1"; +eval SET @current_pos1= "$current_pos1"; +--enable_query_log +SET @slave_pos2= @@GLOBAL.gtid_slave_pos; +SET @current_pos2= @@GLOBAL.gtid_current_pos; +SELECT IF(@slave_pos1=@slave_pos2, "OK", CONCAT(@slave_pos1, " != ", @slave_pos2)); +SELECT IF(@current_pos1=@current_pos2, "OK", CONCAT(@current_pos1, " != ", @current_pos2)); + +--connection server_1 +INSERT INTO t1 VALUES (6); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4490: Old-style master position points at the last GTID event after slave restart *** + +--connection server_1 +INSERT INTO t1 VALUES (7); +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +# Now we restart the slave server. When it restarts, there is nothing new +# to replicate. Check that the position is nevertheless updated and +# MASTER_POS_WAIT() works correctly and detects that we are up-to-date. + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/wait_for_slave_to_start.inc + +--connection server_1 +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable + +--connection server_2 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid= no; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (8); +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; +--source include/stop_slave.inc + +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=1 --skip-innodb +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM mysql.gtid_slave_pos; +SET sql_log_bin=0; +call mtr.add_suppression("Failed to load slave replication state from table"); +call mtr.add_suppression("Unable to load replication GTID slave state"); +SET sql_log_bin=1; + +--source include/start_slave.inc +--connection server_1 +INSERT INTO t1 VALUES (9); +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +# Put things back as they were. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +SET sql_log_bin= 1; +# Do a second restart to get the mysql.gtid_slave_pos table loaded with +# the right engine. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (10); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid= slave_pos; +--source include/start_slave.inc + +--echo *** MDEV-4692: mysql.gtid_slave_pos accumulates values for a domain *** +SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; + +--connection server_1 +INSERT INTO t1 VALUES (11); +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; + + +--echo *** MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position *** + +--connection server_2 +SET sql_log_bin=0; +--let $old_pos= `SELECT @@GLOBAL.gtid_slave_pos` +RENAME TABLE mysql.gtid_slave_pos TO mysql.old_gtid_slave_pos; +SET sql_log_bin=1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +# Let the slave mysqld server start again. +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart +EOF + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--disable_result_log +SHOW VARIABLES; +--enable_result_log +SHOW VARIABLES LIKE 'gtid_slave_pos'; +--error ER_CANNOT_LOAD_SLAVE_GTID_STATE,ER_NO_SUCH_TABLE +SET GLOBAL gtid_slave_pos = '0-1-2'; +SHOW WARNINGS; + +# Restore things. + +SET sql_log_bin=0; +RENAME TABLE mysql.old_gtid_slave_pos TO mysql.gtid_slave_pos; +CALL mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos"); +SET sql_log_bin=1; + +SHOW VARIABLES LIKE 'gtid_slave_pos'; +SET GLOBAL gtid_slave_pos = '0-1-2'; +SHOW VARIABLES LIKE 'gtid_slave_pos'; + +# Don't let .result file depend on old state of gtid_slave_pos +--disable_query_log +--disable_result_log +eval SET GLOBAL gtid_slave_pos = '$old_pos'; +--enable_query_log +--enable_result_log + +--source include/start_slave.inc + + +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_strict.test b/mysql-test/suite/rpl/t/rpl_gtid_strict.test new file mode 100644 index 00000000..56ebba82 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_strict.test @@ -0,0 +1,179 @@ +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 0; +call mtr.add_suppression("Error writing file .*errno: 1950"); + +SET sql_log_bin= 1; + +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode= 1; +--connection server_2 +--source include/stop_slave.inc +SET @old_gtid_strict_mode= @@GLOBAL.gtid_strict_mode; +SET GLOBAL gtid_strict_mode=1; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--source include/show_binlog_events.inc + +SET server_id= 3; +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 3; +SET @old_dbug = @@session.debug_dbug; +SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 3; +SET SESSION debug_dbug=@old_dbug; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t1 VALUES (2); + +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 2; +SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 2; +SET SESSION debug_dbug=@old_dbug; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t1 VALUES (3); +SET server_id= 1; +SET gtid_seq_no= 4; +INSERT INTO t1 VALUES (4); +SELECT * FROM t1 ORDER BY 1; +--source include/show_binlog_events.inc + +--echo *** Test non-transactional GTID error (cannot be rolled back). *** +SET server_id= 3; +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 1; +SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug=@old_dbug; +--error ER_GTID_STRICT_OUT_OF_ORDER +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; +# The table is still created, DDL cannot be rolled back. +# Fix it up for replication. +SET sql_log_bin= 0; +DROP TABLE t2; +SET sql_log_bin= 1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=MyISAM; + +--error ER_GTID_STRICT_OUT_OF_ORDER +SET gtid_seq_no= 1; +SET SESSION debug_dbug="d,ignore_set_gtid_seq_no_check"; +SET gtid_seq_no= 1; +SET SESSION debug_dbug=@old_dbug; +--error ER_GTID_STRICT_OUT_OF_ORDER +INSERT INTO t2 VALUES (1); +# The value is still inserted, cannot be rolled back. +SET server_id= 1; +SET gtid_seq_no= 6; +INSERT INTO t2 VALUES (2); +SELECT * FROM t2 ORDER BY a; +--source include/show_binlog_events.inc + + +--echo *** Test that slave stops if it tries to apply a GTID that would create out-of-order binlog GTID sequence numbers. *** + +--save_master_pos +--connection server_2 +--sync_with_master + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SET sql_log_bin= 0; +call mtr.add_suppression("An attempt was made to binlog GTID .* which would create an out-of-order sequence number with existing GTID .*, and gtid strict mode is enabled"); +call mtr.add_suppression("The binlog on the master is missing the GTID [-0-9]+ requested by the slave"); +SET sql_log_bin= 1; + +# Create some out-of-order stuff on slave. +INSERT INTO t1 VALUES (5); + +--connection server_1 +INSERT INTO t1 VALUES (6); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t1 ORDER BY a; + +INSERT INTO t1 VALUES (7); +--connection server_1 +CREATE TABLE t3 (a INT PRIMARY KEY); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +--error ER_NO_SUCH_TABLE +--query_vertical SHOW CREATE TABLE t3 +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +--query_vertical SHOW CREATE TABLE t3 + +INSERT INTO t1 VALUES (8); +--connection server_1 +INSERT INTO t2 VALUES (3); +--save_master_pos + +--connection server_2 +--let $slave_sql_errno=1950 +--source include/wait_for_slave_sql_error.inc +SELECT * FROM t2 ORDER BY a; +STOP SLAVE IO_THREAD; +SET GLOBAL gtid_strict_mode=0; +--source include/start_slave.inc +--sync_with_master +SET GLOBAL gtid_strict_mode=1; +SELECT * FROM t2 ORDER BY a; + + +--echo *** Check slave requests starting from a hole on the master. *** +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (10); +SET gtid_seq_no= 100; +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +--save_master_pos + +--connection server_2 +SET GLOBAL gtid_slave_pos= "0-1-50"; +START SLAVE; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc +STOP SLAVE SQL_THREAD; +SET GLOBAL gtid_strict_mode= 0; +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t1 ORDER BY a; +SET GLOBAL gtid_strict_mode= 1; + + +# Clean up. +--connection server_1 +DROP TABLE t1, t2, t3; +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; +--connection server_2 +SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_until.test b/mysql-test/suite/rpl/t/rpl_gtid_until.test new file mode 100644 index 00000000..aa05ecf7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_until.test @@ -0,0 +1,248 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +# Function to extract one GTID from a list. +delimiter |; +CREATE FUNCTION extract_gtid(d VARCHAR(100), s VARCHAR(100)) + RETURNS VARCHAR(100) DETERMINISTIC +BEGIN + SET s= CONCAT(",", s, ","); + SET s= SUBSTR(s FROM LOCATE(CONCAT(",", d, "-"), s) + 1); + SET s= SUBSTR(s FROM 1 FOR LOCATE(",", s) - 1); + RETURN s; +END| +delimiter ;| +--save_master_pos + +--connection server_2 +--sync_with_master +# Restart SQL thread to pick up ALTER TABLE of mysql.gtid_slave_pos. +--source include/stop_slave.inc +--source include/start_slave.inc + +# Both replication threads must be stopped for UNTIL master_gtid_pos. +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +--source include/stop_slave_io.inc +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +--source include/stop_slave_sql.inc +--error ER_SLAVE_WAS_RUNNING +START SLAVE UNTIL master_gtid_pos = ""; +--source include/stop_slave_io.inc +# UNTIL master_gtid_pos only valid if GTID is used. + +--error ER_UNTIL_REQUIRES_USING_GTID +START SLAVE UNTIL master_gtid_pos = ""; + +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +--let $gtid_pos=`SELECT @@GLOBAL.gtid_binlog_pos` +INSERT INTO t1 VALUES(2); + +--connection server_2 + +# Test various incorrect syntax for UNTIL master_gtid_pos. +--error ER_DUPLICATE_GTID_DOMAIN +START SLAVE UNTIL master_gtid_pos = "0-1-100,1-1-100,2-2-200,1-3-100,4-4-400"; +--error ER_PARSE_ERROR +START SLAVE UNTIL master_log_file = "master-bin.000001", master_log_pos = 4, master_gtid_pos = ""; +--error ER_BAD_SLAVE_UNTIL_COND +START SLAVE IO_THREAD UNTIL master_gtid_pos = ""; +--error ER_BAD_SLAVE_UNTIL_COND +START SLAVE SQL_THREAD UNTIL master_gtid_pos = ""; + +eval START SLAVE UNTIL master_gtid_pos = '$gtid_pos'; + +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1; + +--source include/start_slave.inc + +--connection server_1 +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Test showing the UNTIL condition in SHOW SLAVE STATUS. +--source include/stop_slave.inc +START SLAVE UNTIL master_gtid_pos = "1-10-100,2-20-200,0-1-300"; +--source include/wait_for_slave_to_start.inc +--let $status_items= Using_Gtid,Until_Condition +--source include/show_slave_status.inc + +# Clear the UNTIL condition. +# Note that we need to wait for a transaction to get through from the master. +# Otherwise the IO thread may still be in get_master_version_and_clock() +# (wait_for_slave_to_start.inc returns as soon as the IO thread is connected), +# and we can get test failures from warnings in the log about IO thread being +# killed in the middle of setting @@gtid_strict_mode or similar (MDEV-7940). +--connection server_1 +INSERT INTO t1 VALUES (3); +DELETE FROM t1 WHERE a=3; +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc + + +--echo *** Test UNTIL condition in an earlier binlog than the start GTID. *** +--connection server_2 + +--connection server_1 +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (3); +SET gtid_domain_id = 2; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (3); +--let $d1_point1= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point1= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (4); +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (4); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (5); +--let $d1_point2= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point2= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (5); +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (6); +--let $d1_point3= `SELECT extract_gtid("1", @@GLOBAL.gtid_binlog_pos)` +--let $d2_point3= `SELECT extract_gtid("2", @@GLOBAL.gtid_binlog_pos)` +SET gtid_domain_id = 2; +INSERT INTO t2 VALUES (6); +SET gtid_domain_id = 0; +--source include/show_binary_logs.inc +--save_master_pos + +--connection server_2 +# Let the slave reach an middle point in domain 1 and a late point in domain 2. +eval START SLAVE UNTIL master_gtid_pos='$d1_point2,$d2_point3'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +# Now test starting at a middle point in the binlogs when the stop position in +# one domain (domain 2) is early. +eval START SLAVE UNTIL master_gtid_pos='$d1_point3,$d2_point1'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +# Test that one UNTIL domain empty means stop that domain immediately. +eval START SLAVE UNTIL master_gtid_pos='$d1_point2'; +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Test when the UNTIL position is right at the end of the binlog file prior to the starting position *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +FLUSH LOGS; +SET gtid_domain_id = 1; +INSERT INTO t1 VALUES (7); +SET gtid_domain_id = 0; +--save_master_pos + +--connection server_2 +eval START SLAVE UNTIL master_gtid_pos='$d1_point3'; +--source include/wait_for_slave_to_stop.inc +# This should not show row 7, as we requested stop just before it. +SELECT * FROM t1 ORDER BY a; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test when UNTIL condition is after a stand-alone event (not a transaction). *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +CREATE TABLE t3 (a INT); +--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos` +DROP TABLE t3; +--save_master_pos + +--connection server_2 +--replace_result $until_condition UNTIL_CONDITION +eval START SLAVE UNTIL master_gtid_pos='$until_condition'; +--source include/wait_for_slave_to_stop.inc +SHOW CREATE TABLE t3; +--source include/start_slave.inc +--sync_with_master + +--echo *** Test UNTIL condition that has not yet been logged. *** + +--connection server_2 +--source include/stop_slave.inc +RESET SLAVE ALL; +RESET MASTER; +SET GLOBAL gtid_slave_pos=''; + +--connection server_1 +# Do it once to compute the right GTID, then throw it away and do it again +# for the actual test. +RESET MASTER; +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +--let $until_condition=`SELECT @@GLOBAL.gtid_binlog_pos` +INSERT INTO t1 VALUES (12); +DELETE FROM t1 WHERE a >= 10; + +RESET MASTER; +INSERT INTO t1 VALUES (10); + +--connection server_2 +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_1, + master_user = "root", master_use_gtid = current_pos; +eval START SLAVE UNTIL master_gtid_pos = '$until_condition'; +--source include/wait_for_slave_to_start.inc + +--connection server_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +--save_master_pos + +--connection server_2 +# This then should wait until it gets the row (11) and then stop, not +# yet having the row (12). +--source include/wait_for_slave_to_stop.inc +SELECT * FROM t1 ORDER BY a; +--source include/start_slave.inc +--sync_with_master +# And now the row (12) should be there. +SELECT * FROM t1 ORDER BY a; + + +# Clean up. +--connection server_1 +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION extract_gtid; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat.test b/mysql-test/suite/rpl/t/rpl_heartbeat.test new file mode 100644 index 00000000..77c05a60 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat.test @@ -0,0 +1,172 @@ +# Testing master to slave heartbeat protocol +# +# Including: +# - user interface, grammar, checking the range and warnings about +# unreasonable values for the heartbeat period; +# - no rotation of relay log if heartbeat is less that slave_net_timeout +# - SHOW STATUS like 'Slave_received_heartbeats' action +# - SHOW STATUS like 'Slave_heartbeat_period' report + +-- source include/have_log_bin.inc + +connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK); + +connection master; +reset master; + +connection slave; +set @restore_slave_net_timeout= @@global.slave_net_timeout; +--disable_warnings +set @@global.slave_net_timeout= 10; +--enable_warnings + +### +### Checking the range +### + +# +# default period slave_net_timeout/2 +# +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; +--query_vertical show status like 'Slave_heartbeat_period'; + +# +# the max for the period is ULONG_MAX/1000; an attempt to exceed it is denied +# +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294968; +--query_vertical show status like 'Slave_heartbeat_period'; + +# +# the min value for the period is 1 millisecond an attempt to assign a +# lesser will be warned with treating the value as zero +# +connection slave; +--replace_result $MASTER_MYPORT MASTER_PORT +### 5.1 mtr does not have --warning ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.0009999; +--query_vertical show status like 'Slave_heartbeat_period'; + +# +# the actual max and min must be accepted +# +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4294967; +--query_vertical show status like 'Slave_heartbeat_period'; + +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.001; +--query_vertical show status like 'Slave_heartbeat_period'; + +reset slave; + +# +# A warning if period greater than slave_net_timeout +# +set @@global.slave_net_timeout= 5; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 5.001; +--query_vertical show status like 'Slave_heartbeat_period'; + +reset slave; + +# +# A warning if slave_net_timeout is set to less than the current HB period +# +set @@global.slave_net_timeout= 5; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 4; +--query_vertical show status like 'Slave_heartbeat_period'; +set @@global.slave_net_timeout= 3 /* must be a warning */; + +reset slave; + + +### +### checking no rotation +### + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings +# +# Even though master_heartbeat_period= 0.5 is 20 times less than +# @@global.slave_net_timeout= 10 in some circumstances master will +# not be able to send any heartbeat during the slave's net timeout +# and slave's relay log will rotate. +# The probability for such a scenario is pretty small so the following +# part is almost deterministic. +# + +connection slave; +set @@global.slave_net_timeout= 10; +--replace_result $MASTER_MYPORT MASTER_PORT +# no error this time but rather a warning +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root', master_heartbeat_period= 0.5; +--query_vertical show status like 'Slave_heartbeat_period'; + +start slave; + +connection master; +create table t1 (f1 int); + +#connection slave; +sync_slave_with_master; +let $slave_param= Relay_Log_File; +let $slave_param_value= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); + +# there is an explicit sleep lasting longer than slave_net_timeout +# to ensure that nothing will come to slave from master for that period. +# That would cause reconnecting and relaylog rotation w/o the fix i.e +# without a heartbeat received. + +real_sleep 15; + +# check (compare with the previous show's results) that no rotation happened +source include/check_slave_param.inc; + +### +### SHOW STATUS like 'Slave_heartbeat_period' and 'Slave_received_heartbeats' +### + +--query_vertical show status like 'Slave_heartbeat_period'; + +# +# proof that there has been received at least one heartbeat; +# The exact number of received heartbeat is an indeterministic value +# and therefore it's not recorded into results. +# + +let $slave_wait_param_counter= 300; +let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1); +# Checking the fact that at least one heartbeat is received +while (!$slave_value) +{ + dec $slave_wait_param_counter; + if (!$slave_wait_param_counter) + { + --echo ERROR: failed while waiting for slave parameter $slave_param: $slave_param_value + query_vertical show slave status; + SHOW STATUS like 'Slave_received_heartbeats'; + exit; + } + sleep 0.1; + let $slave_value= query_get_value("SHOW STATUS like 'Slave_received_heartbeats'", Value, 1); +} +--echo A heartbeat has been received by the slave +# cleanup + +connection master; +drop table t1; + +#connection slave; +sync_slave_with_master; +set @@global.slave_net_timeout= @restore_slave_net_timeout; + +--source include/stop_slave.inc + +--echo End of tests diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf new file mode 100644 index 00000000..f24de9ab --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.cnf @@ -0,0 +1,12 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates + +[mysqld.2] +log-slave-updates + +[mysqld.3] + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test new file mode 100644 index 00000000..e0fdf668 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_2slaves.test @@ -0,0 +1,124 @@ +############################################################# +# Author: Serge Kozlov <Serge.Kozlov@Sun.COM> +# Date: 02/19/2009 +# Purpose: Testing heartbeat for schema +# 1 master and 2 slaves +############################################################# +--let $rpl_topology= 1->2,1->3 +--source include/rpl_init.inc + +--let $rpl_connection_name= master +--let $rpl_server_number= 1 +--source include/rpl_connect.inc + +--let $rpl_connection_name= slave_1 +--let $rpl_server_number= 2 +--source include/rpl_connect.inc + +--let $rpl_connection_name= slave_2 +--let $rpl_server_number= 3 +--source include/rpl_connect.inc + +# +# Set different heartbeat periods for slaves +# +--connection slave_1 +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = 0.1; +--source include/start_slave.inc +--connection slave_2 +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD = 1; +--source include/start_slave.inc + +# +# Testing heartbeat for one master and two slaves +# + +# Check that heartbeat events sent to both slaves with correct periods +--connection slave_1 +let $status_var= slave_received_heartbeats; +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Slave has received heartbeat event +--connection slave_2 +let $status_var= slave_received_heartbeats; +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--let $assert_cond= [slave_1:SHOW STATUS LIKE "slave_received_heartbeats", Value, 1] > [slave_2:SHOW STATUS LIKE "slave_received_heartbeats", Value, 1] +--let $assert_text= slave_1 should have received more heartbeats than slave_2 +--source include/assert.inc +--echo + +# Create topology master->slave_2->slave_1 and check that slave_1 +# receives heartbeat while slave_2 gets data. + +# slave_2 was started w/o --log-slave-updates because slave_2 should +# not send data from master to slave_1 + +--source include/rpl_stop_slaves.inc +--let $rpl_topology= 1->3->2 +--source include/rpl_change_topology.inc +--source include/rpl_start_slaves.inc +--connection slave_1 +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc + +# Check heartbeat for new replication channel slave_2->slave +let $status_var= slave_received_heartbeats; +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo slave_1 has received heartbeat event +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT); +INSERT INTO t1 VALUES (1, 'on master', ''); +SHOW TABLES; +--sync_slave_with_master slave_2 +SHOW TABLES; +let $slave_2_pos_before= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1); +--sync_slave_with_master slave_1 +SHOW TABLES; +--connection master +--echo creating updates on master and send to slave_2 during 5 second +# Generate events on master and send to slave_2 during 5 second +let $i= 1; +let $j= 1; +let $k= 1; +--disable_query_log +while ($i) { + eval SET @c_text=REPEAT('1234567890', $j); + eval UPDATE t1 SET a=$j, c=@c_text; + --connection slave_2 + let $slave_2_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1); + if (`SELECT ($k*($slave_2_pos - $slave_2_pos_before)) > 0`) { + --connection slave_1 + let $slave_1_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); + let $k= 0; + let $time_before = `SELECT NOW()`; + } + if (`SELECT ((1-$k)*TIMESTAMPDIFF(SECOND,'$time_before',NOW())) > 5`) { + let $i= 0; + } + --connection master + inc $j; + sleep 0.1; +} +--enable_query_log +--connection slave_1 +--let $assert_cond= [SHOW STATUS LIKE "slave_received_heartbeats", Value, 1] > $slave_1_rcvd_heartbeats_before +--let $assert_text= slave_1 should have received heartbeats +--source include/assert.inc +--echo + +# +# Clean up +# +--echo *** Clean up *** +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf new file mode 100644 index 00000000..a4a291bc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.cnf @@ -0,0 +1,7 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates + +[mysqld.2] +log-slave-updates diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test new file mode 100644 index 00000000..f12c5921 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test @@ -0,0 +1,565 @@ +############################################################# +# Author: Serge Kozlov <Serge.Kozlov@Sun.COM> +# Date: 02/19/2009 +# Purpose: Testing basic functionality of heartbeat. +# Description: +# * Testing different values for slave_heartbeat_period. +# * How to affect various statements to slave_heartbeat_period +# * Various states of slave and heartbeat +# * Various states of master and heartbeat +# * Circular replication +############################################################# +--source include/master-slave.inc +# +# The test runs long and does not have any specifics to +# binlog_format. It is chosen therefore to run with MIXED mode +# in order to not slow down much `make test'. +# +--source include/have_binlog_format_mixed.inc +--echo + +# Set number of retries to connect to master +let $connect_retry= 20; + +--echo *** Preparing *** +--connection slave +--source include/stop_slave.inc +RESET SLAVE; +SET @restore_slave_net_timeout=@@global.slave_net_timeout; +let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1); +--disable_query_log +eval SET @restore_slave_heartbeat_timeout=$slave_heartbeat_timeout; +--enable_query_log + +--connection master +RESET MASTER; +SET @restore_slave_net_timeout=@@global.slave_net_timeout; +--echo + +# +# Test slave_heartbeat_period +# + +--connection slave + +# Default value of slave_heartbeat_timeout = slave_net_timeout/2 +--echo *** Default value *** +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root'; +let $slave_net_timeout= query_get_value(SHOW VARIABLES LIKE 'slave_net_timeout', Value, 1); +let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1); +let $result= query_get_value(SELECT $slave_net_timeout/$slave_heartbeat_timeout AS Result, Result, 1); +--echo slave_net_timeout/slave_heartbeat_timeout=$result +RESET SLAVE; +--echo + +# Reset slave set slave_heartbeat_timeout = slave_net_timeout/2 +--echo *** Reset slave affect *** +--disable_warnings +SET @@global.slave_net_timeout=30; +--enable_warnings +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; +RESET SLAVE; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +--echo + +# Check default value of slave_heartbeat_timeout if slave_net_timeout is changed +--echo *** Default value if slave_net_timeout changed *** +--disable_warnings +SET @@global.slave_net_timeout=50; +--enable_warnings +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SET @@global.slave_net_timeout=@restore_slave_net_timeout; +RESET SLAVE; +--echo + +# Set slave_net_timeout less than current value of slave_heartbeat_period +--echo *** Warning if updated slave_net_timeout < slave_heartbeat_timeout *** +let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1); +--replace_result $slave_heartbeat_timeout SLAVE_HEARTBEAT_TIMEOUT +eval SET @@global.slave_net_timeout=FLOOR($slave_heartbeat_timeout)-1; +SET @@global.slave_net_timeout=@restore_slave_net_timeout; +RESET SLAVE; +--echo + +# Set value of slave_heartbeat_period greater than slave_net_timeout +--echo *** Warning if updated slave_heartbeat_timeout > slave_net_timeout *** +let $slave_net_timeout= query_get_value(SHOW VARIABLES LIKE 'slave_net_timeout', Value, 1); +inc $slave_net_timeout; +--replace_result $MASTER_MYPORT MASTER_PORT $slave_net_timeout SLAVE_NET_TIMEOUT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=$slave_net_timeout; +RESET SLAVE; +--echo + +# Changing of slave_net_timeout shouldn't affect to current value of slave_heartbeat_period +--echo *** CHANGE MASTER statement only updates slave_heartbeat_period *** +--disable_warnings +SET @@global.slave_net_timeout=20; +--enable_warnings +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; +SHOW VARIABLES LIKE 'slave_net_timeout'; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SET @@global.slave_net_timeout=2*@@global.slave_net_timeout; +SHOW VARIABLES LIKE 'slave_net_timeout'; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SET @@global.slave_net_timeout=@restore_slave_net_timeout; +RESET SLAVE; +--echo + +# Master value of slave_net_timeout shouldn't affect to slave's slave_heartbeat_period +--echo *** Update slave_net_timeout on master *** +--connection master +--disable_warnings +SET @@global.slave_net_timeout=500; +--enable_warnings +--connection slave +SET @@global.slave_net_timeout=200; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry; +--source include/start_slave.inc +--connection master +--sync_slave_with_master +SHOW VARIABLES LIKE 'slave_net_timeout'; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SET @@global.slave_net_timeout=@restore_slave_net_timeout; +--source include/stop_slave.inc +RESET SLAVE; +--connection master +SET @@global.slave_net_timeout=@restore_slave_net_timeout; +--echo + +# Start/stop slave shouldn't change slave_heartbeat_period +--echo *** Start/stop slave *** +--connection slave +--disable_warnings +SET @@global.slave_net_timeout=100; +--enable_warnings +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=20; +--source include/start_slave.inc +--connection master +--sync_slave_with_master +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +--source include/stop_slave.inc +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +--echo + +# Reload slave shouldn't change slave_heartbeat_period +--echo *** Reload slave *** +--connection slave +--disable_warnings +SET @@global.slave_net_timeout=50; +--enable_warnings +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=30; +--let $rpl_server_number= 2 +--source include/rpl_restart_server.inc +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SET @restore_slave_net_timeout=@@global.slave_net_timeout; +--echo + +# Disable heartbeat +--echo *** Disable heartbeat *** +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SHOW STATUS LIKE 'slave_received_heartbeats'; +--source include/start_slave.inc +--connection master +--sync_slave_with_master +--sleep 2 +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SHOW STATUS LIKE 'slave_received_heartbeats'; +--source include/stop_slave.inc +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +SHOW STATUS LIKE 'slave_received_heartbeats'; +RESET SLAVE; +let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period', Value, 1); +--replace_result $slave_heartbeat_timeout SLAVE_HEARTBEAT_TIMEOUT +--eval SELECT $slave_heartbeat_timeout = 0 AS Result +--echo + +# +# Check limits for slave_heartbeat_timeout +# + +--echo *** Min slave_heartbeat_timeout *** +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.001; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.0009; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +RESET SLAVE; +--echo + +--echo *** Max slave_heartbeat_timeout *** +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967; +SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294968; +RESET SLAVE; +# Check double size of max allowed value for master_heartbeat_period +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=8589935; +RESET SLAVE; +# Check 2^32 +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967296; +RESET SLAVE; +--echo + +--echo *** Misc incorrect values *** +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_PARSE_ERROR +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='-1'; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_PARSE_ERROR +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='123abc'; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +--error ER_PARSE_ERROR +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=''; +RESET SLAVE; +--echo + +# +# Testing heartbeat +# + +# Check received heartbeat events for running slave +--echo *** Running slave *** +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc +--connection master +--sync_slave_with_master +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var= slave_received_heartbeats; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--echo + +# Check received heartbeat events for stopped slave +--echo *** Stopped slave *** +--source include/stop_slave.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +sleep 2; +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) AS Result, Result, 1); +--echo Number of received heartbeat events while slave stopped: $result +--echo + +# Check received heartbeat events for started slave +--echo *** Started slave *** +--source include/start_slave.inc +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--echo + +# Check received heartbeat events for stopped IO thread +--echo *** Stopped IO thread *** +--source include/stop_slave_io.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +sleep 2; +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) AS Result, Result, 1); +--echo Number of received heartbeat events while io thread stopped: $result +--echo + +# Check received heartbeat events for started IO thread +--echo *** Started IO thread *** +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--echo + +# Check received heartbeat events for stopped SQL thread +--echo *** Stopped SQL thread *** +--source include/stop_slave_sql.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +sleep 2; +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); +--echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result +--echo + +# Check received heartbeat events for started SQL thread +--echo *** Started SQL thread *** +START SLAVE SQL_THREAD; +--source include/wait_for_slave_sql_to_start.inc +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--echo + +# Check received heartbeat event for stopped SQL thread by error +--echo *** Stopped SQL thread by error *** +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10), c LONGTEXT); +--sync_slave_with_master +INSERT INTO t1 VALUES (1, 'on slave', NULL); +--connection master +INSERT INTO t1 VALUES (1, 'on master', NULL); +--connection slave +call mtr.add_suppression("Slave SQL.*Duplicate entry .1. for key .PRIMARY.. on query.* error.* 1062"); +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); +let $slave_errno= ER_DUP_ENTRY +--source include/wait_for_slave_sql_error.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +sleep 4; +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); +--echo Heartbeat events are received while sql thread stopped (1 means 'yes'): $result +--source include/stop_slave.inc +DROP TABLE t1; +--echo + +# Check received heartbeat events while master send events to slave +--echo *** Master send to slave *** +--connection master +# Create the event that will update table t1 every second +DELIMITER |; +CREATE EVENT e1 + ON SCHEDULE EVERY 1 SECOND + DO + BEGIN + UPDATE test.t1 SET a = a + 1 WHERE a < 10; + END| +DELIMITER ;| +--connection slave +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; +--source include/start_slave.inc +--connection master +# Enable scheduler +SET @@global.event_scheduler=1; + +--sync_slave_with_master +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); + +--connection master + +# Whether or not to send a heartbeat is decided on the master, based on +# whether the binlog was updated during the period or not. +# Even with the 1-second event, we cannot make the master to write binary +# logs (or execute SQL) in a timely manner. We can only check that they +# were executed in a timely manner, and if they were not, neutralize the +# heartbeat check on the slave. +# We will wait for 5 events, and keep checking 'Binlog_commits' on master. +# Time interval between consequent events will be measured. +# We can only expect that no heartbeats have been sent if the interval +# between events never exceeded MASTER_HEARTBEAT_PERIOD. +# If it has exceeded the value at least once, the slave can legitimately +# receive a heartbeat (but we cannot require it, because the delay +# could have occurred somewhere else, e.g. upon checking the status). +# So, if the delay is detected, we will signal slave to ignore possible +# heartbeats. + +let $possible_heartbeats= 0; +let $commits_to_wait= 5; +while ($commits_to_wait) +{ + let $tm= `SELECT UNIX_TIMESTAMP(NOW(3))`; + let $binlog_commits= query_get_value(SHOW STATUS LIKE 'Binlog_commits', Value, 1); + let $wait_condition= SELECT VARIABLE_VALUE > $binlog_commits FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME= 'BINLOG_COMMITS'; + --source include/wait_condition.inc + dec $commits_to_wait; + if (`SELECT UNIX_TIMESTAMP(NOW(3)) > $tm + 5`) + { + let $possible_heartbeats= 1; + let $commits_to_wait= 0; + } +} + +--connection slave +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= `SELECT CASE WHEN $possible_heartbeats THEN 'TRUE' WHEN $rcvd_heartbeats_after - $rcvd_heartbeats_before > 0 THEN 'FALSE' ELSE 'TRUE' END`; +--echo Received heartbeats meet expectations: $result +--connection master +DELETE FROM t1; +DROP EVENT e1; +--sync_slave_with_master +--echo + +# Check received heartbeat events while logs flushed on slave +--echo *** Flush logs on slave *** +STOP SLAVE; +RESET SLAVE; +DROP TABLE t1; +--connection master +DROP TABLE t1; +RESET MASTER; +--connection slave +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.5; +let $slave_param_comparison= =; +--source include/start_slave.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +# Flush logs every 0.1 second during 5 sec +--disable_query_log +let $i=100; +while ($i) { + FLUSH LOGS; + dec $i; + sleep 0.1; +} +--enable_query_log +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); +--echo Heartbeat events are received while rotation of relay logs (1 means 'yes'): $result +--echo + +# Use compressed protocol between master and slave +--echo *** Compressed protocol *** +--connection master +SET @@global.slave_compressed_protocol=1; +--connection slave +--source include/stop_slave.inc +RESET SLAVE; +SET @@global.slave_compressed_protocol=1; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var= slave_received_heartbeats; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received +SET @@global.slave_compressed_protocol=0; +--connection master +SET @@global.slave_compressed_protocol=0; +--echo + + +# Check received heartbeat events after reset of master +--echo *** Reset master *** +--connection slave +STOP SLAVE; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc +let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +--connection master +RESET MASTER; +--enable_query_log +--sync_slave_with_master +--sleep 2 +let $rcvd_heartbeats_after= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_before) > 0 AS Result, Result, 1); +--echo Heartbeat events are received after reset of master (1 means 'yes'): $result +--echo + +# Reloaded master should restore heartbeat +--echo *** Reload master *** +--connection slave +STOP SLAVE; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc +# Wait until slave_received_heartbeats will be incremented +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var= slave_received_heartbeats; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--let $rpl_server_number= 1 +--source include/rpl_restart_server.inc +# make sure IO thread has re-connected +# due to slow valgrind env the following wait_for_status may time out +--let $rpl_allow_error= 1 +--source include/wait_for_slave_io_to_start.inc +# Wait until slave_received_heartbeats will be incremented +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var= slave_received_heartbeats; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received +--echo + +# Circular replication: demonstrating bidirectional hearbeat flow +--echo *** Circular replication *** +# Configure circular replication +--source include/rpl_reset.inc +--source include/stop_slave.inc +--let $rpl_topology= 1->2->1 +--source include/rpl_change_topology.inc + +#--connection slave +#--source include/stop_slave.inc +#let $slave_binlog= query_get_value(SHOW MASTER STATUS, File, 1); +--connection master +#--replace_result $SLAVE_MYPORT SLAVE_PORT $slave_binlog SLAVE_BINLOG +#eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='$slave_binlog'; + +# BUG#12403008 RPL_HEARTBEAT_BASIC FAILS SPORADICALLY ON PUSHBUILD +# MASTER_HEARTBEAT_PERIOD had the default value (slave_net_timeout/2) +# so wait on "Heartbeat event received on master", that only waits for +# 1 minute, sometimes timeout before heartbeat arrives. +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=1; +--source include/start_slave.inc + +# Insert data on master and on slave and make sure that it replicated for both directions +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10)); +INSERT INTO t1 VALUES(1, 'on master'); +--save_master_pos +--connection slave +## set slave period 1/10 of master's +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.1; +--source include/start_slave.inc +--sync_with_master +INSERT INTO t1 VALUES(2, 'on slave'); +--sync_slave_with_master master +SELECT * FROM t1 ORDER BY a; +let $master_rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +--connection slave +SELECT * FROM t1 ORDER BY a; + +# Wait for heartbeat event on master +--connection master +let $status_var= slave_received_heartbeats; +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received on master + +# Wait heartbeat events on slave +--connection slave +let $status_var= slave_received_heartbeats; +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event received on slave +let $slave_rcvd_heartbeats= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); + +# +# Clean up and restore system variables +# +--echo *** Clean up *** +--connection master +#--source include/stop_slave.inc +DROP TABLE t1; +--sync_slave_with_master +SET @@global.slave_net_timeout=@restore_slave_net_timeout; + +#--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test new file mode 100644 index 00000000..bd66a249 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test @@ -0,0 +1,52 @@ +# Testing master to slave heartbeat protocol, test cases that need debug build. + +--source include/have_debug.inc +--source include/master-slave.inc + +connection slave; +--source include/stop_slave.inc +set @restore_slave_net_timeout= @@global.slave_net_timeout; +--disable_warnings +set @@global.slave_net_timeout= 10; +--enable_warnings + +### +### Checking the range +### + +# +# default period slave_net_timeout/2 +# +--query_vertical show status like 'Slave_heartbeat_period'; +SET @saved_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,simulate_slave_heartbeat_network_error"; +CALL mtr.add_suppression('SET @master_heartbeat_period to master failed with error'); +CALL mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again'); +--source include/start_slave.inc + + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings + +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); + +sync_slave_with_master; + +--connection slave +SELECT * FROM t1; + +connection master; +drop table t1; + +connection slave; +--source include/stop_slave.inc +--disable_warnings +SET GLOBAL debug_dbug=@saved_dbug; +set @@global.slave_net_timeout= @restore_slave_net_timeout; +--enable_warnings +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test b/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test new file mode 100644 index 00000000..810db4cc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_ssl.test @@ -0,0 +1,56 @@ +############################################################# +# Author: Serge Kozlov <Serge.Kozlov@Sun.COM> +# Date: 02/19/2009 +# Purpose: Testing basic functionality of heartbeat over SSL +############################################################# +--source include/have_ssl_communication.inc +--source include/master-slave.inc +--echo + +# +# Testing heartbeat over SSL +# + +# Heartbeat over SSL +--echo *** Heartbeat over SSL *** +--connection master +let $master_binlog= query_get_value(SHOW MASTER STATUS, File, 1); +--connection slave +--source include/stop_slave.inc +RESET SLAVE; +# Connect to master with SSL +--replace_result $MASTER_MYPORT MASTER_PORT $MYSQL_TEST_DIR MYSQL_TEST_DIR $master_binlog MASTER_BINLOG +eval CHANGE MASTER TO + MASTER_HOST='127.0.0.1', + MASTER_PORT=$MASTER_MYPORT, + MASTER_USER='root', + MASTER_HEARTBEAT_PERIOD=0.1, + MASTER_LOG_FILE='$master_binlog', + MASTER_SSL=1, + MASTER_SSL_CA='$MYSQL_TEST_DIR/std_data/cacert.pem', + MASTER_SSL_CERT='$MYSQL_TEST_DIR/std_data/client-cert.pem', + MASTER_SSL_KEY='$MYSQL_TEST_DIR/std_data/client-key.pem'; +--source include/start_slave.inc +# Check SSL state of slave +let $slave_ssl_status= query_get_value(SHOW SLAVE STATUS, Master_SSL_Allowed, 1); +--echo Master_SSL_Allowed: $slave_ssl_status +# Wait until hearbeat event will received +let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); +let $status_var= slave_received_heartbeats; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +--echo Heartbeat event has received +--echo + +# +# Clean up +# +--echo *** Clean up *** +--source include/stop_slave.inc +CHANGE MASTER TO + MASTER_SSL=0, + MASTER_SSL_CA='', + MASTER_SSL_CERT='', + MASTER_SSL_KEY=''; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_hrtime.test b/mysql-test/suite/rpl/t/rpl_hrtime.test new file mode 100644 index 00000000..98b08abe --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_hrtime.test @@ -0,0 +1,7 @@ +--source include/have_binlog_format_mixed_or_statement.inc + +--source suite/rpl/include/hrtime.inc + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 + diff --git a/mysql-test/suite/rpl/t/rpl_hrtime_row.test b/mysql-test/suite/rpl/t/rpl_hrtime_row.test new file mode 100644 index 00000000..e1d49f53 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_hrtime_row.test @@ -0,0 +1,3 @@ +--source include/have_binlog_format_row.inc +--source suite/rpl/include/hrtime.inc + diff --git a/mysql-test/suite/rpl/t/rpl_idempotency.test b/mysql-test/suite/rpl/t/rpl_idempotency.test new file mode 100644 index 00000000..12dec236 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_idempotency.test @@ -0,0 +1,107 @@ +# Testing various forms of idempotency for replication that should +# work the same way under statement based as under row based. + +source include/master-slave.inc; + +# Add suppression for expected warning(s) in slaves error log +call mtr.add_suppression("Slave SQL.*Can.t find record in .t[12].* error.* 1032"); +call mtr.add_suppression("Slave SQL.*Cannot delete or update a parent row: a foreign key constraint fails .* error.* 1451"); +call mtr.add_suppression("Slave SQL.*Cannot add or update a child row: a foreign key constraint fails .* error.* 1452"); +call mtr.add_suppression("Slave SQL.*Could not execute Write_rows event on table test.* Duplicate entry .1. for key .PRIMARY.* error.* 1062"); +call mtr.add_suppression("Can't find record in 't1'"); +call mtr.add_suppression("Can't find record in 't2'"); + +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT); +INSERT INTO t1 VALUES (-1),(-2),(-3); +INSERT INTO t2 VALUES (-1),(-2),(-3); +sync_slave_with_master; + +SET @old_slave_exec_mode= @@global.slave_exec_mode; +SET @@global.slave_exec_mode= IDEMPOTENT; + +# A delete for a row that does not exist, the statement is +# deliberately written to be idempotent for statement-based +# replication as well. We test this towards both a table with a +# primary key and without a primary key. + +connection slave; +DELETE FROM t1 WHERE a = -2; +DELETE FROM t2 WHERE a = -2; +connection master; +DELETE FROM t1 WHERE a = -2; +DELETE FROM t2 WHERE a = -2; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/check_slave_no_error.inc + +# An insert of a row that already exists. Since we are replacing the +# row if it already exists, the most apropriate representation is +# INSERT IGNORE. We only test this towards a table with a primary key, +# since the other case does not make sense. + +INSERT IGNORE INTO t1 VALUES (-2); +connection master; +INSERT IGNORE INTO t1 VALUES (-2); +SELECT * FROM t1 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; +--source include/check_slave_no_error.inc + + +# BUG#19958: RBR idempotency issue for UPDATE and DELETE + +# Statement-based and row-based replication have different behaviour +# when updating a row with an explicit WHERE-clause that matches +# exactly one row (or no row at all). For statement-based replication, +# the statement is idempotent since the first time it is executed, it +# will update exactly one row, and the second time it will not update +# any row at all. This was not the case for row-based replication, so +# we test under both row-based and statement-based replication both +# for tables with and without primary keys. + +connection slave; +UPDATE t1 SET a = 1 WHERE a = -1; +UPDATE t2 SET a = 1 WHERE a = -1; +connection master; +UPDATE t1 SET a = 1 WHERE a = -1; +UPDATE t2 SET a = 1 WHERE a = -1; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/check_slave_no_error.inc + +connection slave; +drop table t1, t2; + +connection master; +DROP TABLE t1, t2; +sync_slave_with_master; +--source include/check_slave_no_error.inc +create database d; +create database e; + +connection master; +create database d; +create database if not exists e; + +sync_slave_with_master; +--source include/check_slave_no_error.inc +drop database d; +drop database e; + +connection master; +drop database d; +drop database if exists e; +sync_slave_with_master; +--source include/check_slave_no_error.inc + +SET @@global.slave_exec_mode= @old_slave_exec_mode; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt new file mode 100644 index 00000000..e931bfbd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_grant-slave.opt @@ -0,0 +1 @@ +--replicate-wild-ignore-table=mysql.% diff --git a/mysql-test/suite/rpl/t/rpl_ignore_grant.test b/mysql-test/suite/rpl/t/rpl_ignore_grant.test new file mode 100644 index 00000000..58457c14 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_grant.test @@ -0,0 +1,55 @@ +# Test that GRANT is not replicated to the slave +# when --replicate-wild-ignore-table=mysql.% +# In BUG#980, this test would _randomly_ fail. + +source include/master-slave.inc; + +# do not be influenced by other tests. +connection master; +set sql_mode=""; +delete from mysql.user where user=_binary'rpl_ignore_grant'; +delete from mysql.db where user=_binary'rpl_ignore_grant'; +flush privileges; +--sync_slave_with_master +set sql_mode=""; +# as these DELETE were not replicated, we need to do them manually on the +# slave. +delete from mysql.user where user=_binary'rpl_ignore_grant'; +delete from mysql.db where user=_binary'rpl_ignore_grant'; +flush privileges; + +# test non-replication of GRANT +connection master; +grant select on *.* to rpl_ignore_grant@localhost; +grant drop on test.* to rpl_ignore_grant@localhost; +show grants for rpl_ignore_grant@localhost; +--sync_slave_with_master +--error 1141 #("no such grant for user") +show grants for rpl_ignore_grant@localhost; +# check it another way +select count(*) from mysql.user where user=_binary'rpl_ignore_grant'; +select count(*) from mysql.db where user=_binary'rpl_ignore_grant'; + +# test non-replication of SET PASSWORD +# first force creation of the user on slave (because as the user does not exist +# on slave, the SET PASSWORD may be replicated but silently do nothing; this is +# not what we want; we want it to be not-replicated). +grant select on *.* to rpl_ignore_grant@localhost; +connection master; +set password for rpl_ignore_grant@localhost=password("does it work?"); +--sync_slave_with_master +select password<>_binary'' from mysql.user where user=_binary'rpl_ignore_grant'; + +# clear what we have done, to not influence other tests. +connection master; +delete from mysql.user where user=_binary'rpl_ignore_grant'; +delete from mysql.db where user=_binary'rpl_ignore_grant'; +flush privileges; +--sync_slave_with_master +delete from mysql.user where user=_binary'rpl_ignore_grant'; +delete from mysql.db where user=_binary'rpl_ignore_grant'; +flush privileges; + +connection master; +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt new file mode 100644 index 00000000..e931bfbd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_revoke-slave.opt @@ -0,0 +1 @@ +--replicate-wild-ignore-table=mysql.% diff --git a/mysql-test/suite/rpl/t/rpl_ignore_revoke.test b/mysql-test/suite/rpl/t/rpl_ignore_revoke.test new file mode 100644 index 00000000..db20e807 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_revoke.test @@ -0,0 +1,52 @@ +# test verifies that REVOKE must not be replicated when +# slave server starts with --replicate-wild-ignore-table=mysql.% +# the option is set in rpl_ignore_revoke-slave.opt +# The first part of BUG#9483 for GRANT is checked by +# existed specific rpl_ignore_grant test case (BUG#980) + + +source include/master-slave.inc; + +### CLEAN-UP: create an account and manually duplicate it on the slave + +connection master; +grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; +revoke select on *.* from 'user_foo'@'%'; +select select_priv from mysql.user where user='user_foo' /* master:must be N */; + +sync_slave_with_master; +#connection slave; +grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; +revoke select on *.* from 'user_foo'@'%'; +select select_priv from mysql.user where user='user_foo' /* slave:must be N */; + + +### TEST + +#connection slave; +grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; +select select_priv from mysql.user where user='user_foo' /* slave:must be Y */; + +connection master; +revoke select on *.* from 'user_foo'; +select select_priv from mysql.user where user='user_foo' /* master:must be N */; + +sync_slave_with_master; +#connection slave; +select select_priv from mysql.user where user='user_foo' /* slave:must get Y */; + +### CLEAN-UP + +connection slave; +--disable_abort_on_error +revoke select on *.* FROM 'user_foo'; +--enable_abort_on_error + +connection master; +delete from mysql.user where user="user_foo"; +sync_slave_with_master; + +# Since changes to mysql.* are ignored, the revoke need to +# be done on slave as well +delete from mysql.user where user="user_foo"; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt new file mode 100644 index 00000000..3aabbb2e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_table-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 --replicate-wild-ignore-table=%.tmptbl% diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test new file mode 100644 index 00000000..19797b89 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test @@ -0,0 +1,198 @@ +let collation=utf8_unicode_ci; +source include/have_collation.inc; +source include/master-slave.inc; + +call mtr.add_suppression("Can't find record in 't.'"); +call mtr.add_suppression("Can't find record in 'global_priv'"); +call mtr.add_suppression("Can't find record in 'tables_priv'"); + +# +# BUG#16487 +# +# Requirement: +# Multi-updates on ignored tables should not fail even if the slave does +# not have the ignored tables. +# +# Note table t1, t2, and t3 are ignored in the option file to this test. +# + +--echo **** Test case for BUG#16487 **** +connection master; +CREATE TABLE test.t4 (a int); +CREATE TABLE test.t1 (a int); + +# Expect: The row must *not* by updated on slave, since t1 is ignored +UPDATE test.t4 NATURAL JOIN test.t1 SET t1.a=5; + +sync_slave_with_master; +SELECT * FROM t4; + +# Cleanup +connection master; +DROP TABLE t1; +DROP TABLE t4; + +sync_slave_with_master; + + +# +# Bug#25482 GRANT statements are not replicated if +# you use "replicate-ignore-table" +# + +--echo **** Test case for BUG#25482 **** +--echo **** Adding GRANTS on master **** + +connection master; +create table test.t1(a int); +create table test.t4(a int); + +set sql_mode=""; +# Simple user that should not replicate +GRANT SELECT ON test.t1 TO mysqltest1@localhost; + +# Partial replicate +GRANT INSERT ON test.t4 TO mysqltest2@localhost; +GRANT select, update, insert, references on t1 + to mysqltest2@localhost; + +# Partial replicate 2 +GRANT SELECT ON test.* TO mysqltest3@localhost; +GRANT INSERT ON test.t4 TO mysqltest3@localhost; +GRANT select(a), update(a), insert(a), references(a) on t4 + to mysqltest3@localhost; + +# Create another database and table +create database mysqltest2; +create table mysqltest2.t2 (id int); +# Create a grant that should replicate +GRANT SELECT ON mysqltest2.t2 TO mysqltest4@localhost IDENTIFIED BY 'pass'; + +# Create a grant manually +insert into mysql.global_priv (user, host) values ("mysqltest5", "somehost"); + +# Partial replicate 3 with *.* +GRANT SELECT ON *.* TO mysqltest6@localhost; +GRANT INSERT ON *.* TO mysqltest6@localhost; +GRANT INSERT ON test.* TO mysqltest6@localhost; +GRANT INSERT ON test.t1 TO mysqltest6@localhost; + +--sorted_result +show grants for mysqltest1@localhost; +--sorted_result +show grants for mysqltest2@localhost; +--sorted_result +show grants for mysqltest3@localhost; +--sorted_result +show grants for mysqltest4@localhost; +--sorted_result +show grants for mysqltest6@localhost; + +flush privileges; +show grants for mysqltest5@somehost; + +set sql_mode=""; +sync_slave_with_master; + +--echo **** Checking grants on slave **** + +# Check that grants are replicated to slave +--sorted_result +show grants for mysqltest2@localhost; +--sorted_result +show grants for mysqltest3@localhost; +--sorted_result +show grants for mysqltest4@localhost; +--sorted_result +show grants for mysqltest5@somehost; +--sorted_result +show grants for mysqltest6@localhost; + +# mysqltest1 should not be on slave +--error 1141 +show grants for mysqltest1@localhost; + +--echo **** Revoking grants on master **** +connection master; +REVOKE SELECT ON test.t1 FROM mysqltest1@localhost; +REVOKE SELECT ON mysqltest2.t2 FROM mysqltest4@localhost; +REVOKE select(a) on t4 + from mysqltest3@localhost; + +--sorted_result +show grants for mysqltest1@localhost; +--sorted_result +show grants for mysqltest3@localhost; +--sorted_result +show grants for mysqltest4@localhost; + +sync_slave_with_master; + +--echo **** Checking grants on slave **** + +# mysqltest1 should not be on slave +--error 1141 +show grants for mysqltest1@localhost; +show grants for mysqltest3@localhost; +show grants for mysqltest4@localhost; + +# Cleanup +# connection slave; +# BUG31552 changes idempotency is not default any longer +# In order the following `delete from mysql.user', +# where mysqltest1 does not exist on slave, +# to succeed on slave the mode is temporarily changed +set global slave_exec_mode='IDEMPOTENT'; +call mtr.add_suppression("Slave SQL.*Could not execute Delete_rows event on table mysql.* error.* 1032"); + +connection master; +drop table t1, mysqltest2.t2; +drop table t4; +drop database mysqltest2; +delete from mysql.user where user like "mysqltest%"; +delete from mysql.db where user like "mysqltest%"; +# +# BUG 27606 causes failure to replicate this statement +# move it to slave instead +#delete from mysql.tables_priv where user like "mysqltest%"; +delete from mysql.columns_priv where user like "mysqltest%"; + +sync_slave_with_master; +# bug#31552: do not restore the mode here but later in order +# to succeed with yet the following delete from mysql.tables_priv + +#BUG27606 +delete from mysql.tables_priv where user like "mysqltest%"; + +connection master; + +#BUG27606 +delete from mysql.tables_priv where user like "mysqltest%"; + +# +# bug#22877 replication character sets get out of sync +# using replicate-wild-ignore-table +# +connection master; +--disable_warnings +DROP TABLE IF EXISTS t5; +--enable_warnings +CREATE TABLE t5 ( + word varchar(50) collate utf8_unicode_ci NOT NULL default '' +) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +SET @@session.character_set_client=33,@@session.collation_connection=192; +CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY; +INSERT INTO t5 (word) VALUES ('TEST’'); +SELECT HEX(word) FROM t5; +sync_slave_with_master; +set @@global.slave_exec_mode= default; # bug#31552 comments above +connection slave; +SELECT HEX(word) FROM t5; +--error 1146 +SELECT * FROM tmptbl504451f4258$1; +connection master; +DROP TABLE t5; +flush privileges; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt b/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt new file mode 100644 index 00000000..177f89e0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_table_update-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.mysqltest_foo diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table_update.test b/mysql-test/suite/rpl/t/rpl_ignore_table_update.test new file mode 100644 index 00000000..6591dbbc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ignore_table_update.test @@ -0,0 +1,35 @@ +# This one assumes we are ignoring updates on table mysqltest_foo, but doing +# the ones on all other tables + +source include/master-slave.inc; +connection slave; + +# +# For this test we must be in the test database +# +use test; + +--disable_warnings +drop table if exists mysqltest_foo; +drop table if exists mysqltest_bar; +--enable_warnings + +create table mysqltest_foo (n int); +insert into mysqltest_foo values(4); +connection master; +use test; +create table mysqltest_foo (n int); +insert into mysqltest_foo values(5); +create table mysqltest_bar (m int); +insert into mysqltest_bar values(15); +create table t1 (k int); +insert into t1 values(55); +--sync_slave_with_master +select mysqltest_foo.n,mysqltest_bar.m,t1.k from mysqltest_foo,mysqltest_bar,t1; +connection master; +drop table mysqltest_foo,mysqltest_bar,t1; +--sync_slave_with_master +drop table mysqltest_foo,mysqltest_bar,t1; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_incident.test b/mysql-test/suite/rpl/t/rpl_incident.test new file mode 100644 index 00000000..4bb6477c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_incident.test @@ -0,0 +1 @@ +--source include/rpl_incident.inc diff --git a/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test b/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test new file mode 100644 index 00000000..104debe7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_incompatible_heartbeat.test @@ -0,0 +1,44 @@ +# ==== Purpose ==== +# +# Test verifies that slave IO thread can process heartbeat events with log_pos +# values higher than UINT32_MAX. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Stop slave threads. Configure a small master_heartbeat_period. +# 1 - Using debug points, simulate a huge binlog offset higher than +# UINT32_MAX on master. +# 2 - Start the slave and observe that slave IO thread is able to process +# the offset received through heartbeat event. +# +# ==== References ==== +# +# MDEV-16146: MariaDB slave stops with incompatible heartbeat +# +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +# Test simulates binarylog offsets higher than UINT32_MAX +--source include/have_64bit.inc +--source include/master-slave.inc + +--connection master +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@global.debug_dbug= 'd,simulate_pos_4G'; + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO MASTER_HEARTBEAT_PERIOD=0.001; +--source include/start_slave.inc + +--connection master +sleep 1; +SET @@GLOBAL.debug_dbug = @saved_dbug; +--sync_slave_with_master + +--connection master +CREATE TABLE t (f INT) ENGINE=INNODB; +INSERT INTO t VALUES (10); +DROP TABLE t; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt b/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt new file mode 100644 index 00000000..337e8a60 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_init_slave-slave.opt @@ -0,0 +1 @@ +--init-slave="set global max_connections=500" diff --git a/mysql-test/suite/rpl/t/rpl_init_slave.test b/mysql-test/suite/rpl/t/rpl_init_slave.test new file mode 100644 index 00000000..1803b146 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_init_slave.test @@ -0,0 +1,34 @@ +source include/master-slave.inc; + +# +# Test of init_slave variable +# + +set global max_connections=151; + +connection slave; +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +sync_slave_with_master; +show variables like 'init_slave'; +show variables like 'max_connections'; +reset master; +connection master; +show variables like 'init_slave'; +show variables like 'max_connections'; +sync_slave_with_master; +# Save variable value +set @my_global_init_connect= @@global.init_connect; +set global init_connect="set @c=1"; +show variables like 'init_connect'; +connection master; +sync_slave_with_master; + +# Restore changed global variable +set global init_connect= @my_global_init_connect; +set global max_connections= default; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_init_slave_errors.test b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test new file mode 100644 index 00000000..6f6ab7e8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test @@ -0,0 +1 @@ +--source include/rpl_init_slave_errors.inc diff --git a/mysql-test/suite/rpl/t/rpl_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_innodb-master.opt new file mode 100644 index 00000000..e27ee9b2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb-master.opt @@ -0,0 +1 @@ +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt new file mode 100644 index 00000000..e27ee9b2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt @@ -0,0 +1 @@ +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt new file mode 100644 index 00000000..e27ee9b2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt @@ -0,0 +1 @@ +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test new file mode 100644 index 00000000..12698263 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430.test @@ -0,0 +1,163 @@ +--source include/big_test.inc +--source include/have_innodb.inc +--source include/have_partition.inc +--source include/have_binlog_format_mixed_or_row.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +--vertical_results + +let $engine_type= 'innodb'; + +######## Creat Table Section ######### +use test; + +eval CREATE TABLE test.regular_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, + dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON + UPDATE CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB, + fkid MEDIUMINT, filler VARCHAR(255), + PRIMARY KEY(id)) ENGINE=$engine_type; + +eval CREATE TABLE test.bykey_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, + dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE + CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB, + fkid MEDIUMINT, filler VARCHAR(255), + PRIMARY KEY(id)) ENGINE=$engine_type + PARTITION BY KEY(id) partitions 5; + +eval CREATE TABLE test.byrange_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, + dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE + CURRENT_TIMESTAMP, user CHAR(255), uuidf LONGBLOB, + fkid MEDIUMINT, filler VARCHAR(255), + PRIMARY KEY(id)) ENGINE=$engine_type + PARTITION BY RANGE(id) + SUBPARTITION BY hash(id) subpartitions 2 + (PARTITION pa1 values less than (10), + PARTITION pa2 values less than (20), + PARTITION pa3 values less than (30), + PARTITION pa4 values less than (40), + PARTITION pa5 values less than (50), + PARTITION pa6 values less than (60), + PARTITION pa7 values less than (70), + PARTITION pa8 values less than (80), + PARTITION pa9 values less than (90), + PARTITION pa10 values less than (100), + PARTITION pa11 values less than MAXVALUE); + +######## Create SPs, Functions, Views and Triggers Section ############## + +delimiter |; +CREATE PROCEDURE test.proc_norm() +BEGIN + DECLARE ins_count INT DEFAULT 1000; + DECLARE del_count INT; + DECLARE cur_user VARCHAR(255); + DECLARE local_uuid VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SET local_time= NOW(); + SET cur_user= CURRENT_USER(); + SET local_uuid= UUID(); + + WHILE ins_count > 0 DO + INSERT INTO test.regular_tbl VALUES (NULL, NOW(), USER() , UUID(), + ins_count,'Going to test MBR for MySQL'); + SET ins_count = ins_count - 1; + END WHILE; + + SELECT MAX(id) FROM test.regular_tbl INTO del_count; + WHILE del_count > 0 DO + DELETE FROM test.regular_tbl WHERE id = del_count; + SET del_count = del_count - 2; + END WHILE; +END| + +CREATE PROCEDURE test.proc_bykey() +BEGIN + DECLARE ins_count INT DEFAULT 1000; + DECLARE del_count INT; + DECLARE cur_user VARCHAR(255); + DECLARE local_uuid VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SET local_time= NOW(); + SET cur_user= CURRENT_USER(); + SET local_uuid= UUID(); + + WHILE ins_count > 0 DO + INSERT INTO test.bykey_tbl VALUES (NULL, NOW(), USER() , UUID(), + ins_count,'Going to test MBR for MySQL'); + SET ins_count = ins_count - 1; + END WHILE; + + SELECT MAX(id) FROM test.bykey_tbl INTO del_count; + WHILE del_count > 0 DO + DELETE FROM test.bykey_tbl WHERE id = del_count; + SET del_count = del_count - 2; + END WHILE; +END| + +CREATE PROCEDURE test.proc_byrange() +BEGIN + DECLARE ins_count INT DEFAULT 1000; + DECLARE del_count INT; + DECLARE cur_user VARCHAR(255); + DECLARE local_uuid VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SET local_time= NOW(); + SET cur_user = CURRENT_USER(); + SET local_uuid=UUID(); + + WHILE ins_count > 0 DO + INSERT INTO test.byrange_tbl VALUES (NULL, NOW(), USER(), UUID(), + ins_count,'Going to test MBR for MySQL'); + SET ins_count = ins_count - 1; + END WHILE; + + SELECT MAX(id) FROM test.byrange_tbl INTO del_count; + WHILE del_count > 0 DO + DELETE FROM test.byrange_tbl WHERE id = del_count; + SET del_count = del_count - 2; + END WHILE; +END| + +delimiter ;| + +############ Finish Setup Section ################### + + +############ Test Section ################### + +begin; +CALL test.proc_norm(); +commit; +SELECT count(*) as "Master regular" FROM test.regular_tbl; +begin; +CALL test.proc_bykey(); +commit; +SELECT count(*) as "Master bykey" FROM test.bykey_tbl; +begin; +CALL test.proc_byrange(); +commit; +SELECT count(*) as "Master byrange" FROM test.byrange_tbl; + +--sync_slave_with_master +connection slave; +show create table test.byrange_tbl; +SELECT count(*) "Slave norm" FROM test.regular_tbl; +SELECT count(*) "Slave bykey" FROM test.bykey_tbl; +SELECT count(*) "Slave byrange" FROM test.byrange_tbl; + +###### CLEAN UP SECTION ############## + +connection master; +DROP PROCEDURE test.proc_norm; +DROP PROCEDURE test.proc_bykey; +DROP PROCEDURE test.proc_byrange; +DROP TABLE test.regular_tbl; +DROP TABLE test.bykey_tbl; +DROP TABLE test.byrange_tbl; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt new file mode 100644 index 00000000..e6685732 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.opt @@ -0,0 +1 @@ +--innodb-flush-log-at-trx-commit=2 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test new file mode 100644 index 00000000..9bfce618 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug30888.test @@ -0,0 +1,66 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_mixed_or_row.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +--vertical_results + +#let $engine_type= 'myisam'; +let $engine_type= 'innodb'; + +######## Creat Table Section ######### +use test; + +eval CREATE TABLE test.regular_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, + dt TIMESTAMP, user CHAR(255), uuidf LONGBLOB, + fkid MEDIUMINT, filler VARCHAR(255), + PRIMARY KEY(id)) ENGINE=$engine_type; + +######## Create SPs, Functions, Views and Triggers Section ############## + +delimiter |; +CREATE PROCEDURE test.proc_norm() +BEGIN + DECLARE ins_count INT DEFAULT 1000; + DECLARE del_count INT; + DECLARE cur_user VARCHAR(255); + DECLARE local_uuid VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SET local_time= NOW(); + SET cur_user= CURRENT_USER(); + SET local_uuid= UUID(); + + WHILE ins_count > 0 DO + INSERT INTO test.regular_tbl VALUES (NULL, NOW(), USER() , UUID(), + ins_count,'Going to test MBR for MySQL'); + SET ins_count = ins_count - 1; + END WHILE; + + SELECT MAX(id) FROM test.regular_tbl INTO del_count; + WHILE del_count > 0 DO + DELETE FROM test.regular_tbl WHERE id = del_count; + SET del_count = del_count - 2; + END WHILE; +END| + +delimiter ;| + +############ Finish Setup Section ################### + + +############ Test Section ################### + +CALL test.proc_norm(); + +--sync_slave_with_master + +###### CLEAN UP SECTION ############## + +connection master; +DROP PROCEDURE test.proc_norm; +DROP TABLE test.regular_tbl; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug68220.test b/mysql-test/suite/rpl/t/rpl_innodb_bug68220.test new file mode 100644 index 00000000..1e4f40a0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug68220.test @@ -0,0 +1,53 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# +# Bug#68220: innodb_rows_updated is misleading on slave when *info_repository=TABLE +# + +# created all the base variables at the beginning at the test +--connection master +select variable_value into @master_rows_read from information_schema.global_status where variable_name = 'innodb_rows_read'; +select variable_value into @master_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated'; +select variable_value into @master_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted'; +select variable_value into @master_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted'; +select variable_value into @master_system_rows_read from information_schema.global_status where variable_name = 'innodb_system_rows_read'; +select variable_value into @master_system_rows_updated from information_schema.global_status where variable_name = 'innodb_system_rows_updated'; +select variable_value into @master_system_rows_deleted from information_schema.global_status where variable_name = 'innodb_system_rows_deleted'; +select variable_value into @master_system_rows_inserted from information_schema.global_status where variable_name = 'innodb_system_rows_inserted'; + +--connection slave +select variable_value into @slave_rows_read from information_schema.global_status where variable_name = 'innodb_rows_read'; +select variable_value into @slave_rows_updated from information_schema.global_status where variable_name = 'innodb_rows_updated'; +select variable_value into @slave_rows_deleted from information_schema.global_status where variable_name = 'innodb_rows_deleted'; +select variable_value into @slave_rows_inserted from information_schema.global_status where variable_name = 'innodb_rows_inserted'; +select variable_value into @slave_system_rows_read from information_schema.global_status where variable_name = 'innodb_system_rows_read'; +select variable_value into @slave_system_rows_updated from information_schema.global_status where variable_name = 'innodb_system_rows_updated'; +select variable_value into @slave_system_rows_deleted from information_schema.global_status where variable_name = 'innodb_system_rows_deleted'; +select variable_value into @slave_system_rows_inserted from information_schema.global_status where variable_name = 'innodb_system_rows_inserted'; + +--connection master +CREATE DATABASE testdb; +USE testdb; +CREATE TABLE testdb.t1 (i int NOT NULL PRIMARY KEY) ENGINE=InnoDB; + +# insert a row and show counters on master and slave +INSERT INTO testdb.t1 VALUES (1); +--source suite/rpl/include/rpl_innodb_rows_counters.inc + +# update the row and show counters on master and slave +UPDATE t1 SET i=2 WHERE i=1; +--sync_slave_with_master +--source suite/rpl/include/rpl_innodb_rows_counters.inc + +# delete the row and show counters on master and slave +DELETE FROM t1 WHERE i=2; +--source suite/rpl/include/rpl_innodb_rows_counters.inc + +# clean the test +DROP TABLE t1; +DROP DATABASE testdb; +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test b/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test new file mode 100644 index 00000000..5147e67c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_mixed_ddl.test @@ -0,0 +1,9 @@ +######################################### +# Purpose: testing the replication in mixed mode +# Requirements: define binlog format for mysqld as in example below: +# ./mysql-test-run.pl --mysqld=--binlog-format=mixed +######################################### +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +let $engine_type= innodb; +--source suite/rpl/include/rpl_mixed_ddl.inc diff --git a/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test b/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test new file mode 100644 index 00000000..d04ced0f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_innodb_mixed_dml.test @@ -0,0 +1,9 @@ +######################################### +# Purpose: testing the replication in mixed mode +# Requirements: define binlog format for mysqld as in example below: +# ./mysql-test-run.pl --mysqld=--binlog-format=mixed +######################################### +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +let $engine_type= innodb; +--source suite/rpl/include/rpl_mixed_dml.inc diff --git a/mysql-test/suite/rpl/t/rpl_insert.test b/mysql-test/suite/rpl/t/rpl_insert.test new file mode 100644 index 00000000..48814508 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_insert.test @@ -0,0 +1,45 @@ +--echo # +--echo # Bug#20821: INSERT DELAYED fails to write some rows to binlog +--echo # + +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/master-slave.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +--disable_warnings +CREATE SCHEMA IF NOT EXISTS mysqlslap; +USE mysqlslap; +--enable_warnings + +CREATE TABLE t1 (id INT, name VARCHAR(64)) ENGINE=MyISAM; + +sync_slave_with_master; +connection master; + +let $query = "INSERT DELAYED INTO t1 VALUES (1, 'Dr. No'), (2, 'From Russia With Love'), (3, 'Goldfinger'), (4, 'Thunderball'), (5, 'You Only Live Twice')"; +--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=200 --query=$query --delimiter=";" + +# Wait until all the 5000 inserts has been inserted into the table +let $wait_condition= SELECT COUNT(*) = 5000 FROM mysqlslap.t1; +source include/wait_condition.inc; +SELECT COUNT(*) FROM mysqlslap.t1; + +connection slave; +# Wait until all the 5000 inserts has been inserted into the table +let $wait_condition= SELECT COUNT(*) = 5000 FROM mysqlslap.t1; +source include/wait_condition.inc; +SELECT COUNT(*) FROM mysqlslap.t1; + +--echo # +--echo # Cleanup +--echo # + +connection master; +USE test; +DROP SCHEMA mysqlslap; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_insert_delayed.test b/mysql-test/suite/rpl/t/rpl_insert_delayed.test new file mode 100644 index 00000000..6a88899f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_insert_delayed.test @@ -0,0 +1,5 @@ +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/master-slave.inc +--source include/rpl_insert_delayed.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_insert_id.test b/mysql-test/suite/rpl/t/rpl_insert_id.test new file mode 100644 index 00000000..c9d84049 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_insert_id.test @@ -0,0 +1,6 @@ +################################# +# Wrapper for rpl_insert_id.test# +################################# +-- source include/have_innodb.inc +let $engine_type=myisam; +-- source include/rpl_insert_id.test diff --git a/mysql-test/suite/rpl/t/rpl_insert_id_pk.test b/mysql-test/suite/rpl/t/rpl_insert_id_pk.test new file mode 100644 index 00000000..d9ba2a2b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_insert_id_pk.test @@ -0,0 +1,6 @@ +################################# +# Wrapper for rpl_insert_id.test# +################################# +-- source include/have_innodb.inc +let $engine_type=innodb; +-- source include/rpl_insert_id_pk.test diff --git a/mysql-test/suite/rpl/t/rpl_insert_ignore.test b/mysql-test/suite/rpl/t/rpl_insert_ignore.test new file mode 100644 index 00000000..2940ad16 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_insert_ignore.test @@ -0,0 +1,15 @@ +##################################### +# Wrapper for rpl_insert_ignore.test# +##################################### +-- source include/have_innodb.inc +-- source include/master-slave.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +-- let $engine_type=innodb +-- source include/rpl_insert_ignore.test + +-- let $engine_type=myisam +-- source include/rpl_insert_ignore.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt new file mode 100644 index 00000000..96f0ce3f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_invoked_features-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_invoked_features.test b/mysql-test/suite/rpl/t/rpl_invoked_features.test new file mode 100644 index 00000000..91391cf8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_invoked_features.test @@ -0,0 +1,311 @@ +######################################### +# Author: Serge Kozlov skozlov@mysql.com +# Date: 04/25/2007 +# Purpose: Testing Invocation and Invoked +# Features for Replication. +######################################### + +--source include/have_innodb.inc +--source include/master-slave.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +# --disable_warnings/--enable_warnings added before/after query +# if one uses UUID() function because we need to avoid warnings +# for STATEMENT binlog format + +# Non-transactional engine +--let $engine_type= myisam + +# Transactional engine +--let $engine_type2= innodb + + +# +# Clean up +# + +USE test; +--disable_warnings +DROP VIEW IF EXISTS v1,v11; +DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p11; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e11; +--enable_warnings + + +# +# Prepare objects (tables etc) +# + +# Create tables + +--echo +eval CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type; +INSERT INTO t1 VALUES (1,1,'1'); +--disable_warnings +INSERT INTO t1 VALUES (2,2,UUID()); +--enable_warnings +eval CREATE TABLE t2 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type; +INSERT INTO t2 VALUES (1,1,'1'); +--disable_warnings +INSERT INTO t2 VALUES (2,2,UUID()); +--enable_warnings + +eval CREATE TABLE t11 (a INT NOT NULL PRIMARY KEY, b INT, c VARCHAR(64)) ENGINE=$engine_type2; +INSERT INTO t11 VALUES (1,1,'1'); +--disable_warnings +INSERT INTO t11 VALUES (2,2,UUID()); +--enable_warnings +eval CREATE TABLE t12 (a INT UNIQUE, b INT, c VARCHAR(64)) ENGINE=$engine_type2; +INSERT INTO t12 VALUES (1,1,'1'); +--disable_warnings +INSERT INTO t12 VALUES (2,2,UUID()); +--enable_warnings + +# Create invoked features +--echo +# Create view for tables t1,t11 +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v11 AS SELECT * FROM t11; + +# Create triggers for t1,t11 +DELIMITER |; + +CREATE TRIGGER t1_tr1 BEFORE INSERT ON t1 FOR EACH ROW +BEGIN + INSERT INTO t2 VALUES (NEW.a, NEW.b, NEW.c); + INSERT INTO t3 VALUES (NEW.a, NEW.b, NEW.c); +END| + +CREATE TRIGGER t1_tr2 BEFORE UPDATE ON t1 FOR EACH ROW +BEGIN + UPDATE t2 SET c = ''; + UPDATE t3 SET c = ''; +END| + +CREATE TRIGGER t11_tr1 BEFORE INSERT ON t11 FOR EACH ROW +BEGIN + INSERT INTO t12 VALUES (NEW.a, NEW.b, NEW.c); + INSERT INTO t13 VALUES (NEW.a, NEW.b, NEW.c); +END| + +CREATE TRIGGER t11_tr2 BEFORE UPDATE ON t11 FOR EACH ROW +BEGIN + UPDATE t12 SET c = ''; + UPDATE t13 SET c = ''; +END| + +# Create events which will run every 1 sec +CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO +BEGIN + ALTER EVENT e1 DISABLE; + CALL p1(10, ''); +END| + +CREATE EVENT e11 ON SCHEDULE EVERY 1 SECOND DISABLE DO +BEGIN + ALTER EVENT e11 DISABLE; + CALL p11(10, ''); +END| + +# Create functions and procedures used for events +CREATE FUNCTION f1 (x INT) RETURNS VARCHAR(64) +BEGIN + IF x > 5 THEN + RETURN UUID(); + END IF; + RETURN ''; +END| + +CREATE FUNCTION f2 (x INT) RETURNS VARCHAR(64) +BEGIN + RETURN f1(x); +END| + +CREATE PROCEDURE p1 (IN x INT, IN y VARCHAR(64)) +BEGIN + INSERT IGNORE INTO t1 VALUES (x,x,y); +END| + +CREATE PROCEDURE p11 (IN x INT, IN y VARCHAR(64)) +BEGIN + INSERT IGNORE INTO t11 VALUES (x,x,y); +END| + +DELIMITER ;| + + +# +# Start test case +# + +# Do some actions for non-transactional tables +--echo +CREATE TABLE t3 SELECT * FROM v1; +INSERT INTO t1 VALUES (3,3,''); +UPDATE t1 SET c='2' WHERE a = 1; +--disable_warnings +INSERT INTO t1 VALUES(4,4,f1(4)); +--enable_warnings +INSERT INTO t1 VALUES (100,100,''); +--disable_warnings +CALL p1(5, UUID()); +--enable_warnings +INSERT INTO t1 VALUES (101,101,''); +--disable_warnings +INSERT INTO t1 VALUES(6,6,f1(6)); +--enable_warnings +INSERT INTO t1 VALUES (102,102,''); +--disable_warnings +INSERT INTO t1 VALUES(7,7,f2(7)); +--enable_warnings +INSERT INTO t1 VALUES (103,103,''); + +# Do some actions for transactional tables +--echo +--disable_warnings +CREATE TABLE t13 SELECT * FROM v11; +INSERT INTO t11 VALUES (3,3,''); +UPDATE t11 SET c='2' WHERE a = 1; +INSERT INTO t11 VALUES(4,4,f1(4)); +INSERT INTO t11 VALUES (100,100,''); +CALL p11(5, UUID()); +INSERT INTO t11 VALUES (101,101,''); +INSERT INTO t11 VALUES(6,6,f1(6)); +INSERT INTO t11 VALUES (102,102,''); +INSERT INTO t11 VALUES(7,7,f2(7)); +INSERT INTO t11 VALUES (103,103,''); +--enable_warnings + +# Scheduler is on +--echo +# Temporally events fire sequentally due Bug#29020. +SET GLOBAL EVENT_SCHEDULER = on; +# Wait while events will executed +ALTER EVENT e1 ENABLE; +let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE t1.a = 10; +--source include/wait_condition.inc +ALTER EVENT e11 ENABLE; +let $wait_condition= SELECT COUNT(*) = 1 FROM t11 WHERE t11.a = 10; +--source include/wait_condition.inc +SET GLOBAL EVENT_SCHEDULER = off; + +# Check original objects +--echo +--sorted_result +SHOW TABLES LIKE 't%'; +--sorted_result +SELECT table_name FROM information_schema.views WHERE table_schema='test'; +--sorted_result +SELECT trigger_name, event_manipulation, event_object_table FROM information_schema.triggers WHERE trigger_schema='test'; +--sorted_result +SELECT routine_type, routine_name FROM information_schema.routines WHERE routine_schema='test'; +--sorted_result +SELECT event_name, status FROM information_schema.events WHERE event_schema='test'; + +# Check original data +--echo +SELECT COUNT(*) FROM t1; +SELECT a,b FROM t1 ORDER BY a; +SELECT COUNT(*) FROM t2; +SELECT a,b FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +SELECT a,b FROM t3 ORDER BY a; +SELECT a,b FROM v1 ORDER BY a; +SELECT COUNT(*) FROM t11; +SELECT a,b FROM t11 ORDER BY a; +SELECT COUNT(*) FROM t12; +SELECT a,b FROM t12 ORDER BY a; +SELECT COUNT(*) FROM t13; +SELECT a,b FROM t13 ORDER BY a; +SELECT a,b FROM v11 ORDER BY a; + +--sync_slave_with_master slave + +# Check replicated objects +--echo +--sorted_result +SHOW TABLES LIKE 't%'; +--sorted_result +SELECT table_name FROM information_schema.views WHERE table_schema='test'; +--sorted_result +SELECT trigger_name, event_manipulation, event_object_table FROM information_schema.triggers WHERE trigger_schema='test'; +--sorted_result +SELECT routine_type, routine_name FROM information_schema.routines WHERE routine_schema='test'; +--sorted_result +SELECT event_name, status FROM information_schema.events WHERE event_schema='test'; + +# Check replicated data +--echo +SELECT COUNT(*) FROM t1; +SELECT a,b FROM t1 ORDER BY a; +SELECT COUNT(*) FROM t2; +SELECT a,b FROM t2 ORDER BY a; +SELECT COUNT(*) FROM t3; +SELECT a,b FROM t3 ORDER BY a; +SELECT a,b FROM v1 ORDER BY a; +SELECT COUNT(*) FROM t11; +SELECT a,b FROM t11 ORDER BY a; +SELECT COUNT(*) FROM t12; +SELECT a,b FROM t12 ORDER BY a; +SELECT COUNT(*) FROM t13; +SELECT a,b FROM t13 ORDER BY a; +SELECT a,b FROM v11 ORDER BY a; + +# Remove UUID() before comparing and sort tables + +--connection master +--echo +UPDATE t1 SET c=''; +UPDATE t2 SET c=''; +UPDATE t3 SET c=''; +--disable_warnings +UPDATE t11 SET c=''; +--enable_warnings +UPDATE t12 SET c=''; +UPDATE t13 SET c=''; + +ALTER TABLE t3 ORDER BY a; +ALTER TABLE t13 ORDER BY a; + +--sync_slave_with_master slave + +# Compare a data from master and slave +--echo +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql +--diff_files $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql + + +# +# Clean up +# + +# Remove dumps +--echo +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_master.sql +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_invoked_features_slave.sql + +# Remove tables,views,procedures,functions +--connection master +--echo +DROP VIEW IF EXISTS v1,v11; +DROP TABLE IF EXISTS t1,t2,t3,t11,t12,t13; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p11; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e11; + +--sync_slave_with_master slave + +# End 5.1 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf new file mode 100644 index 00000000..00e2637d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix.test b/mysql-test/suite/rpl/t/rpl_ip_mix.test new file mode 100644 index 00000000..63c5fa92 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix.test @@ -0,0 +1,48 @@ +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, master: --bind-address=::, slave: --bind-address=0.0.0.0 +# (see corresponding cnf file) +# +--source include/check_ipv6.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +connect (master,$IPv6,root,,test,$MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +connection master; +reset master; +source include/show_master_status.inc; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host + +# clean up +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; +--connection slave +reset slave all; diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf new file mode 100644 index 00000000..306df437 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ip_mix2.test b/mysql-test/suite/rpl/t/rpl_ip_mix2.test new file mode 100644 index 00000000..3fff54e5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ip_mix2.test @@ -0,0 +1,49 @@ +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, master: --bind-address=0.0.0.0, slave: --bind-address=:: +# (see corresponding cnf file) +# +--source include/check_ipv6.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ip_mix2.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ip_mix2.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +connect (slave,$IPv6,root,,test,$SLAVE_MYPORT); +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host + +# clean up +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; +connection slave; +reset slave all; diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf new file mode 100644 index 00000000..b646a408 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= 0.0.0.0 + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= 0.0.0.0 + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test new file mode 100644 index 00000000..d17b32c3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv4_as_ipv6.test @@ -0,0 +1,63 @@ +# Test of ipv4 (127.0.0.1) in ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, --bind-address=0.0.0.0 (see corresponding cnf file) +# for master and slave +# +--source include/have_ipv4_mapped.inc +--source include/have_log_bin.inc + +let $IPv6= 127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0::0000:FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +#let $IPv6= ::FFFF:127.0.0.1/96; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= ::FFFF:127.0.0.1; +--echo #################### IP: $IPv6 ########################### +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0000:0000:0:0000:FFFF:127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host + +# clean up +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.cnf b/mysql-test/suite/rpl/t/rpl_ipv6.cnf new file mode 100644 index 00000000..c657e7c5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6.cnf @@ -0,0 +1,56 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf +!include include/default_client.cnf + +[mysqld.1] + +# Run the master.sh script before starting this process +#!run-master-sh + +log-bin= master-bin + +loose-innodb + +skip-name-resolve +bind-address= :: + + +[mysqld.2] +# Run the slave.sh script before starting this process +#!run-slave-sh + +# Append <testname>-slave.opt file to the list of argument used when +# starting the mysqld +#!use-slave-opt + +log-bin= slave-bin +relay-log= slave-relay-bin + +init-rpl-role= slave +log-slave-updates +master-retry-count= 10 + +# Values reported by slave when it connect to master +# and shows up in SHOW SLAVE STATUS; +report-host= localhost +report-port= @mysqld.2.port +report-user= root + +skip-slave-start +skip-name-resolve +bind-address= :: + +# Directory where slaves find the dumps generated by "load data" +# on the server. The path need to have constant length otherwise +# test results will vary, thus a relative path is used. +slave-load-tmpdir= ../../tmp + +loose-innodb + +[ENV] +MASTER_MYPORT= @mysqld.1.port +MASTER_MYSOCK= @mysqld.1.socket + +SLAVE_MYPORT= @mysqld.2.port +SLAVE_MYSOCK= @mysqld.2.socket + diff --git a/mysql-test/suite/rpl/t/rpl_ipv6.test b/mysql-test/suite/rpl/t/rpl_ipv6.test new file mode 100644 index 00000000..f3795832 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ipv6.test @@ -0,0 +1,49 @@ +# Test of ipv6 format, especially "change master host=..." +# Options: --skip-name-resolve, --bind-address=:: (see corresponding cnf file) +# for master and slave. +# +--source include/check_ipv6.inc +# Can't be tested with windows due to mixed format like 0::0000:FFFF:127.0.0.1 +--source include/not_windows.inc +--source include/have_log_bin.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= ::1/128; +#--echo #################### IP: $IPv6 ########################### +#--source include/rpl_ipv6.inc + +let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= 0:0:0:0:0:0:0:1; +--echo #################### IP: $IPv6 ########################### +--source include/rpl_ipv6.inc + +let $IPv6= ::1; +--echo #################### IP: $IPv6 mix ####################### +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT); +connection master; +reset master; +source include/show_master_status.inc; +save_master_pos; +connection slave; +reset slave; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='$IPv6'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='127.0.0.1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host +eval change master to master_host='0:0:0:0:0:0:0:1'; +let $master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1); +--echo Master-Host: $master_host + +# clean up +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root'; diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt b/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt new file mode 100644 index 00000000..dcc136e1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl-master.opt @@ -0,0 +1 @@ +--loose-debug-dbug=d,debug_lock_before_query_log_event diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test new file mode 100644 index 00000000..6415b3e8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test @@ -0,0 +1,349 @@ +# ==== Purpose ==== +# +# This test check if DDL statements are correctly binlogged when the +# thread is killed +# +# ==== Method ==== +# +# Start a DDL query and kill it, check if the error code of the binlog +# event is correct. +# +# DDL statements tested: +# CREATE/ALTER/RENAME/DROP DATABASE +# CREATE/ALTER/DROP EVENT +# CREATE/ALTER/DROP FUNCTION +# CREATE/ALTER/DROP PROCEDURE +# CREATE/ALTER/DROP SERVER +# CREATE/ALTER/RENAME/DROP TABLE +# CREATE/DROP TRIGGER +# CREATE/ALTER/DROP VIEW +# +# ==== Bugs ===== +# +# BUG#37145 +# +# ==== TODO ==== +# +# There are some part of the test are temporarily disabled because of +# the following bugs, please enable then once they get fixed: +# - BUG#22473427 +# - Bug#22587377 + +# Temporarily disabled on Windows due to bug #47638 +--source include/not_windows.inc + +source include/have_debug.inc; +source include/master-slave.inc; + +# Use the DBUG_SYNC_POINT to make sure the thread running the DDL is +# waiting before creating the query log event + +let $debug_lock= "debug_lock.before_query_log_event"; + +######## INITIALIZATION ######## + +disable_warnings; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e2; +DROP EVENT IF EXISTS e3; +DROP EVENT IF EXISTS e4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP SERVER IF EXISTS s1; +DROP SERVER IF EXISTS s2; +DROP SERVER IF EXISTS s3; +DROP SERVER IF EXISTS s4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP TRIGGER IF EXISTS tr3; +DROP TRIGGER IF EXISTS tr4; +enable_warnings; + +CREATE DATABASE d1; + +CREATE EVENT e1 + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY + DO INSERT INTO test.t1 VALUES (1); + +CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC + RETURN 1; + +DELIMITER //; +CREATE PROCEDURE p1 (OUT rows_cnt INT) + BEGIN + SELECT COUNT(*) INTO rows_cnt FROM t1; + END; + // +DELIMITER ;// + +CREATE SERVER s1 +FOREIGN DATA WRAPPER mysql +OPTIONS (USER 'user1', HOST '192.168.1.106', DATABASE 'test'); + +CREATE TABLE t1 (a int); +CREATE TABLE t3 (a int); + +DELIMITER //; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 + FOR EACH ROW BEGIN + DELETE FROM t4 WHERE a=NEW.a; + END; + // +DELIMITER ;// + +CREATE INDEX i1 ON t1 (a); + +CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100; + +sync_slave_with_master; + +connection master1; +let $connection_name= master1; +let $connection_id= `SELECT CONNECTION_ID()`; + +connection master; + +# This will block the execution of a statement at the DBUG_SYNC_POINT +# with given lock name +if ($debug_lock) +{ + disable_query_log; + disable_result_log; + eval SELECT IS_FREE_LOCK($debug_lock); + eval SELECT GET_LOCK($debug_lock, 10); + eval SELECT IS_FREE_LOCK($debug_lock); + enable_query_log; + enable_result_log; +} + +######## START TEST ######## + +connection master1; + +disable_warnings; + +######## DATABASE ######## + +let $rpl_diff_statement= SELECT schema_name FROM information_schema.schemata + WHERE schema_name LIKE \'d%\' ORDER BY schema_name; + +send CREATE DATABASE d2; +source include/kill_query_and_diff_master_slave.inc; + +send ALTER DATABASE d1 + DEFAULT CHARACTER SET = 'utf8'; +source include/kill_query_and_diff_master_slave.inc; + +send DROP DATABASE d1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP DATABASE IF EXISTS d2; +source include/kill_query_and_diff_master_slave.inc; + +######## EVENT ######## + +let $rpl_diff_statement= SELECT event_name, event_body, execute_at + FROM information_schema.events where event_name like \'e%\' + ORDER BY event_name; + +send CREATE EVENT e2 + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY + DO INSERT INTO test.t1 VALUES (2); +source include/kill_query_and_diff_master_slave.inc; + +# Temporarily disabled,see Bug#22587377-RPL.RPL_KILLED_DDL +# FAILS SPORADICALLY ON PB2 IN 5.5 AND 5.6 +#send ALTER EVENT e1 +# ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY; +#source include/kill_query_and_diff_master_slave.inc; + +send DROP EVENT e1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP EVENT IF EXISTS e2; +source include/kill_query_and_diff_master_slave.inc; + +######## FUNCTION ######## + +--let $rpl_diff_statement= SHOW FUNCTION STATUS LIKE \'f%\' + +send CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC + RETURN 1; +source include/kill_query_and_diff_master_slave.inc; + +send ALTER FUNCTION f1 SQL SECURITY INVOKER; +source include/kill_query_and_diff_master_slave.inc; + +# function f1 probably does not exist because the ALTER query was +# killed +send DROP FUNCTION f1; +source include/kill_query_and_diff_master_slave.inc; + +# function f2 probably does not exist because the CREATE query was +# killed +send DROP FUNCTION IF EXISTS f2; +source include/kill_query_and_diff_master_slave.inc; + +######## PROCEDURE ######## + +--let $rpl_diff_statement= SHOW PROCEDURE STATUS LIKE \'p%\' + +DELIMITER //; +send CREATE PROCEDURE p2 (OUT rows_cnt INT) + BEGIN + SELECT COUNT(*) INTO rows_cnt FROM t2; + END; + // +DELIMITER ;// +source include/kill_query_and_diff_master_slave.inc; + +send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows_cnt of table t1'; +source include/kill_query_and_diff_master_slave.inc; + +send DROP PROCEDURE p1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP PROCEDURE IF EXISTS p2; +source include/kill_query_and_diff_master_slave.inc; + +######## TABLE ######## + +--let $rpl_diff_statement= SHOW TABLES LIKE \'t%\' + +send CREATE TABLE t2 (b int); +source include/kill_query_and_diff_master_slave.inc; + +send ALTER TABLE t1 ADD (d int); +source include/kill_query_and_diff_master_slave.inc; + +send RENAME TABLE t3 TO t4; +source include/kill_query_and_diff_master_slave.inc; + +######## INDEX ######## + +--let $rpl_diff_statement= SHOW INDEX FROM t1 + +send CREATE INDEX i2 on t1 (a); +source include/kill_query_and_diff_master_slave.inc; + +send DROP INDEX i1 on t1; +source include/kill_query_and_diff_master_slave.inc; + + +######## SERVER ######## + +# Temporarily disabled, see Bug #22473427 - DROP SERVER FAILS +# AFTER ALTER SERVER+KILL QUERY + +# --let $rpl_diff_statement= SELECT * FROM mysql.servers WHERE Server_name like \'s%\' + +# send CREATE SERVER s2 +# FOREIGN DATA WRAPPER mysql +# OPTIONS (USER 'user2', HOST '192.168.1.108', DATABASE 'test'); +# source include/kill_query_and_diff_master_slave.inc; + +# send ALTER SERVER s1 +# OPTIONS (DATABASE 'test1'); +# source include/kill_query_and_diff_master_slave.inc; + +# send DROP SERVER s1; +# source include/kill_query_and_diff_master_slave.inc; + +# send DROP SERVER IF EXIST s1; +# source include/kill_query_and_diff_master_slave.inc; + +######## TRIGGER ######## + +# Make sure table t4 exists +connection master; +CREATE TABLE IF NOT EXISTS t4 (a int); +connection master1; + +--let $rpl_diff_statement= SHOW TRIGGERS LIKE \'v%\' + +DELIMITER //; +send CREATE TRIGGER tr2 BEFORE INSERT ON t4 + FOR EACH ROW BEGIN + DELETE FROM t1 WHERE a=NEW.a; + END; + // +DELIMITER ;// +source include/kill_query_and_diff_master_slave.inc; + +send DROP TRIGGER tr1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP TRIGGER IF EXISTS tr2; +source include/kill_query_and_diff_master_slave.inc; + +######## VIEW ######## + +--let $rpl_diff_statement= SHOW TABLES LIKE \'v%\' + +send CREATE VIEW v2 AS SELECT a FROM t1 WHERE a > 100; +source include/kill_query_and_diff_master_slave.inc; + +send DROP VIEW v1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP VIEW IF EXISTS v2; +source include/kill_query_and_diff_master_slave.inc; + +######## DROP TABLE ######## + +--let $rpl_diff_statement= SHOW TABLES LIKE \'t%\' + +send DROP TABLE t1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP TABLE IF EXISTS t2; +source include/kill_query_and_diff_master_slave.inc; + +######## CLEAN UP ######## + +connection master; + +# The DROP statements above are killed during the process, so they +# does not make sure the objects are dropped. + +disable_warnings; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP EVENT IF EXISTS e1; +DROP EVENT IF EXISTS e2; +DROP EVENT IF EXISTS e3; +DROP EVENT IF EXISTS e4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP SERVER IF EXISTS s1; +DROP SERVER IF EXISTS s2; +DROP SERVER IF EXISTS s3; +DROP SERVER IF EXISTS s4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +enable_warnings; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt b/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt new file mode 100644 index 00000000..d4ba386a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_known_bugs_detection-master.opt @@ -0,0 +1 @@ +--loose-debug=d,pretend_version_50034_in_binlog diff --git a/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test new file mode 100644 index 00000000..5ea056d5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test @@ -0,0 +1,76 @@ +# Test to see if slave can detect certain known bugs present +# on the master, and appropriately decides to stop +# (assuming the bug is fixed in the slave, slave cannot of course +# imitate the bug, so it has to stop). + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); + +source include/have_debug.inc; +# because of pretend_version_50034_in_binlog the test can't run with checksum +source include/have_binlog_checksum_off.inc; + +# Currently only statement-based-specific bugs are here +-- source include/have_binlog_format_statement.inc + +source include/master-slave.inc; + +# testcase with INSERT SELECT +connection master; +CREATE TABLE t1 ( + id bigint(20) unsigned NOT NULL auto_increment, + field_1 int(10) unsigned NOT NULL, + field_2 varchar(255) NOT NULL, + field_3 varchar(255) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY field_1 (field_1, field_2) +); +CREATE TABLE t2 ( + field_a int(10) unsigned NOT NULL, + field_b varchar(255) NOT NULL, + field_c varchar(255) NOT NULL +); +INSERT INTO t2 (field_a, field_b, field_c) VALUES (1, 'a', '1a'); +INSERT INTO t2 (field_a, field_b, field_c) VALUES (2, 'b', '2b'); +INSERT INTO t2 (field_a, field_b, field_c) VALUES (3, 'c', '3c'); +INSERT INTO t2 (field_a, field_b, field_c) VALUES (4, 'd', '4d'); +INSERT INTO t2 (field_a, field_b, field_c) VALUES (5, 'e', '5e'); +sync_slave_with_master; +connection master; +# Updating table t1 based on values from table t2 +INSERT INTO t1 (field_1, field_2, field_3) +SELECT t2.field_a, t2.field_b, t2.field_c +FROM t2 +ON DUPLICATE KEY UPDATE +t1.field_3 = t2.field_c; +# Inserting new record into t2 +INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f'); +# Updating t1 again +INSERT INTO t1 (field_1, field_2, field_3) +SELECT t2.field_a, t2.field_b, t2.field_c +FROM t2 +ON DUPLICATE KEY UPDATE +t1.field_3 = t2.field_c; +SELECT * FROM t1; +connection slave; + +# show the error message +#1105 = ER_UNKNOWN_ERROR +--let $slave_sql_errno= 1105 +--let $show_slave_sql_error= 1 +--source include/wait_for_slave_sql_error.inc + +# show that it was not replicated +SELECT * FROM t1; +connection master; + +# clean up +drop table t1, t2; +connection slave; +drop table t1, t2; +# clear error message in sql thread +--source include/stop_slave_io.inc +RESET SLAVE; + +# End of 5.0 tests +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt new file mode 100644 index 00000000..0031a57a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db-slave.opt @@ -0,0 +1 @@ +--lower-case-table-names=1 "--replicate-rewrite-db=b37656->bug37656" diff --git a/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test new file mode 100644 index 00000000..9c804d82 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_lcase_tblnames_rewrite_db.test @@ -0,0 +1,60 @@ +# BUG#37656 +# +# DESCRIPTION +# +# +# This test case is tests whether replication works properly when +# slave is configured with --lower-case-table-names=1 and replication +# rewrite rules are in effect. +# +# It checks four issues: +# +# (i) master contains capitalized table name +# +# (ii) slave contains lowered case table name +# +# (iii) master and slave tables do not differ +# +-- source include/master-slave.inc +-- source include/not_windows.inc + +SET SQL_LOG_BIN=0; +CREATE DATABASE B37656; +SET SQL_LOG_BIN=1; + +-- connection slave +CREATE DATABASE BUG37656; + +-- echo ### action: show that database on slave is created in lowercase +SHOW DATABASES LIKE '%37656'; + +-- connection master +USE B37656; +CREATE TABLE T1 (a int); +INSERT INTO T1 VALUES (1); + +-- echo ### assertion: master contains capitalized case table +SHOW TABLES; + +-- sync_slave_with_master + +use bug37656; + +-- echo ### assertion: slave contains lowered case table +SHOW TABLES; + +-- echo ### assertion: master and slave tables do not differ +let $diff_tables= master:B37656.T1, slave:bug37656.t1; + +-- source include/diff_tables.inc + +-- connection master +SET SQL_LOG_BIN=0; +DROP DATABASE B37656; +SET SQL_LOG_BIN=1; +SHOW DATABASES LIKE '%37656'; + +-- connection slave +DROP DATABASE BUG37656; +SHOW DATABASES LIKE '%37656'; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata.test b/mysql-test/suite/rpl/t/rpl_loaddata.test new file mode 100644 index 00000000..9f0ba95a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata.test @@ -0,0 +1,4 @@ +-- source include/have_binlog_format_statement.inc + +let $engine_type=MyISAM; +-- source include/rpl_loaddata.test diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_charset.test b/mysql-test/suite/rpl/t/rpl_loaddata_charset.test new file mode 100644 index 00000000..bb87ee95 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_charset.test @@ -0,0 +1,49 @@ +# +# Check LOAD DATA + character sets + replication +# +source include/master-slave.inc; + +# +# Bug#15126 character_set_database is not replicated +# (LOAD DATA INFILE need it) +# +connection master; +create table t1 (a varchar(10) character set utf8); +load data infile '../../std_data/loaddata6.dat' into table t1; +set @@character_set_database=koi8r; +load data infile '../../std_data/loaddata6.dat' into table t1; +set @@character_set_database=DEFAULT; +load data infile '../../std_data/loaddata6.dat' into table t1; +load data infile '../../std_data/loaddata6.dat' into table t1; +load data infile '../../std_data/loaddata6.dat' into table t1; +set @@character_set_database=koi8r; +load data infile '../../std_data/loaddata6.dat' into table t1; +set @@character_set_database=DEFAULT; +load data infile '../../std_data/loaddata6.dat' into table t1 character set koi8r; + +select hex(a) from t1; + +sync_slave_with_master; + +select hex(a) from t1; +connection master; +drop table t1; +sync_slave_with_master; + +# +# Bug#45516 +# When slave SQL thread executing LOAD DATA command, the +# thd->variables.collation_database was not set properly to the default +# database charset +# + +echo -------------test bug#45516------------------; + +# LOAD DATA INFILE +let $LOAD_LOCAL=1; +source include/rpl_loaddata_charset.inc; + +# LOAD DATA LOCAL INFILE +let $LOAD_LOCAL=0; +source include/rpl_loaddata_charset.inc; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt new file mode 100644 index 00000000..9c846c79 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_fatal-slave.opt @@ -0,0 +1 @@ +--loose-debug=+d,LOAD_DATA_INFILE_has_fatal_error diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test b/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test new file mode 100644 index 00000000..4e87d6de --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_fatal.test @@ -0,0 +1,27 @@ +source include/have_binlog_format_statement.inc; +source include/have_debug.inc; +source include/master-slave.inc; + +# We do this little stunt to make sure that the slave has started +# before we stop it again. +connection master; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,10); +sync_slave_with_master; + +# Now we feed it a load data infile, which should make it stop with a +# fatal error. +connection master; +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE t1; + +connection slave; +call mtr.add_suppression("Slave SQL.*Fatal error: Not enough memory, error.* 1593"); +let $slave_sql_errno= 1593; +let $show_slave_sql_error= 1; +source include/wait_for_slave_sql_error_and_skip.inc; + +connection master; +DROP TABLE t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt new file mode 100644 index 00000000..9d4a8f0b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_m-master.opt @@ -0,0 +1 @@ +--binlog_ignore_db=test diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_m.test b/mysql-test/suite/rpl/t/rpl_loaddata_m.test new file mode 100644 index 00000000..b9dffa3f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_m.test @@ -0,0 +1,51 @@ +# See if the master logs LOAD DATA INFILE correctly when binlog_*_db rules +# exist. +# This is for BUG#1100 (LOAD DATA INFILE was half-logged). +###################################################### +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Test rewritten to remove show binlog events +# and to test the option better + Cleanup +###################################################### +-- source include/master-slave.inc + +--disable_warnings +drop database if exists mysqltest; +--enable_warnings + +connection master; +# 'test' database should be ignored by the slave +USE test; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE test.t1; +SELECT COUNT(*) FROM test.t1; + +# 'mysqltest' database should NOT be ignored by the slave +CREATE DATABASE mysqltest; +USE mysqltest; +CREATE TABLE t1(a INT, b INT, UNIQUE(b)); +LOAD DATA INFILE '../../std_data/rpl_loaddata.dat' INTO TABLE mysqltest.t1; +SELECT COUNT(*) FROM mysqltest.t1; + +# Now lets check the slave to see what we have :-) +sync_slave_with_master; + +SHOW DATABASES; + +USE test; +SHOW TABLES; + +USE mysqltest; +SHOW TABLES; +SELECT COUNT(*) FROM mysqltest.t1; + +#show binlog events; + +# Cleanup +connection master; +DROP DATABASE mysqltest; +DROP TABLE IF EXISTS test.t1; +sync_slave_with_master; + +# End of test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt new file mode 100644 index 00000000..5fdeb855 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_map-master.opt @@ -0,0 +1 @@ +--read_buffer_size=12K --max_allowed_packet=8K --net-buffer-length=8K diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt new file mode 100644 index 00000000..7d404fae --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_map-slave.opt @@ -0,0 +1 @@ +--max_allowed_packet=8K --net-buffer-length=8K diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_map.test b/mysql-test/suite/rpl/t/rpl_loaddata_map.test new file mode 100644 index 00000000..655bcc39 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_map.test @@ -0,0 +1,72 @@ +# ==== Purpose ==== +# +# check replication of load data with the server parameters subjected to +# read_buffer_size > max_allowed_packet +# +# ==== Implementation ==== +# +# Insert many rows into t1, write t1 to file. +# Load the file into t2. +# See that t2 came out as expected on slave. +# +# ==== Related Bugs ==== +# +# BUG#30435 loading large LOAD DATA INFILE breaks slave with +# read_buffer_size set on master +# BUG#33413 show binlog events fails if binlog has event size of close +# to max_allowed_packet + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + + +--echo ==== Create a big file ==== + +# We turn off binlogging to avoid too much noise in the binlog. t1 is +# just an auxiliary construction anyways, it is not needed on the +# slave. + +--disable_query_log +SET @@sql_log_bin= 0; + +let $rows= 5000; +create table t1 (id int not null primary key auto_increment); + +while($rows) +{ + eval insert into t1 values (null); + dec $rows; +} +eval select * into outfile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' from t1; + +DROP TABLE t1; +SET @@sql_log_bin= 1; +--enable_query_log + + +--echo ==== Load our big file into a table ==== +create table t2 (id int not null primary key auto_increment); + +select @@session.read_buffer_size - @@session.max_allowed_packet > 0 ; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval load data infile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2; +select count(*) from t2 /* 5 000 */; + +# the binlog will show fragmented Append_block events +source include/show_binlog_events.inc; + + +--echo ==== Verify results on slave ==== + +sync_slave_with_master; +select count(*) from t2 /* 5 000 */; + + +--echo ==== Clean up ==== + +connection master; +drop table t2; +sync_slave_with_master; +remove_file $MYSQLTEST_VARDIR/tmp/bug30435_5k.txt; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt new file mode 100644 index 00000000..9d4a8f0b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_s-slave.opt @@ -0,0 +1 @@ +--binlog_ignore_db=test diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_s.test b/mysql-test/suite/rpl/t/rpl_loaddata_s.test new file mode 100644 index 00000000..21167968 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_s.test @@ -0,0 +1,27 @@ +# See if the slave logs (in its own binlog, with --log-slave-updates) a +# replicated LOAD DATA INFILE correctly when it has binlog_*_db rules. +# This is for BUG#1100 (LOAD DATA INFILE was half-logged). + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc + +connection slave; +# Not sure why we connect to slave and then try to reset master, but I will leave it [JBM] +reset master; + +connection master; +# 'test' is the current database +create table test.t1(a int, b int, unique(b)); +load data infile '../../std_data/rpl_loaddata.dat' into table test.t1; + +# Test logging on slave; + +sync_slave_with_master; +select count(*) from test.t1; # check that LOAD was replicated +source include/show_binlog_events.inc; + +# Cleanup +connection master; +drop table test.t1; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_simple.test b/mysql-test/suite/rpl/t/rpl_loaddata_simple.test new file mode 100644 index 00000000..a09d3fee --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_simple.test @@ -0,0 +1,15 @@ +--source include/master-slave.inc + +CREATE TABLE t1 (word CHAR(20) NOT NULL); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +SELECT * FROM t1 ORDER BY word; +sync_slave_with_master; + +# Check +SELECT * FROM t1 ORDER BY word; + +# Cleanup +connection master; +drop table t1; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt new file mode 100644 index 00000000..719832a2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.opt @@ -0,0 +1 @@ +--secure-file-priv=$MYSQLTEST_VARDIR/std_data_master_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh new file mode 100644 index 00000000..e5bb3e61 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-master.sh @@ -0,0 +1,2 @@ +rm -f $MYSQLTEST_VARDIR/std_data_master_link +ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_master_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt new file mode 100644 index 00000000..a112e81a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.opt @@ -0,0 +1 @@ +--slave-load-tmpdir=$MYSQLTEST_VARDIR/std_data_slave_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh new file mode 100644 index 00000000..7a0c0bb3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink-slave.sh @@ -0,0 +1,2 @@ +rm -f $MYSQLTEST_VARDIR/std_data_slave_link +ln -s $MYSQLTEST_VARDIR/std_data $MYSQLTEST_VARDIR/std_data_slave_link diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test new file mode 100644 index 00000000..e5ee400d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_symlink.test @@ -0,0 +1,22 @@ +# +# BUG#43913 +# This test verifies if loading data infile will work fine +# if the path of the load data file is a symbolic link. +# +--source include/not_windows.inc +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +select * from t1; + +sync_slave_with_master; +connection slave; +select * from t1; + +connection master; +drop table t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_loaddatalocal.test b/mysql-test/suite/rpl/t/rpl_loaddatalocal.test new file mode 100644 index 00000000..71204146 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddatalocal.test @@ -0,0 +1 @@ +--source include/rpl_loaddata_local.inc diff --git a/mysql-test/suite/rpl/t/rpl_loadfile.test b/mysql-test/suite/rpl/t/rpl_loadfile.test new file mode 100644 index 00000000..10fecf1f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loadfile.test @@ -0,0 +1 @@ +--source include/rpl_loadfile.inc diff --git a/mysql-test/suite/rpl/t/rpl_locale.test b/mysql-test/suite/rpl/t/rpl_locale.test new file mode 100644 index 00000000..0d6692dd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_locale.test @@ -0,0 +1,25 @@ +# Replication of locale variables + +source include/master-slave.inc; + +# +# Bug#22645 LC_TIME_NAMES: Statement not replicated +# +connection master; +create table t1 (s1 char(10)); +set lc_time_names= 'de_DE'; +insert into t1 values (date_format('2001-01-01','%W')); +set lc_time_names= 'en_US'; +insert into t1 values (date_format('2001-01-01','%W')); +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; +sync_slave_with_master; + +# End of 4.1 tests + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_log_pos.test b/mysql-test/suite/rpl/t/rpl_log_pos.test new file mode 100644 index 00000000..4f63cd32 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_log_pos.test @@ -0,0 +1,57 @@ +########## +# Change Author: JBM +# Change Date: 2006-01-16 +########## + +# +# Testing of setting slave to wrong log position with master_log_pos +# + +# Passes with rbr no problem, removed statement include [jbm] + +source include/master-slave.inc; + +# +# Add an event to get some information into the log we can try to parse +# +let $read_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +create table if not exists t1 (n int); +drop table t1; + +call mtr.add_suppression ("Slave I/O: Got fatal error 1236 from master when reading data from binary"); +call mtr.add_suppression ("Error in Log_event::read_log_event"); +source include/show_master_status.inc; +sync_slave_with_master; +source include/stop_slave.inc; + +let $wrong_log_pos= `SELECT $read_pos+2`; +--replace_result $wrong_log_pos MASTER_LOG_POS +eval change master to master_log_pos=$wrong_log_pos; +start slave; +let $slave_io_errno= 1236; +--let $show_slave_io_error= 1 +# Mask line numbers +--let $slave_io_error_replace= / at [0-9]*/ at XXX/ +source include/wait_for_slave_io_error.inc; +source include/stop_slave_sql.inc; +--enable_warnings + +connection master; +source include/show_master_status.inc; +create table if not exists t1 (n int); +drop table if exists t1; +create table t1 (n int); +insert into t1 values (1),(2),(3); +save_master_pos; +connection slave; +--replace_result 4 MASTER_LOG_POS +change master to master_log_pos=4; +start slave; +sync_with_master; +select * from t1 ORDER BY n; +connection master; +drop table t1; +sync_slave_with_master; + +--echo End of 5.0 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test b/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test new file mode 100644 index 00000000..3a4a24e1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_lost_events_on_rotate.test @@ -0,0 +1,51 @@ +# +# Whenever the mysql_binlog_send method (dump thread) reaches the +# end of file when reading events from the binlog, before checking +# if it should wait for more events, there was a test to check if +# the file being read was still active, i.e, it was the last known +# binlog. However, it was possible that something was written to +# the binary log and then a rotation would happen, after EOF was +# detected and before the check for active was performed. In this +# case, the end of the binary log would not be read by the dump +# thread, and this would cause the slave to lose updates. +# +# This test verifies that the problem has been fixed. It waits +# during this window while forcing a rotation in the binlog. +# +--source include/have_debug.inc +--source include/master-slave.inc + +--connection master + +SET @debug_saved= @@GLOBAL.DEBUG_DBUG; + +CREATE TABLE t (i INT); + +# When reaching the EOF the dump thread will wait before deciding if +# it should move to a new binlong file. +SET GLOBAL DEBUG_DBUG= "d,wait_after_binlog_EOF"; + +INSERT INTO t VALUES (1); + +--sleep 1 + +# A insert and a rotate happens before the decision +INSERT INTO t VALUES (2); +FLUSH LOGS; + +SET DEBUG_SYNC= 'now SIGNAL signal.rotate_finished'; + +--sync_slave_with_master + +# All the rows should be sent to the slave. +--let $diff_tables=master:t,slave:t +--source include/diff_tables.inc + +##Clean up +--connection master + +SET @@GLOBAL.DEBUG_DBUG= @debug_saved; +SET DEBUG_SYNC= 'RESET'; + +DROP TABLE t; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test new file mode 100644 index 00000000..1c087c55 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test @@ -0,0 +1,108 @@ +source include/master-slave.inc; + +# +# BUG#28421 Infinite loop on slave relay logs +# +# That, manually deleteing one or more entries from 'master-bin.index', will +# cause master infinitely loop to send one binlog file. +# +# Manually changing index file is a illegal action, so when this happen, we +# send a fatal error to slave and close the dump session. + +FLUSH LOGS; +# Now, 2 entries in index file. +# ./master-bin.000001 +# ./master-bin.000002 + +CREATE TABLE t1(c1 INT); +# Now, the current dump file(master-bin.000002) is the second line of index +# file +sync_slave_with_master; +# Now, all events has been replicate to slave. As current dump file +# (master-bin.000002) is the last binlog file, so master is waiting for new +# events. + +connection master; +# Delete './master-bin.000001' from index file. +let $MYSQLD_DATADIR= `SELECT @@DATADIR`; +let TRUNCATE_FILE= $MYSQLD_DATADIR/master-bin.index; +source include/truncate_file.inc; + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +./master-bin.000002 +EOF +sleep 0.00000001; +} + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +.\master-bin.000002 +EOF +sleep 0.00000001; +} + +# Now, only 1 entry in index file. ./master-bin.000002 + +# Generate master-bin.000003, but it is in the second line. +FLUSH LOGS; +# Now, 2 entries in index file. +# ./master-bin.000002 +# ./master-bin.000003 + +# Now, master know that new binlog file(master-bin.000003) has been generated. +# It expects that the new binlog file is in third line of index file, but +# there is no third line in index file. It is so strange that master sends an +# error to slave. +call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log'); +connection slave; +# 1236 = ER_MASTER_FATAL_ERROR_READING_BINLOG +--let $slave_io_errno= 1236 +--let $show_slave_io_error= 1 +# Mask line numbers +--let $slave_io_error_replace= / at [0-9]*/ at XXX/ +--source include/wait_for_slave_io_error.inc + +connection master; + +source include/truncate_file.inc; + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +./master-bin.000001 +./master-bin.000002 +./master-bin.000003 +EOF +sleep 0.00000001; +} + +if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`) +{ +append_file $MYSQLD_DATADIR/master-bin.index; +.\master-bin.000001 +.\master-bin.000002 +.\master-bin.000003 +EOF +sleep 0.00000001; +} + +CREATE TABLE t2(c1 INT); +FLUSH LOGS; +CREATE TABLE t3(c1 INT); +FLUSH LOGS; +CREATE TABLE t4(c1 INT); + +connection slave; +START SLAVE IO_THREAD; +source include/wait_for_slave_io_to_start.inc; + +connection master; +sync_slave_with_master; +SHOW TABLES; + +connection master; +DROP TABLE t1, t2, t3, t4; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_many_optimize.test b/mysql-test/suite/rpl/t/rpl_many_optimize.test new file mode 100644 index 00000000..d5e9f69b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_many_optimize.test @@ -0,0 +1,23 @@ +# Test for BUG#7658 "optimize crashes slave thread (1 in 1000)]" + +source include/master-slave.inc; + +create table t1 (a int not null auto_increment primary key, b int, key(b)); +INSERT INTO t1 (a) VALUES (1),(2); +# Now many OPTIMIZE to test if we crash (BUG#7658) +let $1=300; +disable_query_log; +disable_result_log; +while ($1) +{ + eval OPTIMIZE TABLE t1; + dec $1; +} +enable_result_log; +enable_query_log; +drop table t1; +# Bug was that slave segfaulted after ~ a hundred of OPTIMIZE (or ANALYZE) +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test new file mode 100644 index 00000000..046a65f7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test @@ -0,0 +1,158 @@ +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +connection master; +set @old_master_binlog_checksum= @@global.binlog_checksum; + +# MDEV-4475: Cannot replicate to old server when binlog contains +# empty Gtid_list event +# +# Test this by binlog rotation before we log any GTIDs. +connection slave; +--source include/stop_slave.inc +--echo # Test slave with no capability gets dummy event, which is ignored. +set @old_dbug= @@global.debug_dbug; +SET @@global.debug_dbug='+d,simulate_slave_capability_none'; +--source include/start_slave.inc + +connection master; +FLUSH LOGS; +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (0); +sync_slave_with_master; + +connection master; +# Add a dummy event just to have something to sync_slave_with_master on. +# Otherwise we occasionally get different $relaylog_start, depending on +# whether Format_description_log_event was written to relay log or not +# at the time of SHOW SLAVE STATUS. +ALTER TABLE t1 ORDER BY a; +sync_slave_with_master; +connection slave; +let $relaylog_start= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1); + +connection master; +SET SESSION binlog_annotate_row_events = ON; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +# A short event, to test when we need to use user_var_event for dummy event. +DELETE FROM t1; +INSERT INTO t1 /* A comment just to make the annotate event sufficiently long that the dummy event will need to get padded with spaces so that we can test that this works */ VALUES(1); +let $binlog_limit= 0, 10; +--source include/show_binlog_events.inc +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; +let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); +let $binlog_start= $relaylog_start; +let $binlog_limit=0,10; +--source include/show_relaylog_events.inc +set @@global.debug_dbug= @old_dbug; + +--echo # Test dummy event is checksummed correctly. + +connection master; +set @@global.binlog_checksum = CRC32; +--source include/wait_for_binlog_checkpoint.inc +TRUNCATE t1; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t1 VALUES(2); +let $binlog_limit= 0, 5; +--source include/show_binlog_events.inc +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; +let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); +let $binlog_start= 0; +let $binlog_limit=7,5; +--source include/show_relaylog_events.inc + + +--echo *** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 *** + +# The problem was that for a group commit, we get commit id into the +# GTID event, and there was a bug in the code that replaces GTID with +# dummy that failed when commit id was present. +# +# So setup a group commit in InnoDB. + +--connection master +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; +send INSERT INTO t2 VALUES (1); + +--connection master +SET debug_sync='now WAIT_FOR master_queued1'; + +--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2'; +send INSERT INTO t2 VALUES (2); + +--connection master +SET debug_sync='now WAIT_FOR master_queued2'; +SET debug_sync='now SIGNAL master_cont1'; + +--connection con1 +REAP; +SET debug_sync='RESET'; +--connection con2 +REAP; +SET debug_sync='RESET'; +--connection master +SET debug_sync='RESET'; +let $binlog_limit= 0, 10; +--source include/show_binlog_events.inc +--save_master_pos + +--connection slave +--sync_with_master +SELECT * FROM t2 ORDER BY a; + + +--echo # Test that slave which cannot tolerate holes in binlog stream but +--echo # knows the event does not get dummy event + +--source include/stop_slave.inc +SET @@global.debug_dbug='+d,simulate_slave_capability_old_53'; +--source include/start_slave.inc +connection master; +ALTER TABLE t1 ORDER BY a; +sync_slave_with_master; +connection slave; +let $relaylog_start= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1); + +connection master; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +UPDATE t1 SET a = 3; +let $binlog_limit= 0, 5; +--source include/show_binlog_events.inc +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; +let $binlog_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1); +let $binlog_start= $relaylog_start; +let $binlog_limit=0,5; +--source include/show_relaylog_events.inc + +select @@global.log_slave_updates; +select @@global.replicate_annotate_row_events; + +--echo Clean up. +connection master; +set @@global.binlog_checksum = @old_master_binlog_checksum; +DROP TABLE t1, t2; +sync_slave_with_master; +set @@global.debug_dbug= @old_dbug; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test b/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test new file mode 100644 index 00000000..6d66e3fd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mark_optimize_tbl_ddl.test @@ -0,0 +1,142 @@ +# ==== Purpose ==== +# +# Test verifies that there is no deadlock or assertion in +# slave_parallel_mode=optimistic configuration while applying admin command +# like 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE'. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Create a table, execute OPTIMIZE TABLE command on the table followed +# by some DMLS. +# 1 - No assert should happen on slave server. +# 2 - Assert that 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE' are +# marked as 'DDL' in the binary log. +# +# ==== References ==== +# +# MDEV-17515: GTID Replication in optimistic mode deadlock +# +--source include/have_partition.inc +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +FLUSH TABLES; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + +--connection server_2 +SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads; +SET @save_slave_parallel_mode= @@GLOBAL.slave_parallel_mode; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=2; +SET GLOBAL slave_parallel_mode=optimistic; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1(a INT) ENGINE=INNODB; +OPTIMIZE TABLE t1; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 SELECT 1+a FROM t1; +INSERT INTO t1 SELECT 2+a FROM t1; +--save_master_pos + +--connection server_2 +--sync_with_master + +--echo # +--echo # Verify that following admin commands are marked as ddl +--echo # 'OPTIMIZE TABLE', 'REPAIR TABLE' and 'ANALYZE TABLE' +--echo # +--connection server_1 + +OPTIMIZE TABLE t1; +--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +REPAIR TABLE t1; +--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +ANALYZE TABLE t1; +--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +FLUSH LOGS; + +--let $MYSQLD_DATADIR= `select @@datadir` +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out + +--let SEARCH_PATTERN= GTID $optimize_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= GTID $repair_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= GTID $analyze_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--echo # +--echo # Clean up +--echo # +DROP TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--save_master_pos + +--connection server_2 +--sync_with_master +FLUSH LOGS; + +--echo # +--echo # Check that ALTER TABLE commands with ANALYZE, OPTIMIZE and REPAIR on +--echo # partitions will be marked as DDL in binary log. +--echo # +--connection server_1 +CREATE TABLE t1(id INT) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN (100), + PARTITION pmax VALUES LESS THAN (MAXVALUE)); +INSERT INTO t1 VALUES (1), (10), (100), (1000); + +ALTER TABLE t1 ANALYZE PARTITION p0; +--let analyze_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +ALTER TABLE t1 OPTIMIZE PARTITION p0; +--let optimize_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +ALTER TABLE t1 REPAIR PARTITION p0; +--let repair_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` + +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +FLUSH LOGS; + +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out + +--let SEARCH_PATTERN= GTID $analyze_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= GTID $optimize_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--let SEARCH_PATTERN= GTID $repair_gtid ddl +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--source include/search_pattern_in_file.inc + +--echo # +--echo # Clean up +--echo # +DROP TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.out +--save_master_pos + +--connection server_2 +--sync_with_master + +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads; +SET GLOBAL slave_parallel_mode= @save_slave_parallel_mode; +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_master_pos_wait.test b/mysql-test/suite/rpl/t/rpl_master_pos_wait.test new file mode 100644 index 00000000..437d8412 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_master_pos_wait.test @@ -0,0 +1,79 @@ +# See if master_pos_wait(,,timeout) +# Terminates with "timeout expired" (-1) +source include/master-slave.inc; +sync_slave_with_master; +# Ask for a master log that has certainly not been reached yet +# timeout= 2 seconds +select master_pos_wait('master-bin.999999',0,2); +explain extended select master_pos_wait('master-bin.999999',0,2); +# Testcase for bug 651 (master_pos_wait() hangs if slave idle and STOP SLAVE). +send select master_pos_wait('master-bin.999999',0); +connection slave1; +stop slave sql_thread; +--source include/wait_for_slave_sql_to_stop.inc +connection slave; +reap; + +# +# bug#26622 MASTER_POS_WAIT does not work as documented +# + +connection master; +echo "*** must be empty ***"; +query_vertical show slave status; + +echo "*** must be NULL ***"; +select master_pos_wait('foo', 98); + +# End of 4.1 tests + + +--echo *** MDEV-7130: MASTER_POS_WAIT(log_name,log_pos,timeout,"connection_name") hangs, does not respect the timeout *** + +--connection slave +--source include/stop_slave.inc +reset slave all; +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval change master 'my_slave' to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root'; +set default_master_connection = 'my_slave'; +--source include/start_slave.inc + +--echo # Call without connection name -- works (expected -1) +select master_pos_wait('master-bin.000001',1000000,1); + +set default_master_connection = ''; + +--echo # Call for non-existing anonymous connection -- works (expected NULL) +select master_pos_wait('master-bin.000001',1000000,1); + +--echo # Call with a valid connection name -- hangs before MDEV-7130 fix (expected -1) +select master_pos_wait('master-bin.000001',1000000,1,"my_slave"); + +STOP SLAVE 'my_slave'; +RESET SLAVE 'my_slave' ALL; + +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval change master to master_port=$MASTER_MYPORT, master_host='127.0.0.1', master_user='root'; + +# End of 10.0 tests + +--echo # +--echo # Start of 10.3 tests +--echo # + +--echo # +--echo # MDEV-13965 Parameter data type control for Item_longlong_func +--echo # + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT MASTER_POS_WAIT('x',1,ROW(1,1)); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT MASTER_POS_WAIT('x',1,1,ROW(1,1)); + +--echo # +--echo # End of 10.3 tests +--echo # + + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.opt b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt new file mode 100644 index 00000000..7f1d270d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.opt @@ -0,0 +1 @@ +--binlog_checksum=1 --binlog-annotate-row-events=1 diff --git a/mysql-test/suite/rpl/t/rpl_mdev-11092.test b/mysql-test/suite/rpl/t/rpl_mdev-11092.test new file mode 100644 index 00000000..782d2480 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev-11092.test @@ -0,0 +1,53 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +######################################################################################## +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Slave SQL: The incident LOST_EVENTS occurred on the master. .*"); + +let $old_max_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_cache_size", Value, 1); +let $old_binlog_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_cache_size", Value, 1); +let $old_max_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "max_binlog_stmt_cache_size", Value, 1); +let $old_binlog_stmt_cache_size= query_get_value(SHOW VARIABLES LIKE "binlog_stmt_cache_size", Value, 1); + +SET GLOBAL max_binlog_cache_size = 4096; +SET GLOBAL binlog_cache_size = 4096; +SET GLOBAL max_binlog_stmt_cache_size = 4096; +SET GLOBAL binlog_stmt_cache_size = 4096; +disconnect master; +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); + +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MYISAM; + +let $data = `select concat('"', repeat('a',2000), '"')`; + +connection master; + +--disable_query_log +--error ER_BINLOG_ROW_LOGGING_FAILED +eval INSERT INTO t1 (a, data) VALUES (2, + CONCAT($data, $data, $data, $data, $data, $data)); +--enable_query_log + +# Incident event +# 1590=ER_SLAVE_INCIDENT +--let $slave_sql_errno= 1590 +--source include/wait_for_slave_sql_error_and_skip.inc + +connection master; + +--replace_result $old_max_binlog_cache_size ORIGINAL_VALUE +--eval SET GLOBAL max_binlog_cache_size= $old_max_binlog_cache_size +--replace_result $old_binlog_cache_size ORIGINAL_VALUE +--eval SET GLOBAL binlog_cache_size= $old_binlog_cache_size +--replace_result $old_max_binlog_stmt_cache_size ORIGINAL_VALUE +--eval SET GLOBAL max_binlog_stmt_cache_size= $old_max_binlog_stmt_cache_size +--replace_result $old_binlog_stmt_cache_size ORIGINAL_VALUE +--eval SET GLOBAL binlog_stmt_cache_size= $old_binlog_stmt_cache_size + +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev10863.test b/mysql-test/suite/rpl/t/rpl_mdev10863.test new file mode 100644 index 00000000..73062df8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev10863.test @@ -0,0 +1,105 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +# Test various aspects of parallel replication. + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +SET @old_max_relay= @@GLOBAL.max_relay_log_size; +SET GLOBAL max_relay_log_size = 4096; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b VARCHAR(100)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, "a"); +--save_master_pos + +--connection server_2 +--sync_with_master + +--echo *** Create a long transaction that will span a relay log file. *** +--connection server_1 + +# Add some transactions in separate domains, that will cause the need to +# have a multi-valued restart position in the relay log for the SQL thread. +SET @old_domain= @@gtid_domain_id; +SET gtid_domain_id=10; +INSERT INTO t1 VALUES (10000, "domain 10"); +SET gtid_domain_id=20; +INSERT INTO t1 VALUES (20000, "domain 20"); +SET gtid_domain_id=@old_domain; + +BEGIN; +--echo [lots of inserts omitted] +--disable_query_log +--let $count = 500 +while ($count) { + eval INSERT INTO t1 VALUES (1000+$count, REPEAT("hulubulu??!?", 8)); + dec $count; +} +--enable_query_log +COMMIT; + +--save_master_pos + +--connection server_2 +--sync_with_master + +--connection server_1 +# Now do another one, to make the inuse_relaylog proceed to somewhere inside +# the first large transaction. + +BEGIN; +--echo [lots of inserts omitted] +--disable_query_log +--let $count = 500 +while ($count) { + eval INSERT INTO t1 VALUES (2000+$count, REPEAT("hulubulu??!?", 8)); + dec $count; +} +--enable_query_log +COMMIT; + +--save_master_pos + +--connection server_2 +--sync_with_master + + +# Stop and restart the SQL thread only. +# The bug was that the SQL thread would restart at the start +# of a relay log file, which could be in the middle of an event group. +# This way, part of that event group could be wrongly re-applied. + +--source include/stop_slave_sql.inc +START SLAVE SQL_THREAD; +--source include/wait_for_slave_to_start.inc + + +--connection server_1 +INSERT INTO t1 VALUES (100000, "More stuffs."); +INSERT INTO t1 VALUES (100001, "And even more"); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 WHERE a >= 100000 ORDER BY a; + + +# Clean up. +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET GLOBAL max_relay_log_size= @old_max_relay; +--source include/start_slave.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test new file mode 100644 index 00000000..e3caccde --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test @@ -0,0 +1,316 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_2 +call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase"); + +--error ER_SLAVE_MUST_STOP +SET GLOBAL gtid_pos_auto_engines="innodb"; +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; + +# Test the @@gtid_pos_auto_engines sysvar. +SELECT @@gtid_pos_auto_engines; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.gtid_pos_auto_engines; +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL gtid_pos_auto_engines= NULL; +SET GLOBAL gtid_pos_auto_engines="innodb"; +SELECT @@gtid_pos_auto_engines; +SET GLOBAL gtid_pos_auto_engines="myisam,innodb"; +SELECT @@gtid_pos_auto_engines; +SET GLOBAL gtid_pos_auto_engines="innodb,myisam"; +SELECT @@gtid_pos_auto_engines; +SET GLOBAL gtid_pos_auto_engines="innodb,innodb,myisam,innodb,myisam,myisam,innodb"; +SELECT @@gtid_pos_auto_engines; +SET GLOBAL gtid_pos_auto_engines=DEFAULT; +SELECT @@gtid_pos_auto_engines; +SET GLOBAL gtid_pos_auto_engines=""; +SELECT @@gtid_pos_auto_engines; + +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 ORDER BY a; +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +--source include/stop_slave.inc +SET sql_log_bin=0; +# Reset storage engine for mysql.gtid_slave_pos in case an earlier test +# might have changed it to InnoDB. +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; +ALTER TABLE mysql.gtid_slave_pos_innodb ENGINE=InnoDB; +INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos; +TRUNCATE mysql.gtid_slave_pos; +SET sql_log_bin=1; + +# Restart the slave mysqld server, and verify that the GTID position is +# read correctly from the new mysql.gtid_slave_pos_innodb table. + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--connection server_1 +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +# Let the slave mysqld server start again. +# As we are restarting, also take the opportunity to test --gtid-pos-auto-engines +--echo *** Restart server with --gtid-pos-auto-engines=innodb,myisam *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 --gtid-pos-auto-engines=innodb,myisam +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--echo *** Verify no new gtid_slave_pos* tables are created *** +SELECT table_name, engine FROM information_schema.tables + WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' + ORDER BY table_name; + +SELECT @@gtid_pos_auto_engines; +--source include/stop_slave.inc +SET sql_log_bin=0; +INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos; +DROP TABLE mysql.gtid_slave_pos; +RENAME TABLE mysql.gtid_slave_pos_innodb TO mysql.gtid_slave_pos; +SET sql_log_bin=1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--connection server_1 +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (4); +INSERT INTO t2 VALUES (1); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--echo *** Restart server with --gtid-pos-auto-engines=myisam,innodb *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 --gtid-pos-auto-engines=myisam,innodb +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Verify that no new gtid_slave_pos* tables are auto-created *** +SELECT table_name, engine FROM information_schema.tables + WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' + ORDER BY table_name; + + +--source include/stop_slave.inc +SET sql_log_bin=0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; +SET sql_log_bin=1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--connection server_1 +INSERT INTO t1 VALUES (5); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--echo *** Restart server with --gtid-pos-auto-engines=innodb *** +restart: --skip-slave-start=0 --gtid-pos-auto-engines=innodb +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** +# Note, the create happens asynchronously, so wait for it. +let $wait_condition= + SELECT EXISTS (SELECT * FROM information_schema.tables + WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); +--source include/wait_condition.inc +# MDEV-15373 lowercases 'table_name' to satisfy --lower-case-table-names options +SELECT lower(table_name), engine FROM information_schema.tables + WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' + ORDER BY table_name; + + +--source include/stop_slave.inc +SET sql_log_bin=0; +INSERT INTO mysql.gtid_slave_pos SELECT * FROM mysql.gtid_slave_pos_InnoDB; +DROP TABLE mysql.gtid_slave_pos_InnoDB; +SET sql_log_bin=1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc + +--connection server_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t2 VALUES (3); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--echo *** Restart server without --gtid-pos-auto-engines *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Verify that no mysql.gtid_slave_pos* table is auto-created *** +SELECT table_name, engine FROM information_schema.tables + WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' + ORDER BY table_name; +SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; + +--source include/stop_slave.inc +SET GLOBAL gtid_pos_auto_engines="innodb"; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (7); +INSERT INTO t2 VALUES (4); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** +let $wait_condition= + SELECT EXISTS (SELECT * FROM information_schema.tables + WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); +--source include/wait_condition.inc +SELECT lower(table_name), engine FROM information_schema.tables + WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' + ORDER BY table_name; +SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; + +# Check that the auto-created InnoDB table starts being used without +# needing slave restart. The auto-create happens asynchronously, so it +# is non-deterministic when it will start being used. But we can wait +# for it to happen. + +--let $count=300 +--let $done=0 +--let $old_silent= $keep_include_silent +--let $keep_include_silent= 1 +--disable_query_log +while (!$done) +{ + --connection server_1 + INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; + --source include/save_master_gtid.inc + + --connection server_2 + --source include/sync_with_master_gtid.inc + --let $done=`SELECT COUNT(*) > 0 FROM mysql.gtid_slave_pos_InnoDB` + if (!$done) + { + dec $count; + if (!$count) + { + SELECT * FROM mysql.gtid_slave_pos_InnoDB; + --die Timeout waiting for mysql.gtid_slave_pos_InnoDB to be used + } + real_sleep 0.1; + } +} +--enable_query_log +--let $keep_include_silent=$old_silent +# Note that at this point, the contents of table t2, as well as the GTID +# position, is non-deterministic. + +# MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names +# This snippet verifies that engine gtid_slave_pos table is found, +# its data are up-to-date. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--connection server_2 +--shutdown_server +--source include/wait_until_disconnected.inc + +--echo *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; + +--connection server_1 +INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +if (`SELECT max(seq_no) <> @seq_no + 1 FROM mysql.gtid_slave_pos_InnoDB`) +{ + SELECT * FROM mysql.gtid_slave_pos_InnoDB; + --die Inconsistent table +} +# +# end of MDEV-15373 + +#--connection server_2 +--source include/stop_slave.inc +SET GLOBAL gtid_pos_auto_engines=""; +SET sql_log_bin=0; +DROP TABLE mysql.gtid_slave_pos_InnoDB; +SET sql_log_bin=1; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev359.test b/mysql-test/suite/rpl/t/rpl_mdev359.test new file mode 100644 index 00000000..5b02ecd7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev359.test @@ -0,0 +1,31 @@ +--source include/not_embedded.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_mixed_or_statement.inc +--source include/master-slave.inc + +# MDEV-359: There was a server crash when the code first checks if semisync +# is enabled without lock, then if so takes the lock and tests again. +# If semisync was disabled in-between the first and the second test, an +# assert was incorrectly made that referenced a NULL pointer. +# +# This tests uses debug_sync to pause one thread at the critical point in +# the code, disable the semisync, and then continue the paused thread. + +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +SET GLOBAL rpl_semi_sync_master_enabled = ON; +--connection master1 +SET DEBUG_SYNC = "rpl_semisync_master_commit_trx_before_lock SIGNAL m1_ready WAIT_FOR m1_cont"; +--send +INSERT INTO t1 SELECT * FROM t1; +--connection master +SET DEBUG_SYNC= "now WAIT_FOR m1_ready"; +SET GLOBAL rpl_semi_sync_master_enabled = OFF; +SET DEBUG_SYNC= "now SIGNAL m1_cont"; +--connection master1 +--reap + +connection master; +DROP TABLE t1; +SET DEBUG_SYNC= "RESET"; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev382.test b/mysql-test/suite/rpl/t/rpl_mdev382.test new file mode 100644 index 00000000..093b7b92 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev382.test @@ -0,0 +1,264 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/not_windows.inc #unix shell escaping used for mysqlbinlog + +# MDEV-382: multiple SQL injections in replication code. + +# Test previous SQL injection attack against binlog for SAVEPOINT statement. +# The test would cause syntax error on slave due to improper quoting of +# the savepoint name. +connection master; +create table t1 (a int primary key) engine=innodb; +create table t2 (a int primary key) engine=myisam; + +begin; +insert into t1 values (1); +SET sql_mode = 'ANSI_QUOTES'; +savepoint `a``; create database couldbebadthingshere; savepoint ``dummy`; +insert into t1 values (2); +insert into t2 values (1); +SET sql_mode = ''; +rollback to savepoint `a``; create database couldbebadthingshere; savepoint ``dummy`; +insert into t1 values (3); +commit; + +--source include/show_binlog_events2.inc + +# This failed due to syntax error in query when the bug was not fixed. +sync_slave_with_master; +connection slave; + +# Test some more combinations of ANSI_QUOTES and sql_quote_show_create +connection master; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +BEGIN; +insert into t1 values(10); +set sql_mode = 'ANSI_QUOTES'; +set sql_quote_show_create = 1; +savepoint a; +insert into t1 values(11); +savepoint "a""a"; +insert into t1 values(12); +set sql_quote_show_create = 0; +savepoint b; +insert into t1 values(13); +savepoint "b""b"; +insert into t1 values(14); +set sql_mode = ''; +set sql_quote_show_create = 1; +savepoint c; +insert into t1 values(15); +savepoint `c``c`; +insert into t1 values(16); +set sql_quote_show_create = 0; +savepoint d; +insert into t1 values(17); +savepoint `d``d`; +insert into t1 values(18); +COMMIT; +set sql_quote_show_create = 1; + +--source include/show_binlog_events2.inc + +--echo *** Test correct USE statement in SHOW BINLOG EVENTS *** +connection master; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +set sql_mode = 'ANSI_QUOTES'; +CREATE DATABASE "db1`; select 'oops!'"; +use "db1`; select 'oops!'"; +CREATE TABLE t1 (a INT PRIMARY KEY) engine=MyISAM; +INSERT INTO t1 VALUES (1); +set sql_mode = ''; +INSERT INTO t1 VALUES (2); +set sql_mode = 'ANSI_QUOTES'; +--source include/show_binlog_events2.inc +set sql_mode = ''; +set sql_quote_show_create = 0; +--source include/show_binlog_events2.inc +set sql_quote_show_create = 1; +--source include/show_binlog_events2.inc +DROP TABLE t1; + +use test; + +--echo ***Test LOAD DATA INFILE with various identifiers that need correct quoting *** + +--let $load_file= $MYSQLTEST_VARDIR/tmp/f'le.txt +--write_file $load_file +'fo\\o','bar' +EOF + +use `db1``; select 'oops!'`; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +set timestamp=1000000000; +CREATE TABLE `t``1` (`a``1` VARCHAR(4) PRIMARY KEY, `b``2` VARCHAR(3), + `c``3` VARCHAR(7)); +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/f''le.txt' INTO TABLE `t``1` + FIELDS TERMINATED BY ',' ESCAPED BY '\\\\' ENCLOSED BY '''' + LINES TERMINATED BY '\\n' + (`a``1`, @`b```) SET `b``2` = @`b```, `c``3` = concat('|', "b""a'z", "!"); + +SELECT * FROM `t``1`; +# Also test when code prefixes table name with database. +truncate `t``1`; +use test; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/f''le.txt' + INTO TABLE `db1``; select 'oops!'`.`t``1` + FIELDS TERMINATED BY ',' ESCAPED BY '\\\\' ENCLOSED BY '''' + LINES TERMINATED BY '\\n' + (`a``1`, `b``2`) SET `c``3` = concat('|', "b""a'z", "!"); +SELECT * FROM `db1``; select 'oops!'`.`t``1`; +let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1); + +--source include/show_binlog_events2.inc +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /LOCAL INFILE '.*SQL_LOAD.*' INTO/LOCAL INFILE '<name>' INTO/ +--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 $MYSQLD_DATADIR/master-bin.000001 + +sync_slave_with_master; +connection slave; +SELECT * FROM `db1``; select 'oops!'`.`t``1`; +connection master; + +DROP TABLE `db1``; select 'oops!'`.`t``1`; +--remove_file $load_file + +connection master; +drop table t1,t2; + + +--echo *** Test truncation of long SET expression in LOAD DATA *** +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(1000)); +--let $load_file= $MYSQLTEST_VARDIR/tmp/file.txt +--write_file $load_file +1,X +2,A +EOF + +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +# The bug was that the SET expression was truncated to 256 bytes, so test with +# an expression longer than that. +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$load_file' INTO TABLE t1 + FIELDS TERMINATED BY ',' + (a, @b) SET b = CONCAT(@b, '| 123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789M123456789N123456789O123456789P123456789Q123456789R123456789123456789T123456789U123456789V123456789W123456789X123456789Y123456789Z123456789|', @b); + +SELECT * FROM t1 ORDER BY a; +--source include/show_binlog_events2.inc + +sync_slave_with_master; +connection slave; +SELECT * FROM t1 ORDER BY a; + +connection master; +--remove_file $load_file +DROP TABLE t1; + + +--echo *** Test user variables whose names require correct quoting *** +use `db1``; select 'oops!'`; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CREATE TABLE t1 (a1 BIGINT PRIMARY KEY, a2 BIGINT, a3 BIGINT, a4 BIGINT UNSIGNED, b DOUBLE, c DECIMAL(65,10), d VARCHAR(100)); +INSERT INTO t1 VALUES (-9223372036854775808,42,9223372036854775807,18446744073709551615,-1234560123456789e110, -1234501234567890123456789012345678901234567890123456789.0123456789, REPEAT("x", 100)); +SELECT @`a``1`:=a1, @`a``2`:=a2, @`a``3`:=a3, @`a``4`:=a4, @`b```:=b, @```c`:=c, @```d```:=d FROM t1; +INSERT INTO t1 VALUES (@`a``1`+1, @`a``2`*100, @`a``3`-1, @`a``4`-1, @`b```/2, @```c`, substr(@```d```, 2, 98)); +let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1); + +--source include/show_binlog_events2.inc + +--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 $MYSQLD_DATADIR/master-bin.000001 + +sync_slave_with_master; +connection slave; +SELECT * FROM `db1``; select 'oops!'`.t1 ORDER BY a1; + +connection master; +DROP TABLE t1; + +--echo *** Test correct quoting in foreign key error message *** +use `db1``; select 'oops!'`; +CREATE TABLE `t``1` ( `a``` INT PRIMARY KEY) ENGINE=innodb; +CREATE TABLE `t``2` ( `b``` INT PRIMARY KEY, `c``` INT NOT NULL, + FOREIGN KEY fk (`c```) REFERENCES `t``1`(`a```)) ENGINE=innodb; +--error ER_TRUNCATE_ILLEGAL_FK +TRUNCATE `t``1`; +DROP TABLE `t``2`; +DROP TABLE `t``1`; + + +--echo *** Test correct quoting of DELETE FROM statement binlogged for HEAP table that is emptied due to server restart + +# Let's keep the slave stopped during master restart, to avoid any potential +# races between slave reconnect and master restart. +connection slave; +--source include/stop_slave.inc + +connection master; +CREATE TABLE `db1``; select 'oops!'`.`t``1` (`a``` INT PRIMARY KEY) ENGINE=heap; +INSERT INTO `db1``; select 'oops!'`.`t``1` VALUES (1), (2), (5); +SELECT * FROM `db1``; select 'oops!'`.`t``1` ORDER BY 1; + +# Restart the master mysqld. +# This will cause an implicit truncation of the memory-based table, which will +# cause logging of an explicit DELETE FROM to binlog. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait-rpl_mdev382.test +EOF + +--shutdown_server + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart-rpl_mdev382.test +EOF + +connection default; +--enable_reconnect +--source include/wait_until_connected_again.inc +# rpl_end.inc needs to use the connection server_1 +connection server_1; +--enable_reconnect +--source include/wait_until_connected_again.inc +connection master; +--enable_reconnect +--source include/wait_until_connected_again.inc +set timestamp=1000000000; + +--echo # The table should be empty on the master. +let $binlog_file= master-bin.000002; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +SELECT * FROM `db1``; select 'oops!'`.`t``1`; + +--echo # The DELETE statement should be correctly quoted +--source include/show_binlog_events2.inc + +connection slave; +--source include/start_slave.inc + +connection master; +sync_slave_with_master; +connection slave; +--echo # The table should be empty on the slave also. +SELECT * FROM `db1``; select 'oops!'`.`t``1`; + +connection master; +DROP TABLE `db1``; select 'oops!'`.`t``1`; +sync_slave_with_master; + + +connection master; +use test; +DROP DATABASE `db1``; select 'oops!'`; + +--echo *** Test correct quoting of mysqlbinlog --rewrite-db option *** +CREATE TABLE t1 (a INT PRIMARY KEY); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t1 VALUES(1); +--source include/show_binlog_events2.inc +let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1); +--exec $MYSQL_BINLOG --short-form --start-position=$binlog_start --stop-position=$pos2 --rewrite-db='test->ts`et' $MYSQLD_DATADIR/master-bin.000002 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev6020.test b/mysql-test/suite/rpl/t/rpl_mdev6020.test new file mode 100644 index 00000000..ec3fd92f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev6020.test @@ -0,0 +1,69 @@ +--source include/have_innodb.inc +--source include/have_partition.inc +--source include/have_binlog_format_mixed_or_row.inc +--source include/master-slave.inc +--connection slave +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 +--remove_file $datadir/master-bin.state +--copy_file $MYSQL_TEST_DIR/std_data/mdev6020-mysql-bin.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +SET SQL_LOG_BIN=0; +ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB; +SET SQL_LOG_BIN=1; +SET @old_engine= @@GLOBAL.default_storage_engine; +SET GLOBAL default_storage_engine=InnoDB; +SET @old_parallel= @@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=12; +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; +--source include/start_slave.inc + +--connection master +SET SQL_LOG_BIN=0; +ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB; +SET SQL_LOG_BIN=1; +--save_master_pos + +--connection slave +--sync_with_master + +SELECT @@gtid_slave_pos; +CHECKSUM TABLE table0_int_autoinc, table0_key_pk_parts_2_int_autoinc, table100_int_autoinc, table100_key_pk_parts_2_int_autoinc, table10_int_autoinc, table10_key_pk_parts_2_int_autoinc, table1_int_autoinc, table1_key_pk_parts_2_int_autoinc, table2_int_autoinc, table2_key_pk_parts_2_int_autoinc; + +--source include/stop_slave.inc + + +SET GLOBAL default_storage_engine= @old_engine; +SET GLOBAL slave_parallel_threads=@old_parallel; +SET sql_log_bin=0; +DROP TABLE table0_int_autoinc; +DROP TABLE table0_key_pk_parts_2_int_autoinc; +DROP TABLE table100_int_autoinc; +DROP TABLE table100_key_pk_parts_2_int_autoinc; +DROP TABLE table10_int_autoinc; +DROP TABLE table10_key_pk_parts_2_int_autoinc; +DROP TABLE table1_int_autoinc; +DROP TABLE table1_key_pk_parts_2_int_autoinc; +DROP TABLE table2_int_autoinc; +DROP TABLE table2_key_pk_parts_2_int_autoinc; +SET sql_log_bin=1; + +--source include/start_slave.inc + +--connection master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt b/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt new file mode 100644 index 00000000..a5d959ae --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev6386-slave.opt @@ -0,0 +1 @@ +--disable-log-slave-updates diff --git a/mysql-test/suite/rpl/t/rpl_mdev6386.test b/mysql-test/suite/rpl/t/rpl_mdev6386.test new file mode 100644 index 00000000..e6fb72dc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev6386.test @@ -0,0 +1,71 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE = InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) Engine=InnoDB; +--sync_slave_with_master + +--connection slave +--source include/stop_slave.inc +# Provoke a duplicate key error on replication. +SET sql_log_bin= 0; +CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); +INSERT INTO t1 VALUES (1, 2); +SET sql_log_bin= 1; +CHANGE MASTER TO master_use_gtid= current_pos; +--echo Contents on slave before: +SELECT * FROM t1 ORDER BY a; + +SET @old_parallel= @@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=8; + +--connection master + +CREATE TEMPORARY TABLE t2 LIKE t1; +INSERT INTO t2 VALUE (1, 1); +INSERT INTO t2 VALUE (2, 1); +INSERT INTO t2 VALUE (3, 1); +INSERT INTO t2 VALUE (4, 1); +INSERT INTO t2 VALUE (5, 1); +INSERT INTO t1 SELECT * FROM t2; +DROP TEMPORARY TABLE t2; +INSERT INTO t1 VALUE (6, 3); +--source include/save_master_gtid.inc +--echo Contents on master: +SELECT * FROM t1 ORDER BY a; + +--connection slave +START SLAVE; +# The slave will stop with a duplicate key error. +# The bug was 1) that the next DROP TEMPORARY TABLE would be allowed to run +# anyway, and 2) that then record_gtid() would get an error during commit +# (since the prior commit failed), and this error was not correctly handled, +# which caused an assertion about closing tables while a statement was still +# active. +--let $slave_sql_errno=1062 +--source include/wait_for_slave_sql_error.inc + +STOP SLAVE IO_THREAD; +--echo Contents on slave on slave error: +SELECT * FROM t1 ORDER BY a; + +# Resolve the duplicate key error so replication can be resumed. +SET sql_log_bin= 0; +DELETE FROM t1 WHERE a=1; +SET sql_log_bin= 1; + +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +--echo Contents on slave after: +SELECT * FROM t1 ORDER BY a; + +--connection master +DROP TABLE t1; + +--connection slave +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads= @old_parallel; +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev8193.test b/mysql-test/suite/rpl/t/rpl_mdev8193.test new file mode 100644 index 00000000..dcad3e5f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev8193.test @@ -0,0 +1,56 @@ +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +--connection slave + +--source include/stop_slave_sql.inc + +--connection master + +CALL mtr.add_suppression("Statement is unsafe because it uses a system function that may return a different value on the slave"); +create table t1 (i int); +insert into t1 values (1),(2); +insert into t1 values (3),(4); +# This sleep() helps trigger the failure more reliably. +insert into t1 select i+20+0*sleep(1) from t1 where i=1; +flush logs; +insert into t1 values (5),(6); +insert into t1 values (7),(8); +insert into t1 values (9),(10); + +--let $master_file = query_get_value(show master status,File,1) +--let $master_pos = query_get_value(show master status,Position,1) + +insert into t1 values (11),(12); +insert into t1 values (13),(14); +insert into t1 values (15),(16); + +--connection slave + +set global slave_parallel_threads = 1; +--replace_result $master_file MASTER_FILE $master_pos MASTER_POS +eval start slave until master_log_file='$master_file', master_log_pos=$master_pos; + +--let $show_statement = SHOW SLAVE STATUS +--let $field = Slave_SQL_Running +--let $condition = = 'No' +--let $wait_timeout = 10 + +--source include/wait_show_condition.inc + +if (`select COUNT(*) > 11 from t1`) +{ + query_vertical show slave status; + SELECT * FROM t1; + die "Wrong number of rows in the table"; +} + +drop table t1; +--source include/stop_slave_io.inc +set global slave_parallel_threads = DEFAULT; + +--connection master +drop table t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev_17614.test b/mysql-test/suite/rpl/t/rpl_mdev_17614.test new file mode 100644 index 00000000..9b86c8c1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev_17614.test @@ -0,0 +1,121 @@ +source include/have_debug.inc; +source include/have_innodb.inc; +-- source include/have_binlog_format_statement.inc +source include/master-slave.inc; +# MDEV-17614 +# INSERT on dup key update is replication unsafe +# There can be three case +# 1. 2 unique key, Replication is unsafe. +# 2. 2 unique key , with one auto increment key, Safe to replicate because Innodb will acquire gap lock +# 3. n no of unique keys (n>1) but insert is only in 1 unique key +# 4. 2 unique key , with one auto increment key(but user gives auto inc value), unsafe to replicate + +# Case 1 +call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT, +UNIQUE(b), c int) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (1, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); + --connection master1 + INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +--connection master +COMMIT; +SELECT * FROM t1; +--connection slave +# show the error message +--let $slave_sql_errno= 1062 +--let $show_slave_sql_error= 1 +--source include/wait_for_slave_sql_error.inc +--echo #Different value from server +SELECT * FROM t1; + +# restart replication for the next testcase +stop slave; +--source include/wait_for_slave_to_stop.inc +reset slave; +connection master; +reset master; +drop table t1; +connection slave; +start slave; +--source include/wait_for_slave_to_start.inc +# Case 2 +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, +UNIQUE(b), c int) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (default, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); + --connection master1 + INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +--connection master +COMMIT; +SELECT * FROM t1; +--sync_slave_with_master +--echo #same data as master +SELECT * FROM t1; + +connection master; +drop table t1; +--sync_slave_with_master + +# Case 3 +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT, +UNIQUE(b), c int, d int ) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (1, 1, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); + --connection master1 + INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +--connection master +COMMIT; +SELECT * FROM t1; +--sync_slave_with_master +--echo #same data as master +SELECT * FROM t1; +connection master; +drop table t1; +--sync_slave_with_master + +# Case 4 +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT, +UNIQUE(b), c int) engine=innodb; +sync_slave_with_master; +connection master; +INSERT INTO t1 VALUES (1, 1, 1); +BEGIN; +INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); + --connection master1 + INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c); +--connection master +COMMIT; +SELECT * FROM t1; +--connection slave +# show the error message +--let $slave_sql_errno= 1062 +--let $show_slave_sql_error= 1 +--source include/wait_for_slave_sql_error.inc +--echo #Different value from server +SELECT * FROM t1; + +# restart replication for the next testcase +stop slave; +--source include/wait_for_slave_to_stop.inc +reset slave; +connection master; +reset master; +drop table t1; +connection slave; +start slave; +--source include/wait_for_slave_to_start.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh b/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh new file mode 100644 index 00000000..8ce79797 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_misc_functions-slave.sh @@ -0,0 +1 @@ +rm -f $MYSQLTEST_VARDIR/master-data/test/rpl_misc_functions.outfile diff --git a/mysql-test/suite/rpl/t/rpl_misc_functions.test b/mysql-test/suite/rpl/t/rpl_misc_functions.test new file mode 100644 index 00000000..7189e5c4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_misc_functions.test @@ -0,0 +1,127 @@ +# +# Test of replicating some difficult functions +# +source include/master-slave.inc; + +CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); + +create table t1(id int, i int, r1 int, r2 int, p varchar(100)); +insert into t1 values(1, connection_id(), 0, 0, ""); +# don't put rand and password in the same query, to see if they replicate +# independently +# Pure rand test +--disable_warnings +insert into t1 values(2, 0, rand()*1000, rand()*1000, ""); +--enable_warnings +# change the rand suite on the master (we do this because otherwise password() +# benefits from the fact that the above rand() is well replicated : +# it picks the same sequence element, which hides a possible bug in password() replication. +set sql_log_bin=0; +insert into t1 values(6, 0, rand(), rand(), ""); +delete from t1 where id=6; +set sql_log_bin=1; +# Pure password test +insert into t1 values(3, 0, 0, 0, password('does_this_work?')); +# "altogether now" +--disable_warnings +insert into t1 values(4, connection_id(), rand()*1000, rand()*1000, password('does_this_still_work?')); +--enable_warnings +select * into outfile 'rpl_misc_functions.outfile' from t1; +let $MYSQLD_DATADIR= `select @@datadir`; +sync_slave_with_master; +create temporary table t2 like t1; +# read the values from the master table +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +eval load data local infile '$MYSQLD_DATADIR/test/rpl_misc_functions.outfile' into table t2; +# compare them with the replica; the SELECT below should return no row +select * from t1, t2 where (t1.id=t2.id) and not(t1.i=t2.i and t1.r1=t2.r1 and t1.r2=t2.r2 and t1.p=t2.p); + +connection master; +drop table t1; + +# End of 4.1 tests + +# +# BUG#25543 test calling rand() multiple times on the master in +# a stored procedure. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + col_a DOUBLE DEFAULT NULL); + +DELIMITER |; + +# Use a SP that calls rand() multiple times +CREATE PROCEDURE test_replication_sp1() +BEGIN + INSERT INTO t1 (col_a) VALUES (rand()), (rand()); + INSERT INTO t1 (col_a) VALUES (rand()); +END| + +# Use a SP that calls another SP to call rand() multiple times +CREATE PROCEDURE test_replication_sp2() +BEGIN + CALL test_replication_sp1(); + CALL test_replication_sp1(); +END| + +# Use a SF that calls rand() multiple times +CREATE FUNCTION test_replication_sf() RETURNS DOUBLE DETERMINISTIC +BEGIN + RETURN (rand() + rand()); +END| + +DELIMITER ;| + +# Exercise the functions and procedures then compare the results on +# the master to those on the slave. +--disable_warnings +CALL test_replication_sp1(); +CALL test_replication_sp2(); +INSERT INTO t1 (col_a) VALUES (test_replication_sf()); +INSERT INTO t1 (col_a) VALUES (test_replication_sf()); +INSERT INTO t1 (col_a) VALUES (test_replication_sf()); +--enable_warnings + +--sync_slave_with_master + +# Dump table on slave +select * from t1 into outfile "../../tmp/t1_slave.txt"; + +# Load data from slave into temp table on master +connection master; +--disable_warnings +create temporary table t1_slave select * from t1 where 1=0; +--enable_warnings +load data infile '../../tmp/t1_slave.txt' into table t1_slave; +--remove_file $MYSQLTEST_VARDIR/tmp/t1_slave.txt + +# Compare master and slave temp table, use subtraction +# for floating point comparison of "double" +select count(*) into @aux from t1 join t1_slave using (id) +where ABS(t1.col_a - t1_slave.col_a) < 0.0000001 ; +SELECT @aux; +if (`SELECT @aux <> 12 OR @aux IS NULL`) +{ + --echo # ERROR: We expected to get count(*) = 12. + SELECT id, col_a FROM t1; + SELECT id, col_a FROM t1_slave; + --echo # abort + exit; +} + +# Cleanup +connection master; +DROP TABLE t1, t1_slave; +DROP PROCEDURE test_replication_sp1; +DROP PROCEDURE test_replication_sp2; +DROP FUNCTION test_replication_sf; +--remove_file $MYSQLD_DATADIR/test/rpl_misc_functions.outfile +--sync_slave_with_master + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mix_found_rows.test b/mysql-test/suite/rpl/t/rpl_mix_found_rows.test new file mode 100644 index 00000000..c8b2eaef --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mix_found_rows.test @@ -0,0 +1,150 @@ +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +# It is not possible to replicate FOUND_ROWS() using statement-based +# replication, but there is a workaround that stores the result of +# FOUND_ROWS() into a user variable and then replicates this instead. +# +# The purpose of this test case is to test that the workaround works +# properly even when inside stored programs (i.e., stored routines and +# triggers). + +--echo ==== Initialize ==== + +connection master; +CREATE TABLE t1 (a INT); +CREATE TABLE logtbl (sect INT, test INT, count INT); + +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; + +--echo ==== Checking a procedure ==== + +connection master; + +# We will now check some stuff that will not work in statement-based +# replication, but which should cause the binary log to switch to +# row-based logging. + +--delimiter $$ +CREATE PROCEDURE just_log(sect INT, test INT) BEGIN + INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS()); +END $$ +--delimiter ; +sync_slave_with_master; + +connection master1; +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +CALL just_log(1,1); + +connection master; +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +CALL just_log(1,2); + +connection master1; +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1; +CALL just_log(1,3); +sync_slave_with_master; + +connection master; +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +CALL just_log(1,4); +sync_slave_with_master; + +connection master; +SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test; +sync_slave_with_master; +SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test; + +--echo ==== Checking a stored function ==== +connection master; +--delimiter $$ +CREATE FUNCTION log_rows(sect INT, test INT) + RETURNS INT +BEGIN + DECLARE found_rows INT; + SELECT FOUND_ROWS() INTO found_rows; + INSERT INTO logtbl VALUES(sect,test,found_rows); + RETURN found_rows; +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1; +SELECT log_rows(2,1), log_rows(2,2); + +CREATE TABLE t2 (a INT, b INT); + +# Trying with referencing FOUND_ROWS() directly in the trigger. + +--delimiter $$ +CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW +BEGIN + INSERT INTO logtbl VALUES (NEW.a, NEW.b, FOUND_ROWS()); +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1; +INSERT INTO t2 VALUES (2,3), (2,4); + +# Referencing FOUND_ROWS() indirectly. + +DROP TRIGGER t2_tr; + +--delimiter $$ +CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW +BEGIN + DECLARE dummy INT; + SELECT log_rows(NEW.a, NEW.b) INTO dummy; +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +INSERT INTO t2 VALUES (2,5), (2,6); + +# Putting FOUND_ROWS() even lower in the call chain. + +connection master; +DROP TRIGGER t2_tr; + +--delimiter $$ +CREATE PROCEDURE log_me_inner(sect INT, test INT) +BEGIN + DECLARE dummy INT; + SELECT log_rows(sect, test) INTO dummy; + SELECT log_rows(sect, test+1) INTO dummy; +END $$ + +CREATE PROCEDURE log_me(sect INT, test INT) +BEGIN + CALL log_me_inner(sect,test); +END $$ +--delimiter ; + +--delimiter $$ +CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW +BEGIN + CALL log_me(NEW.a, NEW.b); +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +INSERT INTO t2 VALUES (2,5), (2,6); + +SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test; +sync_slave_with_master; +SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test; + +connection master; +DROP TABLE t1, t2, logtbl; +DROP PROCEDURE just_log; +DROP PROCEDURE log_me; +DROP PROCEDURE log_me_inner; +DROP FUNCTION log_rows; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test new file mode 100644 index 00000000..c4c89d90 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_binlog_max_cache_size.test @@ -0,0 +1,8 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--source include/rpl_binlog_max_cache_size.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test b/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test new file mode 100644 index 00000000..226a82de --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_bit_pk.test @@ -0,0 +1,83 @@ +# +# BUG +# --- +# BUG#39753: Replication failure on MIXED + bit + myisam + no PK +# +# Description +# ----------- +# Simple statements against a bit column cause failure in mixed-mode +# replication. +# +# Implementation is as follows: +# i) A table with two bit fields is created. One of them is a key. +# ii) A record is inserted without specifying the key value. +# iii) The record is deleted using a where clause that matches it. +# iv) repeat i-iii) for bit key that has different size, generating +# different extra bits values +# v) The slave is synchronized with master +# vi) The table is dropped on master and the slave is re-synchronized +# with master. +# +# Step v) made the bug evident before the patch, as the slave would +# fail to find the correspondent row in its database (although it did +# the insert in step ii) ). +# +# Obs +# --- +# This test is based on the "how to repeat" section from the bug report. +# +# + +--source include/master-slave.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +--disable_warnings +# setup + +DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8; +CREATE TABLE t1 (`bit_key` bit, `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t2 (`bit_key` bit(4), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t3 (`bit_key` bit(7), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t4 (`bit_key` bit(8), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t5 (`bit_key` bit(9), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t6 (`bit_key` bit(14), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t7 (`bit_key` bit(15), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; +CREATE TABLE t8 (`bit_key` bit(16), `bit` bit, key (`bit_key` )) ENGINE=MyISAM; + +# insert and delete +INSERT INTO `t1` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t1` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t2` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t2` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t3` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t3` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t4` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t4` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t5` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t5` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t6` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t6` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t7` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t7` WHERE `bit` < 2 LIMIT 4; + +INSERT INTO `t8` ( `bit` ) VALUES ( 0 ); +DELETE FROM `t8` WHERE `bit` < 2 LIMIT 4; + + +--enable_warnings +sync_slave_with_master; + +# clean up +connection master; +DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test new file mode 100644 index 00000000..f4a1615a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test @@ -0,0 +1,51 @@ +# Mixed DDL-DML (CREATE ... SELECT ...) statements can only be +# replicated properly in statement-based replication. +# Currently statement based due to bug 12345 +--source include/have_binlog_format_mixed_or_statement.inc + +source include/master-slave.inc; + +# Test replication of auto_increment + +create table t1 (n int auto_increment primary key); +set insert_id = 2000; +insert into t1 values (NULL),(NULL),(NULL); +sync_slave_with_master; +select * from t1; +connection master; +--replace_result $SLAVE_MYPORT 9999 +show slave hosts; +drop table t1; +sync_slave_with_master; +stop slave; +--source include/wait_for_slave_to_stop.inc +connection master; + +# Test replication of timestamp + +create table t2(id int auto_increment primary key, created datetime); +SET TIME_ZONE= '+03:00'; +set timestamp=12345; +insert into t2 set created=now(); +select * from t2; + +# Test replication of CREATE .. LIKE (Bug #2557) + +create table t3 like t2; +create temporary table t4 like t2; +create table t5 select * from t4; +save_master_pos; +connection slave; +start slave; +--source include/wait_for_slave_to_start.inc +sync_with_master; +select * from t2; +show create table t3; +show create table t5; +connection master; +drop table t2,t3,t5; +drop temporary table t4; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test new file mode 100644 index 00000000..e707bb99 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_drop_create_temp_table.test @@ -0,0 +1,12 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. Specifically when drop temporary tables and create temporary tables +# are used. +################################################################################### +--source include/big_test.inc +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--source include/rpl_drop_create_temp_table.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test new file mode 100644 index 00000000..8e40295e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_implicit_commit_binlog.test @@ -0,0 +1,12 @@ +################################################################################ +# Check file include/rpl_implicit_commit_binlog.test +################################################################################ +--source include/have_udf.inc +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--let $engine=Innodb +set session default_storage_engine=innodb; +--source include/rpl_implicit_commit_binlog.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test new file mode 100644 index 00000000..1df53270 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_mixing_engines.test @@ -0,0 +1,12 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt new file mode 100644 index 00000000..96f0ce3f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mixed_row_innodb-master.opt @@ -0,0 +1 @@ +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt new file mode 100644 index 00000000..c98fe0b0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_delete-slave.opt @@ -0,0 +1 @@ +--replicate-wild-do-table=test.% diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete.test b/mysql-test/suite/rpl/t/rpl_multi_delete.test new file mode 100644 index 00000000..80acf9c8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_delete.test @@ -0,0 +1,25 @@ +source include/master-slave.inc; +create table t1 (a int primary key); +create table t2 (a int); + +insert into t1 values (1); +insert into t2 values (1); + + +delete t1.* from t1, t2 where t1.a = t2.a; + +save_master_pos; +select * from t1; +select * from t2; + +connection slave; +sync_with_master; +select * from t1; +select * from t2; + +connection master; +drop table t1,t2; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt new file mode 100644 index 00000000..0febb289 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_delete2-slave.opt @@ -0,0 +1 @@ +"--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a diff --git a/mysql-test/suite/rpl/t/rpl_multi_delete2.test b/mysql-test/suite/rpl/t/rpl_multi_delete2.test new file mode 100644 index 00000000..7dc7ca41 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_delete2.test @@ -0,0 +1,67 @@ +#multi delete replication bugs + + +source include/master-slave.inc; + +#BUG#11139 - improper wild-table and table rules +#checking for multi deletes with an alias + +connection master; +set sql_log_bin=0; +create database mysqltest_from; +set sql_log_bin=1; + +connection slave; +create database mysqltest_to; + + +connection master; +use mysqltest_from; +--disable_warnings +drop table if exists a; +--enable_warnings +CREATE TABLE a (i INT); +INSERT INTO a VALUES(1); +DELETE alias FROM a alias WHERE alias.i=1; +SELECT * FROM a; +insert into a values(2),(3); +delete alias FROM a alias where alias.i=2; +select * from a; +sync_slave_with_master; + +use mysqltest_to; +select * from a; + +# BUG#3461 +connection master; +create table t1 (a int primary key); +create table t2 (a int); + +insert into t1 values (1); +insert into t2 values (1); + +delete t1.* from t1, t2 where t1.a = t2.a; + +save_master_pos; +select * from t1; +select * from t2; + +connection slave; +# BUG#3461 would cause sync to fail +sync_with_master; +error 1146; +select * from t1; +error 1146; +select * from t2; + +# cleanup +connection master; +set sql_log_bin=0; +drop database mysqltest_from; +set sql_log_bin=1; +connection slave; +drop database mysqltest_to; + +# End of 4.1 tests + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_engine.test b/mysql-test/suite/rpl/t/rpl_multi_engine.test new file mode 100644 index 00000000..704c0935 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_engine.test @@ -0,0 +1,102 @@ +# See if replication between MyISAM, MEMORY and InnoDB works. + +-- source include/master-slave.inc + +connection slave; +-- source include/have_innodb.inc + +connection master; +-- source include/have_innodb.inc +--disable_warnings +drop table if exists t1; +--enable_warnings + +CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc +VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT +0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY(id)); + +sync_slave_with_master; + +# MyISAM to MyISAM then InnoDB then MEMORY + +connection master; +alter table t1 engine=myisam; +show create table t1; +sync_slave_with_master; + +connection slave; +alter table t1 engine=myisam; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=innodb; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=memory; +show create table t1; + +--source include/rpl_multi_engine.inc + +# MEMORY to ... + +connection master; +alter table t1 engine=memory; +show create table t1; +sync_slave_with_master; + +connection slave; +alter table t1 engine=myisam; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=innodb; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=memory; +show create table t1; + +--source include/rpl_multi_engine.inc + +# InnoDB to ... + +connection master; +alter table t1 engine=innodb; +show create table t1; +sync_slave_with_master; + +connection slave; +alter table t1 engine=myisam; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=innodb; +show create table t1; + +--source include/rpl_multi_engine.inc + +connection slave; +alter table t1 engine=memory; +show create table t1; + +--source include/rpl_multi_engine.inc + +# cleanup +connection master; +DROP TABLE t1; +sync_slave_with_master; + +# End of 5.1 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_update.test b/mysql-test/suite/rpl/t/rpl_multi_update.test new file mode 100644 index 00000000..3927ed69 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update.test @@ -0,0 +1,2 @@ +let $engine_type=MyISAM; +-- source include/rpl_multi_update.test diff --git a/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt new file mode 100644 index 00000000..17d4171a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update2-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=nothing.sensible diff --git a/mysql-test/suite/rpl/t/rpl_multi_update2.test b/mysql-test/suite/rpl/t/rpl_multi_update2.test new file mode 100644 index 00000000..d2368f20 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update2.test @@ -0,0 +1,9 @@ +####################################################### +# Wrapper for rpl_multi_update2.test to allow multi # +# Engines to reuse test code. By JBM 2006-02-15 # +####################################################### +--source include/master-slave.inc +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); +let $engine_type=MyISAM; +--source include/rpl_multi_update2.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_update3.test b/mysql-test/suite/rpl/t/rpl_multi_update3.test new file mode 100644 index 00000000..0a15e9aa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update3.test @@ -0,0 +1,9 @@ +####################################################### +# Wrapper for rpl_multi_update3.test to allow multi # +# Engines to reuse test code. By JBM 2006-02-15 # +####################################################### +--source include/master-slave.inc +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); +let $engine_type=MyISAM; +-- source include/rpl_multi_update3.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt b/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt new file mode 100644 index 00000000..fea27db4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update4-slave.opt @@ -0,0 +1 @@ +--replicate-wild-do-table=d1.% diff --git a/mysql-test/suite/rpl/t/rpl_multi_update4.test b/mysql-test/suite/rpl/t/rpl_multi_update4.test new file mode 100644 index 00000000..8f069b9c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_multi_update4.test @@ -0,0 +1,46 @@ +# Let's verify that multi-update is not always skipped by slave if +# some replicate-* rules exist. +# (BUG#15699) + +source include/master-slave.inc; + +### Clean-up + +connection master; +--disable_warnings +drop database if exists d1; +drop database if exists d2; + +connection slave; +drop database if exists d2; +--enable_warnings + +### Do on master + +connection master; +create database d1; # accepted by slave +create table d1.t0 (id int); +create database d2; # ignored by slave +use d2; +create table t1 (id int); +create table t2 (id int); +insert into t1 values (1), (2), (3), (4), (5); +insert into t2 select id + 3 from t1; +# a problematic query which must be filter out by slave +update t1 join t2 using (id) set t1.id = 0; +insert into d1.t0 values (0); # replication works + +### Check on slave + +sync_slave_with_master; +use d1; +select * from t0 where id=0; # must find + +### Clean-up +connection master; +drop database d1; +drop database d2; +sync_slave_with_master; + +# End of test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test new file mode 100644 index 00000000..675b7db0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test @@ -0,0 +1,58 @@ +--source include/have_binlog_format_statement.inc + +--echo # +--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +--echo # + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 + +# +# Simulate MySQL 5.7.x master +# +# mysql-5.7.11-stm-temporal-round-binlog.000001 was recorded against a +# table with this structure: +#CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +# (note, the CREATE statement is not inside the binary log) +# +# using this command line: +# mysqld --log-bin --binlog-format=statement +# with the following single SQL statement: +# +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +# + +--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; + +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +SELECT * FROM t1 ORDER BY id; + +--source include/stop_slave.inc +DROP TABLE t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test new file mode 100644 index 00000000..ad6df9d9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test @@ -0,0 +1,62 @@ +--source include/have_binlog_format_statement.inc + +--echo # +--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +--echo # + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 + +# +# Simulate MySQL 8.0.x master +# +# mysql-8.0.13-stm-temporal-round-binlog.000001 was recorded against a +# table with this structure: +#CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +# (note, the CREATE statement is not inside the binary log) +# +# using this command line: +# mysqld --log-bin --binlog-format=statement --server-id=1 --character-set-server=latin1 +# with the following SQL script: +# +#SET NAMES latin1 COLLATE latin1_swedish_ci; +#SET sql_mode=''; +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +#SET sql_mode=TIME_TRUNCATE_FRACTIONAL; +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +# + +--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; + +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +SELECT * FROM t1 ORDER BY id; + +--source include/stop_slave.inc +DROP TABLE t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test new file mode 100644 index 00000000..f44c883e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test @@ -0,0 +1,80 @@ +############################################################################# +# BUG#43579 mysql_upgrade tries to alter log tables on replicated database +# Master and slave should be upgraded separately. All statements executed by +# mysql_upgrade will not be binlogged. --write-binlog and --skip-write-binlog +# options are added into mysql_upgrade. These options control whether sql +# statements are binlogged or not. +############################################################################# +--source include/have_innodb.inc +--source include/mysql_upgrade_preparation.inc +--source include/master-slave.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("table or database name 'mysqltest-1'"); + +connection master; +--disable_warnings +CREATE DATABASE `mysqltest-1`; +--enable_warnings +sync_slave_with_master; + +connection master; +let $before_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +#With '--force' option, mysql_upgrade always executes all sql statements for upgrading. +--exec $MYSQL_UPGRADE --skip-verbose --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1 +sync_slave_with_master; + +connection master; +let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +if ($before_position == $after_position) +{ + echo Master position is not changed; +} + +# Some log events of the mysql_upgrade previously caused errors on slave, +# however with MDEV-4851 this should be ok, so we test it: +connection slave; +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; +SET @old_log_output = @@global.log_output; +SET GLOBAL general_log = 'ON'; +SET GLOBAL slow_query_log = 'ON'; +SET GLOBAL log_output = 'FILE'; + +connection master; +#With '--force' option, mysql_upgrade always executes all sql statements for upgrading. +ALTER TABLE mysql.slow_log DROP COLUMN thread_id, DROP COLUMN rows_affected; +DROP DATABASE `mysqltest-1`; +sync_slave_with_master; + +connection slave; +SHOW CREATE TABLE mysql.slow_log; +connection master; +--exec $MYSQL_UPGRADE --skip-verbose --write-binlog --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1 + +let $datadir= `select @@datadir`; +remove_file $datadir/mysql_upgrade_info; + +connection master; +let $after_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +if ($before_position != $after_position) +{ + echo Master position has been changed; +} + +sync_slave_with_master; +connection slave; +SHOW CREATE TABLE mysql.slow_log; +SET GLOBAL general_log = 'OFF'; +SET GLOBAL slow_query_log = 'OFF'; +truncate mysql.slow_log; +truncate mysql.general_log; +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; +SET GLOBAL log_output = @old_log_output; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_name_const.test b/mysql-test/suite/rpl/t/rpl_name_const.test new file mode 100644 index 00000000..074bc148 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_name_const.test @@ -0,0 +1,45 @@ +# ==== Purpose ==== +# +# Test that aliases of variables in binary log aren't ignored with NAME_CONST. +# +# ==== Method ==== +# +# Create a procedure with aliases of variables, then replicate it to slave. +# BUG#35515 Aliases of variables in binary log are ignored with NAME_CONST. +# + +source include/master-slave.inc; + +--echo ==== Initialize ==== + +--connection master + +create table t1 (id int); + +--echo ==== create a procedure that has a column aliase in a subquery ==== +--disable_warnings +drop procedure if exists test_procedure; +--enable_warnings +delimiter $$; +create procedure test_procedure(_id int) +begin +insert into t1 (id) +select a.id +from +( select _id as id ) a; +end;$$ +delimiter ;$$ + +--echo ==== enable the binary log, then call the procedure ==== +call test_procedure(1234); + + +sync_slave_with_master; +select * from t1 order by id; + +--echo ==== Clean up ==== + +connection master; +drop table t1; +drop procedure test_procedure; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test new file mode 100644 index 00000000..1f2f8749 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_non_direct_mixed_mixing_engines.test @@ -0,0 +1,15 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_mixed.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--disable_query_log +SET SESSION binlog_direct_non_transactional_updates = OFF; +--enable_query_log +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test new file mode 100644 index 00000000..b4552c79 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_non_direct_row_mixing_engines.test @@ -0,0 +1,17 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--disable_query_log +SET SESSION binlog_direct_non_transactional_updates = OFF; +--enable_query_log +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test + +--diff_files suite/rpl/r/rpl_non_direct_row_mixing_engines.result suite/rpl/r/rpl_row_mixing_engines.result +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test new file mode 100644 index 00000000..23552515 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_non_direct_stm_mixing_engines.test @@ -0,0 +1,15 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--disable_query_log +SET SESSION binlog_direct_non_transactional_updates = OFF; +--enable_query_log +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test new file mode 100644 index 00000000..a174445f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_nondeterministic_functions.test @@ -0,0 +1,58 @@ +# ==== Purpose ==== +# +# Test that nondeterministic system functions are correctly replicated. +# +# (Some functions are only correctly replicated if binlog_format=MIXED +# or ROW. See binlog_unsafe.test for a test that those variables are +# indeed unsafe.) +# +# ==== Implementation ==== +# +# We insert the values of each unsafe function into a table. Then we +# replicate and check that the table is identical on slave. +# +# ==== Related bugs ==== +# +# BUG#47995 + +--source include/master-slave.inc + +CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); + +CREATE TABLE t1 (a VARCHAR(1000)); + +# We replicate the connection_id in the query_log_event +INSERT INTO t1 VALUES (CONNECTION_ID()); +--connection master1 +INSERT INTO t1 VALUES (CONNECTION_ID()); + +# We replicate the TIMESTAMP variable, so the following functions that +# are affected by the TIMESTAMP variable should be safe to replicate. +INSERT INTO t1 VALUES + (CURDATE()), + (CURRENT_DATE()), + (CURRENT_TIME()), + (CURRENT_TIMESTAMP()), + (CURTIME()), + (LOCALTIME()), + (LOCALTIMESTAMP()), + (NOW()), + (UNIX_TIMESTAMP()), + (UTC_DATE()), + (UTC_TIME()), + (UTC_TIMESTAMP()); + +# We replicate the random seed in a rand_log_event +--disable_warnings +INSERT INTO t1 VALUES (RAND()); +--enable_warnings +# We replicate the last_insert_id in an intvar_log_event +INSERT INTO t1 VALUES (LAST_INSERT_ID()); + +--sync_slave_with_master +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + +--connection master +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_not_null_innodb.test b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test new file mode 100644 index 00000000..0e67cd36 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_not_null_innodb.test @@ -0,0 +1,20 @@ +################################################################################# +# This test checks if the replication between "null" fields to either "null" +# fields or "not null" fields works properly. In the first case, the execution +# should work fine. In the second case, it may fail according to the sql_mode +# being used. +# +# The test is devided in three main parts: +# +# 1 - NULL --> NULL (no failures) +# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures) +# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures) +# +################################################################################# +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +let $engine=Innodb; +--source include/rpl_not_null.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_not_null_myisam.test b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test new file mode 100644 index 00000000..718761d6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_not_null_myisam.test @@ -0,0 +1,19 @@ +################################################################################# +# This test checks if the replication between "null" fields to either "null" +# fields or "not null" fields works properly. In the first case, the execution +# should work fine. In the second case, it may fail according to the sql_mode +# being used. +# +# The test is devided in three main parts: +# +# 1 - NULL --> NULL (no failures) +# 2 - NULL --> NOT NULL ( sql-mode = STRICT and failures) +# 3 - NULL --> NOT NULL ( sql-mode != STRICT and no failures) +# +################################################################################# +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +let $engine=MyISAM; +--source include/rpl_not_null.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_old_decimal.test b/mysql-test/suite/rpl/t/rpl_old_decimal.test new file mode 100644 index 00000000..79fd2754 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_old_decimal.test @@ -0,0 +1,25 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + + +--connection slave +CREATE TABLE t1dec102 (a DECIMAL(10,2)); + +--connection master +let $MYSQLD_DATADIR= `select @@datadir`; + +--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm +--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD +--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI +INSERT INTO t1dec102 VALUES(999.99); + +--let $slave_sql_errno=1677 +--let $show_slave_sql_error= 1 +call mtr.add_suppression("Slave SQL.*Column 0 of table .* cannot be converted from type.* Error_code: 1677"); +--source include/wait_for_slave_sql_error_and_skip.inc + +--connection master +DROP TABLE t1dec102; +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_old_master.test b/mysql-test/suite/rpl/t/rpl_old_master.test new file mode 100644 index 00000000..6ddc227f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_old_master.test @@ -0,0 +1,57 @@ +# Test replicating off old master. +# We simulate old master by copying in pre-generated binlog files from earlier +# server versions. + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 +--copy_file $MYSQL_TEST_DIR/std_data/mariadb-5.5-binlog.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +SET @old_parallel= @@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=10; +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; + +# Block execution yet when the blocked query timestamp has been already accounted +FLUSH TABLES WITH READ LOCK; +--source include/start_slave.inc +--let $slave_param = Seconds_Behind_Master +--let $slave_param_value = 1 +--let $slave_param_comparison= >= +--source include/wait_for_slave_param.inc +UNLOCK TABLES; + +--connection master +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +--save_master_pos + +--connection slave +--sync_with_master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2; + +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel; +DROP TABLE t1; +--source include/start_slave.inc + +--connection master +DROP TABLE t2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_optimize.test b/mysql-test/suite/rpl/t/rpl_optimize.test new file mode 100644 index 00000000..bb960d4e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_optimize.test @@ -0,0 +1,65 @@ +# Test for BUG#1858 "OPTIMIZE TABLE done by a client +# thread stops the slave SQL thread". +# You can replace OPTIMIZE by REPAIR. +##################################### +# Change Author: JBM +# Change Date: 2006-02-09 +# OPTIMIZE for memory tables. If and when +# it does support for Disk Data, a new +# version of this test will be need. +##################################### +# Slow test, don't run during staging part +-- source include/not_staging.inc +-- source include/master-slave.inc + +--disable_warnings +drop tables if exists t1; +--enable_warnings + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +create table t1 (a int not null auto_increment primary key, b int, key(b)); +INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +--disable_warnings +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +INSERT INTO t1 (a) SELECT null FROM t1; +--enable_warnings +save_master_pos; +# a few updates to force OPTIMIZE to do something +--disable_warnings +update t1 set b=(a/2*rand()); +delete from t1 order by b limit 10000; +--enable_warnings + +connection slave; +sync_with_master; +optimize table t1; +connection master; +save_master_pos; +connection slave; +# Bug was that when the INSERT terminated on slave, +# the slave SQL thread got killed by OPTIMIZE. +sync_with_master; # won't work if slave SQL thread stopped + +connection master; # cleanup +drop table t1; +sync_slave_with_master; + +# If the machine is so fast that slave syncs before OPTIMIZE +# starts, this test will demonstrate nothing but will pass. + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_packet-master.opt b/mysql-test/suite/rpl/t/rpl_packet-master.opt new file mode 100644 index 00000000..412bc079 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_packet-master.opt @@ -0,0 +1 @@ +--max_allowed_packet=1024 --net_buffer_length=1024 diff --git a/mysql-test/suite/rpl/t/rpl_packet-slave.opt b/mysql-test/suite/rpl/t/rpl_packet-slave.opt new file mode 100644 index 00000000..1aed7d07 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_packet-slave.opt @@ -0,0 +1 @@ +--max_allowed_packet=1024 --net_buffer_length=1024 --slave_max_allowed_packet=1024 diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test new file mode 100644 index 00000000..1bf99c23 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_packet.test @@ -0,0 +1 @@ +--source include/rpl_packet.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel2.test b/mysql-test/suite/rpl/t/rpl_parallel2.test new file mode 100644 index 00000000..8934b15e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel2.test @@ -0,0 +1,230 @@ +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** MDEV-5509: Incorrect value for Seconds_Behind_Master if parallel replication *** + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +set @old_parallel_mode= @@GLOBAL.slave_parallel_mode; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=5; +set global slave_parallel_mode= optimistic; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY, b INT); +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave"); +--save_master_pos + +--connection server_2 +--sync_with_master + +--connection server_1 +INSERT INTO t1 VALUES (1,sleep(2)); +--save_master_pos + +--connection server_2 +--sync_with_master + +# The slave position (which --sync_with_master waits for) is updated just +# before the Seconds_Behind_Master. So we have to wait for the zero status +# to appear, otherwise there is a small window between --sync_with_master +# and SHOW SLAVE STATUS where we can see a non-zero value. +--let $slave_param= Seconds_Behind_Master +--let $slave_param_value= 0 +--source include/wait_for_slave_param.inc +--echo Seconds_Behind_Master should be zero here because the slave is fully caught up and idle. +--let $status_items= Seconds_Behind_Master +--source include/show_slave_status.inc + + +--echo *** MDEV-8294: Inconsistent behavior of slave parallel threads at runtime *** + +--connection server_1 +INSERT INTO t1 VALUES (10,0); +# Force a duplicate key error on the slave. +SET sql_log_bin= 0; +DELETE FROM t1 WHERE a=10; +SET sql_log_bin= 1; +INSERT INTO t1 VALUES (10,0); +--save_master_pos +SELECT * FROM t1 WHERE a >= 10 ORDER BY a; + +--connection server_2 +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc + +# At this point, the worker threads should have stopped also. +--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread"; +--source include/wait_condition.inc + +# Check that the pool can still be resized, but remains inactive as no slave +# SQL thread is running. +SET GLOBAL slave_parallel_threads=8; +--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread"; +--source include/wait_condition.inc + +STOP SLAVE; +# At this point, the worker threads should have stopped. +--let $wait_condition= SELECT COUNT(*)=0 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread"; +--source include/wait_condition.inc + + +SET GLOBAL sql_slave_skip_counter= 1; +--source include/start_slave.inc +# At this point, the worker threads should have been spawned. +--let $wait_condition= SELECT COUNT(*)=8 FROM information_schema.processlist WHERE User = "system user" AND State = "Waiting for work from SQL thread"; +--source include/wait_condition.inc +--sync_with_master +SELECT * FROM t1 WHERE a >= 10 ORDER BY a; + + +--echo *** MDEV-7818: Deadlock occurring with parallel replication and FTWRL *** + +--connection server_1 +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,0), (2,0), (3,0); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc + +--connection server_1 +# Create a group commit with two transactions, will be used to provoke the +# problematic thread interaction with FTWRL on the slave. +SET @old_dbug= @@SESSION.debug_dbug; +SET @commit_id= 4242; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; + +BEGIN; +UPDATE t2 SET b=b+1 WHERE a=2; +COMMIT; + +BEGIN; +INSERT INTO t2 VALUES (4,10); +COMMIT; + +SET SESSION debug_dbug= @old_dbug; + +INSERT INTO t2 VALUES (5,0); +INSERT INTO t2 VALUES (6,0); +INSERT INTO t2 VALUES (7,0); +INSERT INTO t2 VALUES (8,0); +INSERT INTO t2 VALUES (9,0); +INSERT INTO t2 VALUES (10,0); +INSERT INTO t2 VALUES (11,0); +INSERT INTO t2 VALUES (12,0); +INSERT INTO t2 VALUES (13,0); +INSERT INTO t2 VALUES (14,0); +INSERT INTO t2 VALUES (15,0); +INSERT INTO t2 VALUES (16,0); +INSERT INTO t2 VALUES (17,0); +INSERT INTO t2 VALUES (18,0); +INSERT INTO t2 VALUES (19,0); +--save_master_pos + +--connection server_2 + +--connect (s1, 127.0.0.1, root,, test, $SLAVE_MYPORT,) +# Block one transaction on a row lock. +BEGIN; +SELECT * FROM t2 WHERE a=2 FOR UPDATE; + +--connection server_2 + +# Wait for slave thread of the other transaction to have the commit lock. +--source include/start_slave.inc +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connect (s2, 127.0.0.1, root,, test, $SLAVE_MYPORT,) +send FLUSH TABLES WITH READ LOCK; +# The bug was that at this point we were deadlocked. +# The FTWRL command would wait forever for T2 to commit. +# T2 would wait for T1 to commit first, but T1 is waiting for +# the global read lock to be released. + +--connection s1 +# Release the lock that blocs T1 from replicating. +COMMIT; + +--connection s1 +send STOP SLAVE; + +--connection s2 +reap; + +--connection server_1 +SELECT * FROM t2 ORDER BY a; + +--connection s2 +UNLOCK TABLES; + +SELECT "after UNLOCK TABLES" as state; + +--connection s1 +reap; + +SELECT "after reap of STOP SLAVE" as state; + +--connection server_2 +--source include/wait_for_slave_to_stop.inc +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t2 ORDER BY a; + + + +--echo *** MDEV-8318: Assertion `!pool->busy' failed in pool_mark_busy(rpl_parallel_thread_pool*) on concurrent FTWRL *** + +--connection server_1 +LOCK TABLE t2 WRITE; + + +--connect (m1,localhost,root,,test) +--connection m1 +--let $cid=`SELECT CONNECTION_ID()` +send FLUSH TABLES WITH READ LOCK; + +--connect (m2,localhost,root,,test) +# We cannot force the race with DEBUG_SYNC, because the race does not +# exist after fixing the bug. At best we could force a debug sync to +# time out, which is effectively just a sleep. +# So just put a small sleep here; it is enough to trigger the bug in +# most run before the bug fix, and the code should work correctly +# however the thread scheduling happens. +--sleep 0.1 +send FLUSH TABLES WITH READ LOCK; + +--connection server_1 +--replace_result $cid CID +eval KILL QUERY $cid; + +--connection m1 +--error ER_QUERY_INTERRUPTED +reap; + +--connection server_1 +UNLOCK TABLES; + +--connection m2 +reap; +UNLOCK TABLES; + + +# Clean up. +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +set global slave_parallel_mode= @old_parallel_mode; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test new file mode 100644 index 00000000..c1f1b9ba --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_analyze_table_hang.test @@ -0,0 +1 @@ +--source include/rpl_parallel_analyze_table_hang.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_charset.test b/mysql-test/suite/rpl/t/rpl_parallel_charset.test new file mode 100644 index 00000000..3e0f4913 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_charset.test @@ -0,0 +1,56 @@ +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** MDEV-6156: Parallel replication incorrectly caches charset between worker threads *** + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=5; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100) CHARACTER SET utf8); +SHOW CREATE TABLE t1; +SET character_set_client=latin1; +INSERT INTO t1 VALUES (1, 'Rødgrød med fløde 1'); +INSERT INTO t1 VALUES (2, 'Rødgrød med fløde 2'); +INSERT INTO t1 VALUES (3, 'Rødgrød med fløde 3'); +INSERT INTO t1 VALUES (4, 'Rødgrød med fløde 4'); +INSERT INTO t1 VALUES (5, 'Rødgrød med fløde 5'); +INSERT INTO t1 VALUES (6, 'Rødgrød med fløde 6'); +INSERT INTO t1 VALUES (7, 'Rødgrød med fløde 7'); +INSERT INTO t1 VALUES (8, 'Rødgrød med fløde 8'); +INSERT INTO t1 VALUES (9, 'Rødgrød med fløde 9'); +INSERT INTO t1 VALUES (10, 'Rødgrød med fløde 10'); +SET character_set_client=utf8; +INSERT INTO t1 VALUES (11, 'Rødgrød med fløde 1'); +INSERT INTO t1 VALUES (12, 'Rødgrød med fløde 2'); +INSERT INTO t1 VALUES (13, 'Rødgrød med fløde 3'); +INSERT INTO t1 VALUES (14, 'Rødgrød med fløde 4'); +INSERT INTO t1 VALUES (15, 'Rødgrød med fløde 5'); +INSERT INTO t1 VALUES (16, 'Rødgrød med fløde 6'); +INSERT INTO t1 VALUES (17, 'Rødgrød med fløde 7'); +INSERT INTO t1 VALUES (18, 'Rødgrød med fløde 8'); +INSERT INTO t1 VALUES (19, 'Rødgrød med fløde 9'); +INSERT INTO t1 VALUES (20, 'Rødgrød med fløde 10'); +SET character_set_results=utf8; +SELECT * FROM t1 ORDER BY a; +--save_master_pos + +--connection server_2 +--sync_with_master +SET character_set_results=utf8; +SELECT * FROM t1 ORDER BY a; + + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test new file mode 100644 index 00000000..0ba6a2b2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_conflicts.test @@ -0,0 +1,269 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc + +--echo *** MDEV-7847: "Slave worker thread retried transaction 10 time(s) in vain, giving up", followed by replication hanging *** +--echo *** MDEV-7882: Excessive transaction retry in parallel replication *** + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t7 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t8 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='conservative'; +SET @old_threads= @@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=40; +SET @old_transaction_retries= @@GLOBAL.slave_transaction_retries; +SET GLOBAL slave_transaction_retries=5; + +# Using dbug error injection, we artificially create event groups with a lot of +# conflicting transactions in each event group. The bugs were originally seen +# "in the wild" with transactions that did not conflict on the master, and only +# conflicted very rarely on the slave (maybe some edge case with InnoDB btree +# page splits or something like that). The event groups here loosely reflect +# the structure of the original failure's group commits. + + +--connection server_1 +INSERT INTO t7 VALUES (1,1), (2,2), (3,3), (4,4), (5,5); +SET @old_dbug= @@SESSION.debug_dbug; +SET @commit_id= 42; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; +INSERT INTO t8 VALUES (1,1); +INSERT INTO t8 VALUES (2,2); +INSERT INTO t8 VALUES (3,3); +INSERT INTO t8 VALUES (4,4); +INSERT INTO t8 VALUES (5,5); +INSERT INTO t8 VALUES (6,6); +INSERT INTO t8 VALUES (7,7); +INSERT INTO t8 VALUES (8,8); + +UPDATE t7 SET b=9 WHERE a=3; +UPDATE t7 SET b=10 WHERE a=3; +UPDATE t7 SET b=11 WHERE a=3; + +INSERT INTO t8 VALUES (12,12); +INSERT INTO t8 VALUES (13,13); + +UPDATE t7 SET b=14 WHERE a=3; +UPDATE t7 SET b=15 WHERE a=3; + +INSERT INTO t8 VALUES (16,16); + +UPDATE t7 SET b=17 WHERE a=3; + +INSERT INTO t8 VALUES (18,18); +INSERT INTO t8 VALUES (19,19); + +UPDATE t7 SET b=20 WHERE a=3; + +INSERT INTO t8 VALUES (21,21); + +UPDATE t7 SET b=22 WHERE a=3; + +INSERT INTO t8 VALUES (23,24); +INSERT INTO t8 VALUES (24,24); + +UPDATE t7 SET b=25 WHERE a=3; + +INSERT INTO t8 VALUES (26,26); + +UPDATE t7 SET b=27 WHERE a=3; + +BEGIN; +INSERT INTO t8 VALUES (28,28); +INSERT INTO t8 VALUES (29,28), (30,28); +INSERT INTO t8 VALUES (31,28); +INSERT INTO t8 VALUES (32,28); +INSERT INTO t8 VALUES (33,28); +INSERT INTO t8 VALUES (34,28); +INSERT INTO t8 VALUES (35,28); +INSERT INTO t8 VALUES (36,28); +INSERT INTO t8 VALUES (37,28); +INSERT INTO t8 VALUES (38,28); +INSERT INTO t8 VALUES (39,28); +INSERT INTO t8 VALUES (40,28); +INSERT INTO t8 VALUES (41,28); +INSERT INTO t8 VALUES (42,28); +COMMIT; + + +SET @commit_id=43; +INSERT INTO t8 VALUES (43,43); +INSERT INTO t8 VALUES (44,44); + +UPDATE t7 SET b=45 WHERE a=3; + +INSERT INTO t8 VALUES (46,46); +INSERT INTO t8 VALUES (47,47); + +UPDATE t7 SET b=48 WHERE a=3; + +INSERT INTO t8 VALUES (49,49); +INSERT INTO t8 VALUES (50,50); + + +SET @commit_id=44; +INSERT INTO t8 VALUES (51,51); +INSERT INTO t8 VALUES (52,52); + +UPDATE t7 SET b=53 WHERE a=3; + +INSERT INTO t8 VALUES (54,54); +INSERT INTO t8 VALUES (55,55); + +UPDATE t7 SET b=56 WHERE a=3; + +INSERT INTO t8 VALUES (57,57); + +UPDATE t7 SET b=58 WHERE a=3; + +INSERT INTO t8 VALUES (58,58); +INSERT INTO t8 VALUES (59,59); +INSERT INTO t8 VALUES (60,60); +INSERT INTO t8 VALUES (61,61); + +UPDATE t7 SET b=62 WHERE a=3; + +INSERT INTO t8 VALUES (63,63); +INSERT INTO t8 VALUES (64,64); +INSERT INTO t8 VALUES (65,65); +INSERT INTO t8 VALUES (66,66); + +UPDATE t7 SET b=67 WHERE a=3; + +INSERT INTO t8 VALUES (68,68); + +UPDATE t7 SET b=69 WHERE a=3; +UPDATE t7 SET b=70 WHERE a=3; +UPDATE t7 SET b=71 WHERE a=3; + +INSERT INTO t8 VALUES (72,72); + +UPDATE t7 SET b=73 WHERE a=3; +UPDATE t7 SET b=74 WHERE a=3; +UPDATE t7 SET b=75 WHERE a=3; +UPDATE t7 SET b=76 WHERE a=3; + +INSERT INTO t8 VALUES (77,77); + +UPDATE t7 SET b=78 WHERE a=3; + +INSERT INTO t8 VALUES (79,79); + +UPDATE t7 SET b=80 WHERE a=3; + +INSERT INTO t8 VALUES (81,81); + +UPDATE t7 SET b=82 WHERE a=3; + +INSERT INTO t8 VALUES (83,83); + +UPDATE t7 SET b=84 WHERE a=3; + + +SET @commit_id=45; +INSERT INTO t8 VALUES (85,85); +UPDATE t7 SET b=86 WHERE a=3; +INSERT INTO t8 VALUES (87,87); + + +SET @commit_id=46; +INSERT INTO t8 VALUES (88,88); +INSERT INTO t8 VALUES (89,89); +INSERT INTO t8 VALUES (90,90); + +SET SESSION debug_dbug=@old_dbug; + +INSERT INTO t8 VALUES (91,91); +INSERT INTO t8 VALUES (92,92); +INSERT INTO t8 VALUES (93,93); +INSERT INTO t8 VALUES (94,94); +INSERT INTO t8 VALUES (95,95); +INSERT INTO t8 VALUES (96,96); +INSERT INTO t8 VALUES (97,97); +INSERT INTO t8 VALUES (98,98); +INSERT INTO t8 VALUES (99,99); + + +SELECT * FROM t7 ORDER BY a; +SELECT * FROM t8 ORDER BY a; +--source include/save_master_gtid.inc + + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t7 ORDER BY a; +SELECT * FROM t8 ORDER BY a; + +--echo *** MDEV-8302: Duplicate key with parallel replication *** + +--connection server_2 +--source include/stop_slave.inc +/* Inject a small sleep which makes the race easier to hit. */ +SET @old_dbug=@@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,inject_mdev8302"; + + +--connection server_1 +INSERT INTO t7 VALUES (100,1), (101,2), (102,3), (103,4), (104,5); + +# Artificially create a bunch of group commits with conflicting transactions. +# The bug happened when T1 and T2 was in one group commit, and T3 was in the +# following group commit. T2 is a DELETE of a row with same primary key as a +# row that T3 inserts. T1 and T2 can conflict, causing T2 to be deadlock +# killed after starting to commit. The bug was that T2 could roll back before +# doing unmark_start_commit(); this could allow T3 to run before the retry +# of T2, causing duplicate key violation. + +SET @old_dbug= @@SESSION.debug_dbug; +SET @commit_id= 20000; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; + +--let $n = 100 +--disable_query_log +while ($n) +{ + eval UPDATE t7 SET b=b+1 WHERE a=100+($n MOD 5); + eval DELETE FROM t7 WHERE a=100+($n MOD 5); + + SET @commit_id = @commit_id + 1; + eval INSERT INTO t7 VALUES (100+($n MOD 5), $n); + SET @commit_id = @commit_id + 1; + dec $n; +} +--enable_query_log +SET SESSION debug_dbug=@old_dbug; + + +SELECT * FROM t7 ORDER BY a; +--source include/save_master_gtid.inc + + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t7 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL debug_dbug=@old_dbug; +SET GLOBAL slave_parallel_mode=@old_mode; +SET GLOBAL slave_parallel_threads=@old_threads; +SET GLOBAL slave_transaction_retries=@old_transaction_retries; + +# Clean up. +--source include/start_slave.inc +SET DEBUG_SYNC= 'RESET'; + +--connection server_1 +DROP TABLE t7,t8; +SET DEBUG_SYNC= 'RESET'; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test new file mode 100644 index 00000000..9ee06f59 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_deadlock_corrupt_binlog.test @@ -0,0 +1 @@ +--source include/rpl_parallel_deadlock_corrupt_binlog.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain.test b/mysql-test/suite/rpl/t/rpl_parallel_domain.test new file mode 100644 index 00000000..f5864380 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_domain.test @@ -0,0 +1 @@ +--source include/rpl_parallel_domain.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test new file mode 100644 index 00000000..5ddd2af3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_domain_slave_single_grp.test @@ -0,0 +1 @@ +--source include/rpl_parallel_domain_slave_single_grp.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test new file mode 100644 index 00000000..e2a41d0d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_free_deferred_event.test @@ -0,0 +1 @@ +--source include/rpl_parallel_free_deferred_event.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test new file mode 100644 index 00000000..d9dc4dfd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test @@ -0,0 +1 @@ +--source include/rpl_parallel_gco_wait_kill.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test new file mode 100644 index 00000000..0756caca --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_gtid_slave_pos_update_fail.test @@ -0,0 +1 @@ +--source include/rpl_parallel_gtid_slave_pos_update_fail.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test b/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test new file mode 100644 index 00000000..92c84d49 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_ignore_error_on_rotate.test @@ -0,0 +1 @@ +--source include/rpl_parallel_ignore_error_on_rotate.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test new file mode 100644 index 00000000..90f09a76 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_ignored_errors.test @@ -0,0 +1 @@ +--source include/rpl_parallel_ignored_errors.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test new file mode 100644 index 00000000..e0226d94 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_incorrect_relay_pos.test @@ -0,0 +1 @@ +--source include/rpl_parallel_incorrect_relay_pos.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test new file mode 100644 index 00000000..3838973c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_innodb_lock_conflict.test @@ -0,0 +1 @@ +--source include/rpl_parallel_innodb_lock_conflict.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test new file mode 100644 index 00000000..981c6216 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_mdev6589.test @@ -0,0 +1,133 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=current_pos; +--source include/start_slave.inc + + +--echo *** MDEV-6589: Incorrect relay log start position when restarting SQL thread after error in parallel replication *** + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (a int PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1; +SELECT * FROM t2; + +# Block one domain, which we will later cause to give an error. And let some +# other domains proceed so we can check that after restart, the slave is able +# to correctly restart each domain in a separate position. + +--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,) +SET sql_log_bin=0; +BEGIN; +INSERT INTO t2 VALUES (5); + +--connection server_1 +SET gtid_domain_id=0; +INSERT INTO t1 VALUES (2); +INSERT INTO t2 VALUES (3); +FLUSH LOGS; +INSERT INTO t1 VALUES (4); + +SET gtid_domain_id=1; +# This query will be blocked on the slave, and later give a duplicate key error. +INSERT INTO t2 VALUES (5); + +SET gtid_domain_id=0; +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); + +SET gtid_domain_id=2; +INSERT INTO t2 VALUES (8); +INSERT INTO t1 VALUES (9); +FLUSH LOGS; + +SET gtid_domain_id=3; +INSERT INTO t2 VALUES (10); +INSERT INTO t1 VALUES (11); + +# These cannot be replicated before the error, as a prior commit is blocked. +SET gtid_domain_id=1; +INSERT INTO t1 VALUES (12); +INSERT INTO t2 VALUES (13); + +SET gtid_domain_id=0; +INSERT INTO t2 VALUES (14); +FLUSH LOGS; + +SET gtid_domain_id=3; +INSERT INTO t2 VALUES (15); + +SET gtid_domain_id=2; +INSERT INTO t2 VALUES (16); + +SET gtid_domain_id=0; +INSERT INTO t1 VALUES (17); +SET @gtid0 = @@last_gtid; +SET gtid_domain_id=2; +INSERT INTO t1 VALUES (18); +SET @gtid2 = @@last_gtid; +SET gtid_domain_id=3; +INSERT INTO t1 VALUES (19); +SET @gtid3 = @@last_gtid; +--let $wait_pos= `SELECT CONCAT(@gtid0, ",", @gtid2, ",", @gtid3)` + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + + +--connection server_2 +# First wait for domains 0, 2, and 3 to complete. +--replace_result $wait_pos WAIT_POS +eval SELECT MASTER_GTID_WAIT('$wait_pos'); + +# Then release the row lock, and wait for the domain 1 to fail with +# duplicate key error. +--connection con_temp1 +COMMIT; +CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); +SET sql_log_bin=1; + +--connection server_2 +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +SET sql_log_bin=0; +DELETE FROM t2 WHERE a=5; +SET sql_log_bin=1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + + +# Clean up. +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc +SET DEBUG_SYNC= 'RESET'; + +--connection server_1 +DROP TABLE t1,t2; +SET DEBUG_SYNC= 'RESET'; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test new file mode 100644 index 00000000..de9dc7f7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_missed_error_handling.test @@ -0,0 +1 @@ +--source include/rpl_parallel_missed_error_handling.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_mode.test b/mysql-test/suite/rpl/t/rpl_parallel_mode.test new file mode 100644 index 00000000..afd9e038 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_mode.test @@ -0,0 +1 @@ +--source include/rpl_parallel_mode.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf new file mode 100644 index 00000000..3ff94e45 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.cnf @@ -0,0 +1,24 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[mysqld.4] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test new file mode 100644 index 00000000..168b7ea5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel.test @@ -0,0 +1,284 @@ +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--let $rpl_topology=1->2->3->4 +--source include/rpl_init.inc + +# Test parallel replication with a multi-level replication hierarchy. + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +--sync_with_master +--save_master_pos +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--connection server_3 +--sync_with_master +--save_master_pos +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--connection server_4 +--sync_with_master +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--echo *** MDEV-6676: Test that @@skip_parallel_replication is preserved in slave binlog *** +--connection server_1 + +INSERT INTO t1 VALUES(1,1); +BEGIN; +INSERT INTO t1 VALUES(2,1); +INSERT INTO t1 VALUES(3,1); +COMMIT; +# Do a lot of updates on same row in sequence. These would be likely to cause +# conflicts and rollbacks in optimistic parallel replication, but we disable +# that by enabling @@skip_parallel_replication. We can test that the flag is +# preserved down the replication hierarchy by checking that no slave retries +# are made. +SET SESSION skip_parallel_replication=1; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +UPDATE t1 SET b=b+1 WHERE a=2; +SET SESSION skip_parallel_replication=0; +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + +--connection server_3 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + +--connection server_4 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +--echo *** MDEV-6676: Test that the FL_WAITED flag in GTID is preserved in slave binlog *** + +--connection server_2 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--connection server_3 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +SET GLOBAL slave_parallel_mode='optimistic'; + + +--connection server_4 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; +SET GLOBAL slave_parallel_mode='optimistic'; + +--connection server_1 +# Do a lot of updates on same row in sequence. Ensure that all of these but the +# first have to do a lock wait on the master, setting FL_WAITED in the GTID +# event. This should cause all slaves to not attempt to run those updates in +# parallel with prior events, so that no retries are made. + +BEGIN; +UPDATE t1 SET b=b+1 WHERE a=2; + +--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting1"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting1"; + +--connect (con_temp2,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting2"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting2"; + +--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting3"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting3"; + +--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting4"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting4"; + +--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting5"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting5"; + +--connect (con_temp6,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting6"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting6"; + +--connect (con_temp7,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting7"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting7"; + +--connect (con_temp8,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync="thd_report_wait_for SIGNAL waiting8"; +send UPDATE t1 SET b=b+1 WHERE a=2; +--connection server_1 +SET debug_sync="now WAIT_FOR waiting8"; + +COMMIT; +SET debug_sync="RESET"; + +--connection con_temp1 +reap; + +COMMIT; +--connection con_temp2 +reap; + +COMMIT; +--connection con_temp3 +reap; + +COMMIT; +--connection con_temp4 +reap; + +COMMIT; +--connection con_temp5 +reap; + +COMMIT; +--connection con_temp6 +reap; + +COMMIT; +--connection con_temp7 +reap; + +COMMIT; +--connection con_temp8 +reap; + +--connection server_1 +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + +--connection server_3 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + +--connection server_4 +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +# Clean up + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_3 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_4 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf new file mode 100644 index 00000000..4e1d3878 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf @@ -0,0 +1,17 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test new file mode 100644 index 00000000..4125394e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test @@ -0,0 +1,80 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +--echo *** MDEV-7668: Intermediate master groups CREATE with INSERT, causing parallel replication failure *** + +--connection server_1 +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +--sync_with_master +--save_master_pos +--source include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=10; +SET @old_commit_count=@@GLOBAL.binlog_commit_wait_count; +SET GLOBAL binlog_commit_wait_count=2; +SET @old_commit_usec=@@GLOBAL.binlog_commit_wait_usec; +SET GLOBAL binlog_commit_wait_usec=2000000; +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_3 +--sync_with_master +--save_master_pos +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=current_pos; + + +--connection server_1 + +BEGIN; +CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=MEMORY; +COMMIT; +INSERT INTO t2 VALUES (1); +INSERT INTO t1 SELECT a, a*10 FROM t2; +DROP TABLE t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection server_3 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +# Clean up + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET GLOBAL binlog_commit_wait_count=@old_commit_count; +SET GLOBAL binlog_commit_wait_usec=@old_commit_usec; +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +--source include/start_slave.inc + +--connection server_3 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table"); +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt new file mode 100644 index 00000000..acd68493 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates-slave.opt @@ -0,0 +1 @@ +--log-slave-updates=0 diff --git a/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test new file mode 100644 index 00000000..75db619d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_no_log_slave_updates.test @@ -0,0 +1,201 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test killing transaction waiting in commit for previous transaction to commit, when not using 2-phase commit *** + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +# Use a stored function to inject a debug_sync into the appropriate THD. +# The function does nothing on the master, and on the slave it injects the +# desired debug_sync action(s). +SET sql_log_bin=0; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +SET sql_log_bin=0; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + IF d1 != '' THEN + SET debug_sync = d1; + END IF; + IF d2 != '' THEN + SET debug_sync = d2; + END IF; + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; +--sync_with_master + + +# Set up three transactions on the master that will be group-committed +# together so they can be replicated in parallel on the slave. +--connect (con_temp3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; +SET binlog_format=statement; +send INSERT INTO t3 VALUES (31, foo(31, + 'ha_commit_one_phase WAIT_FOR t2_waiting', + 'commit_one_phase_2 SIGNAL t1_ready WAIT_FOR t1_cont')); + +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued1'; + +--connect (con_temp4,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2'; +SET binlog_format=statement; +BEGIN; +# This insert is just so we can get T2 to wait while a query is running that we +# can see in SHOW PROCESSLIST so we can get its thread_id to kill later. +INSERT INTO t3 VALUES (32, foo(32, + 'ha_write_row_end SIGNAL t2_query WAIT_FOR t2_cont', + '')); +# This insert sets up debug_sync points so that T2 will tell when it is at its +# wait point where we want to kill it - and when it has been killed. +INSERT INTO t3 VALUES (33, foo(33, + 'wait_for_prior_commit_waiting SIGNAL t2_waiting', + 'wait_for_prior_commit_killed SIGNAL t2_killed')); +send COMMIT; + +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued2'; + +--connect (con_temp5,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3'; +SET binlog_format=statement; +send INSERT INTO t3 VALUES (34, foo(34, + '', + '')); + +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued3'; +SET debug_sync='now SIGNAL master_cont1'; + +--connection con_temp3 +REAP; +--connection con_temp4 +REAP; +--connection con_temp5 +REAP; + +--connection server_1 +SELECT * FROM t3 WHERE a >= 30 ORDER BY a; + +--connection server_2 +SET sql_log_bin=0; +CALL mtr.add_suppression("Query execution was interrupted"); +CALL mtr.add_suppression("Commit failed due to failure of an earlier commit on which this one depends"); +CALL mtr.add_suppression("Slave: Connection was killed"); +SET sql_log_bin=1; +# Wait until T2 is inside executing its insert of 32, then find it in SHOW +# PROCESSLIST to know its thread id for KILL later. +SET debug_sync='now WAIT_FOR t2_query'; +--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%foo(32%' AND INFO NOT LIKE '%LIKE%'` +SET debug_sync='now SIGNAL t2_cont'; + +# Wait until T2 has entered its wait for T1 to commit, and T1 has +# progressed into its commit phase. +SET debug_sync='now WAIT_FOR t1_ready'; + +# Now kill the transaction T2. +--replace_result $thd_id THD_ID +eval KILL $thd_id; + +# Wait until T2 has reacted on the kill. +SET debug_sync='now WAIT_FOR t2_killed'; + +# Now we can allow T1 to proceed. +SET debug_sync='now SIGNAL t1_cont'; + +--let $slave_sql_errno= 1317,1927,1963 +--source include/wait_for_slave_sql_error.inc +STOP SLAVE IO_THREAD; +SELECT * FROM t3 WHERE a >= 30 ORDER BY a; + +# Now we have to disable the debug_sync statements, so they do not trigger +# when the events are retried. +SET GLOBAL slave_parallel_threads=0; +SET GLOBAL slave_parallel_threads=10; +SET sql_log_bin=0; +DROP FUNCTION foo; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; + +--connection server_1 +INSERT INTO t3 VALUES (39,0); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t3 WHERE a >= 30 ORDER BY a; +# Restore the foo() function. +SET sql_log_bin=0; +DROP FUNCTION foo; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + IF d1 != '' THEN + SET debug_sync = d1; + END IF; + IF d2 != '' THEN + SET debug_sync = d2; + END IF; + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; + + +--connection server_2 +# Respawn all worker threads to clear any left-over debug_sync or other stuff. +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=0; +SET GLOBAL slave_parallel_threads=10; +--source include/start_slave.inc + + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET debug_sync = 'reset'; +--source include/start_slave.inc + +--connection server_1 +DROP function foo; +DROP TABLE t3; +SET debug_sync = 'reset'; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test new file mode 100644 index 00000000..f5e48282 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -0,0 +1,583 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); +call mtr.add_suppression("Can't find record in 't1'"); +call mtr.add_suppression("Can't find record in 't2'"); + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +--sync_with_master +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; +# Run the first part of the test with high batch size and see that +# old rows remain in the table. +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 1000000; + + +--connection server_1 + +INSERT INTO t1 VALUES(1,1); +BEGIN; +INSERT INTO t1 VALUES(2,1); +INSERT INTO t1 VALUES(3,1); +COMMIT; + +# Do a bunch of INSERT/DELETE on the same rows, bound to conflict. +# We will get a lot of rollbacks, probably, but they should be handled without +# any visible errors. + +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,2); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,3); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,4); +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,5); + +DELETE FROM t1 WHERE a=3; +INSERT INTO t1 VALUES(3,2); +DELETE FROM t1 WHERE a=1; +INSERT INTO t1 VALUES(1,2); +DELETE FROM t1 WHERE a=3; +INSERT INTO t1 VALUES(3,3); + +DELETE FROM t1 WHERE a=2; +INSERT INTO t1 VALUES (2,6); +--source include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +#SHOW STATUS LIKE 'Slave_retried_transactions'; + + +--echo *** Test a bunch of non-transactional/DDL event groups. *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 + +INSERT INTO t1 VALUES (4,4); +INSERT INTO t1 VALUES (5,5); +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1); +CREATE TABLE t3 (a INT PRIMARY KEY) ENGINE=MyISAM; +ALTER TABLE t2 ADD b INT; +INSERT INTO t2 VALUES (2,2); +ALTER TABLE t2 DROP b; +INSERT INTO t2 VALUES (3); +ALTER TABLE t2 ADD c INT; +INSERT INTO t2 VALUES (4,5); +INSERT INTO t2 VALUES (5,5); +INSERT INTO t3 VALUES (1); +UPDATE t2 SET c=NULL WHERE a=4; +ALTER TABLE t2 ADD UNIQUE (c); +INSERT INTO t2 VALUES (6,6); +UPDATE t2 SET c=c+100 WHERE a=2; +INSERT INTO t3(a) VALUES (2); +DELETE FROM t3 WHERE a=2; +INSERT INTO t3(a) VALUES (2); +DELETE FROM t3 WHERE a=2; +ALTER TABLE t3 CHANGE a c INT NOT NULL; +INSERT INTO t3(c) VALUES (2); +DELETE FROM t3 WHERE c=2; +INSERT INTO t3 SELECT a+200 FROM t2; +DELETE FROM t3 WHERE c >= 200; +INSERT INTO t3 SELECT a+200 FROM t2; +--source include/save_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY c; + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY c; +# Check that we have a bunch of old rows left-over - they were not deleted +# due to high @@gtid_cleanup_batch_size. Then set a low +# @@gtid_cleanup_batch_size so we can test that rows start being deleted. +SELECT IF(COUNT(*) >= 30, "OK", CONCAT("Error: too few old rows found: ", COUNT(*))) + FROM mysql.gtid_slave_pos; +SET GLOBAL gtid_cleanup_batch_size=1; + + +--echo *** Test @@skip_parallel_replication. *** + +--connection server_2 +--source include/stop_slave.inc +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) + +--connection server_1 +# We do a bunch of conflicting transactions on the master with +# skip_parallel_replication set to true, and check that we do not +# get any retries on the slave. + +UPDATE t1 SET b=10 WHERE a=3; +SET SESSION skip_parallel_replication=1; +UPDATE t1 SET b=20 WHERE a=3; +UPDATE t1 SET b=30 WHERE a=3; +UPDATE t1 SET b=50 WHERE a=3; +UPDATE t1 SET b=80 WHERE a=3; +UPDATE t1 SET b=130 WHERE a=3; +UPDATE t1 SET b=210 WHERE a=3; +UPDATE t1 SET b=340 WHERE a=3; +UPDATE t1 SET b=550 WHERE a=3; +UPDATE t1 SET b=890 WHERE a=3; +SET SESSION skip_parallel_replication=0; +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +--echo *** Test that we do not replicate in parallel transactions that had row lock waits on the master *** + +--connection server_2 +--source include/stop_slave.inc +--let $retry1= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) + +--connection server_1 +# Setup a bunch of transactions that all needed to wait. +--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m2,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m4,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m5,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m6,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m7,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +--connect (m8,127.0.0.1,root,,test,$SERVER_MYPORT_1,) + +--connection default +BEGIN; UPDATE t1 SET b=b+1 WHERE a=3; + +--connection m1 +SET debug_sync='thd_report_wait_for SIGNAL waiting1'; +send UPDATE t1 SET b=1001 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting1'; + +--connection m2 +BEGIN; +UPDATE t1 SET b=1002 WHERE a=5; +SET debug_sync='thd_report_wait_for SIGNAL waiting2'; +send UPDATE t1 SET b=102 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting2'; + +UPDATE t1 SET b=1000 WHERE a=1; +--connection m3 +SET debug_sync='thd_report_wait_for SIGNAL waiting3'; +send UPDATE t1 SET b=1003 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting3'; + +--connection m4 +SET debug_sync='thd_report_wait_for SIGNAL waiting4'; +send UPDATE t1 SET b=1004 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting4'; + +--connection m5 +SET debug_sync='thd_report_wait_for SIGNAL waiting5'; +send UPDATE t1 SET b=1005 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting5'; + +--connection m6 +SET debug_sync='thd_report_wait_for SIGNAL waiting6'; +send UPDATE t1 SET b=1006 WHERE a=1; +--connection default +SET debug_sync='now WAIT_FOR waiting6'; + +--connection m7 +SET debug_sync='thd_report_wait_for SIGNAL waiting7'; +send UPDATE t1 SET b=1007 WHERE a=5; +--connection default +SET debug_sync='now WAIT_FOR waiting7'; + +--connection m8 +SET debug_sync='thd_report_wait_for SIGNAL waiting8'; +send UPDATE t1 SET b=1008 WHERE a=3; +--connection default +SET debug_sync='now WAIT_FOR waiting8'; + +--connection default +COMMIT; +--connection m1 +REAP; +--connection m2 +REAP; +COMMIT; +--connection m3 +REAP; +--connection m4 +REAP; +--connection m5 +REAP; +--connection m6 +REAP; +--connection m7 +REAP; +--connection m8 +REAP; +--connection default +SET debug_sync='RESET'; +SELECT * FROM t1 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +--let $retry2= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1) +--disable_query_log +eval SELECT IF($retry1=$retry2, "Ok, no retry", + CONCAT("ERROR: ", $retry2-$retry1, " retries during replication (was ", + $retry1, " now ", $retry2, ")")) AS status; +--enable_query_log + + +--echo *** Test that we replicate correctly when using READ COMMITTED and binlog_format=MIXED on the slave *** + +--connection server_2 +--source include/stop_slave.inc +SET @old_format= @@GLOBAL.binlog_format; +# Use MIXED format; we cannot binlog ROW events on slave in STATEMENT format. +SET GLOBAL binlog_format= MIXED; +SET @old_isolation= @@GLOBAL.tx_isolation; +SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; +# Reset the worker threads to make the new settings take effect. +SET GLOBAL slave_parallel_threads=0; +SET GLOBAL slave_parallel_threads=10; + +--connection server_1 +DROP TABLE t1, t2; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0), (2,0), (3,0); +INSERT INTO t2 VALUES (1,0), (2,0); +INSERT INTO t1 SELECT 4, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 4, COUNT(*) FROM t1; + +INSERT INTO t1 SELECT 5, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 5, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 6, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 6, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 7, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 7, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 8, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 8, COUNT(*) FROM t2; + +INSERT INTO t2 SELECT 9, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 9, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 10, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 10, COUNT(*) FROM t1; + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL binlog_format= @old_format; +SET GLOBAL tx_isolation= @old_isolation; +--source include/start_slave.inc + + +--echo *** MDEV-7888: ANALYZE TABLE does wakeup_subsequent_commits(), causing wrong binlog order and parallel replication hang *** + +--connection server_1 +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,1), (2,1), (3,1), (4,1), (5,1); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +SET @old_debug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug= '+d,inject_analyze_table_sleep'; + +--connection server_1 +# The bug was that ANALYZE TABLE would call +# wakeup_subsequent_commits() too early, allowing the following +# transaction in the same group to run ahead and binlog and free the +# GCO. Then we get wrong binlog order and later access freed GCO, +# which causes lost wakeup of following GCO and thus replication hang. +# We injected a small sleep in ANALYZE to make the race easier to hit (this +# can only cause false negatives in versions with the bug, not false positives, +# so sleep is ok here. And it's in general not possible to trigger reliably +# the race with debug_sync, since the bugfix makes the race impossible). + +ALTER TABLE t2 COMMENT "123abc"; +ANALYZE TABLE t2; +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,2); +INSERT INTO t1 VALUES (3,2); +INSERT INTO t1 VALUES (4,2); +INSERT INTO t3 VALUES (1,3); +ALTER TABLE t2 COMMENT "hello, world"; +BEGIN; +INSERT INTO t1 VALUES (5,4); +INSERT INTO t1 VALUES (6,4); +INSERT INTO t1 VALUES (7,4); +INSERT INTO t1 VALUES (8,4); +INSERT INTO t1 VALUES (9,4); +INSERT INTO t1 VALUES (10,4); +INSERT INTO t1 VALUES (11,4); +INSERT INTO t1 VALUES (12,4); +INSERT INTO t1 VALUES (13,4); +INSERT INTO t1 VALUES (14,4); +INSERT INTO t1 VALUES (15,4); +INSERT INTO t1 VALUES (16,4); +INSERT INTO t1 VALUES (17,4); +INSERT INTO t1 VALUES (18,4); +INSERT INTO t1 VALUES (19,4); +INSERT INTO t1 VALUES (20,4); +COMMIT; +INSERT INTO t1 VALUES (21,5); +INSERT INTO t1 VALUES (22,5); + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL debug_dbug= @old_debug; +--source include/start_slave.inc + +--echo *** MDEV-7929: record_gtid() for non-transactional event group calls wakeup_subsequent_commits() too early, causing slave hang. *** + +--connection server_2 +--source include/stop_slave.inc +SET @old_dbug= @@GLOBAL.debug_dbug; +# The bug was that record_gtid(), when there is no existing transaction from +# a DML event being replicated, would commit its own transaction. This wrongly +# caused wakeup_subsequent_commits(), with similar consequences as MDEV-7888 +# above. We simulate this condition with a small sleep in record_gtid() for +# a specific ANALYZE that we binlog with server id 100. +SET GLOBAL debug_dbug= '+d,inject_record_gtid_serverid_100_sleep'; + +--connection server_1 + +ALTER TABLE t3 COMMENT "DDL statement 1"; +INSERT INTO t1 VALUES (30,0); +INSERT INTO t1 VALUES (31,0); +INSERT INTO t1 VALUES (32,0); +INSERT INTO t1 VALUES (33,0); +INSERT INTO t1 VALUES (34,0); +INSERT INTO t1 VALUES (35,0); +INSERT INTO t1 VALUES (36,0); +SET @old_server_id= @@SESSION.server_id; +SET SESSION server_id= 100; +ANALYZE TABLE t2; +SET SESSION server_id= @old_server_id; +INSERT INTO t1 VALUES (37,0); +ALTER TABLE t3 COMMENT "DDL statement 2"; +INSERT INTO t1 VALUES (38,0); +INSERT INTO t1 VALUES (39,0); +ALTER TABLE t3 COMMENT "DDL statement 3"; + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/save_master_gtid.inc + + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + + +--source include/stop_slave.inc +SET GLOBAL debug_dbug= @old_debug; +--source include/start_slave.inc + + +--echo *** MDEV-8113: ALTER TABLE causes slave hang in optimistic parallel replication *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +ALTER TABLE t2 ADD c INT; +INSERT INTO t2 (a,b) VALUES (50, 0); +INSERT INTO t2 (a,b) VALUES (51, 1); +INSERT INTO t2 (a,b) VALUES (52, 2); +INSERT INTO t2 (a,b) VALUES (53, 3); +INSERT INTO t2 (a,b) VALUES (54, 4); +INSERT INTO t2 (a,b) VALUES (55, 5); +INSERT INTO t2 (a,b) VALUES (56, 6); +INSERT INTO t2 (a,b) VALUES (57, 7); +INSERT INTO t2 (a,b) VALUES (58, 8); +INSERT INTO t2 (a,b) VALUES (59, 9); +ALTER TABLE t2 DROP COLUMN c; +SELECT * FROM t2 WHERE a >= 50 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t2 WHERE a >= 50 ORDER BY a; + + +--echo *** MDEV-8075: DROP TEMPORARY TABLE not marked as ddl, causing optimistic parallel replication to fail *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (40, 10); +CREATE TEMPORARY TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (41); +BEGIN; +INSERT INTO t2 SELECT a, 20 FROM t1; +DROP TEMPORARY TABLE t1; +COMMIT; +INSERT INTO t1 VALUES (42, 10); +--source include/save_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 40 ORDER BY a; +SELECT * FROM t2 WHERE a >= 40 ORDER BY a; + +# partial cleanup to reuse the tables by following tests +--connection server_1 +DELETE FROM t1; +DELETE FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +# +# MDEV-13577 optimistic parallel slave errors out to error log unnecessary +# + +# The 1st of the following two trx:s a blocker on slave +--connection server_2 +set global log_warnings=2; +BEGIN; +INSERT INTO t1 SET a=1; + +--connection server_1 +SET @save.binlog_format=@@session.binlog_format; +SET @@SESSION.binlog_format=row; + +BEGIN; + INSERT INTO t1 SET a=1; + INSERT INTO t2 SET a=1; +COMMIT; + +# This transaction is going to win optimistical race with above INSERT +# on slave while being depend on it. That means it will face a kind of temporary error +# and then will retry to succeed. +BEGIN; + DELETE FROM t2; +COMMIT; + +# First make sure DELETE raced indeed to get stuck at retrying stage +# where it runs "realistically" now. There is nomore optimistic error +# in the errorlog, which is downgraded to the warning level (when +# --log-warnings > 1), see above suppression. +--connection server_2 +--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +# Next release the 1st trx to commit. +--connection server_2 +ROLLBACK; + +# MDEV-13577 local cleanup: +--connection server_1 +SET @@SESSION.binlog_format= @save.binlog_format; +DELETE FROM t1; +DELETE FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +# +# Clean up. +# +--connection server_2 +--source include/stop_slave.inc +set global log_warnings=default; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1, t2, t3; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +# Check that old rows are deleted from mysql.gtid_slave_pos. +# Deletion is asynchronous, so use wait_condition.inc. +# Also, there is a small amount of non-determinism in the deletion of old +# rows, so it is not guaranteed that there can never be more than +# @@gtid_cleanup_batch_size rows in the table; so allow a bit of slack +# here. +let $wait_condition= + SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size + FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc +eval $wait_condition; +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; + +--connection server_1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf new file mode 100644 index 00000000..b85a84f6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.cnf @@ -0,0 +1,10 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates=0 +loose-innodb + +[mysqld.2] +slave-transaction-retries=100 +log-slave-updates=0 +loose-innodb diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test new file mode 100644 index 00000000..ee0de499 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_nobinlog.test @@ -0,0 +1,77 @@ +--source include/have_innodb.inc +--source include/have_binlog_format_statement.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0), (2,0), (3,0); +INSERT INTO t2 VALUES (1,0), (2,0); +--save_master_pos + + +--connection server_2 +--sync_with_master +SET @old_isolation= @@GLOBAL.tx_isolation; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED; +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=slave_pos; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='aggressive'; + + +--echo *** Test that we replicate correctly when using READ COMMITTED and --log-slave-updates=0 on the slave *** + +--connection server_1 + +INSERT INTO t1 SELECT 4, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 4, COUNT(*) FROM t1; + +INSERT INTO t1 SELECT 5, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 5, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 6, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 6, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 7, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 7, COUNT(*) FROM t1; + +INSERT INTO t2 SELECT 8, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 8, COUNT(*) FROM t2; + +INSERT INTO t2 SELECT 9, COUNT(*) FROM t1; +INSERT INTO t1 SELECT 9, COUNT(*) FROM t2; + +INSERT INTO t1 SELECT 10, COUNT(*) FROM t2; +INSERT INTO t2 SELECT 10, COUNT(*) FROM t1; + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL tx_isolation= @old_isolation; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1, t2; + +--connection server_2 +call mtr.add_suppression("Deadlock found when trying to get lock.*"); + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test new file mode 100644 index 00000000..508213c9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_until.test @@ -0,0 +1,465 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc +# Format is restricted because the test expects a specific result of +# relay-logging that splits a transaction into two different files. +--source include/have_binlog_format_row.inc + +# +# MDEV-15152 Optimistic parallel slave doesn't cope well with START SLAVE UNTIL +# +--connection slave +--source include/stop_slave.inc +RESET MASTER; +RESET SLAVE; + +--connection master +RESET MASTER; +CREATE TABLE t1 (a int primary key, b text) ENGINE=InnoDB; +--let $a0 = 25 +--eval INSERT INTO t1 SET a=$a0, b='trx0' +# Memorize the position for replication restart from it +--let $pos_trx0 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +--source include/start_slave.inc + +--connection master +# --connection slave +--sync_slave_with_master +--source include/stop_slave.inc +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=2; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode='optimistic'; + +# Run the slave in the following modes one by one. +# +# 1. the until position is set in the middle of trx2 +# below $pos_trx0 of the last exec position in the first file +# 2. and above $pos_trx0 +# In either case trx2 must commit before slave stops. +# 3. the until postion is inside trx1 +# 4. RELAY log until inside trx1 +# 5. RELAY log until inside a "big" trx +# 6. RELAY log until inside a trx within a sequence of relay logs +# +# Execution flaw for Until_Master_Pos cases follows as: +# create the transaction trx1, trx2 +# logged at the beginning of two subsequent binlog files. +# Set the until position to at the middle of the 2rd transaction. +# Engage the optimistic scheduler while having trx1 execution blocked. +# Lift the block after trx2 has reached waiting its order to commit. +# *Proof 1* +# Observe that the slave applier stops at a correct position. +# In the bug condition it would stop prematurely having the stop position +# in the first file, therefore trx2 not committed. +# Specifically, an internal transaction position until makes the applier to run +# beyond it to commit commit the current transaction. +# *Proof 2* +# Observe the following START SLAVE resumes OK. +# +# Auxiliary third trx3 on master is just for triggering the actual stop +# (whihc is a legacy UNTIL's property). +# trx0 is to produce a specific value of the last executed binlog file:pos +# to emulate the bug condition. +# +# Intermediate checks via SELECT are supposed to succeed +# with putting out value 1. +# +# NOTE: Relay log until tests have to use explicit log names and position +# which may require to adjust with future changes to event formats etc. +# + +--connection slave +SET @old_max_relay_log_size = @@global.max_relay_log_size; +SET @@global.max_relay_log_size=4096; + +--connection master +# trx1 +--let $a=1 +BEGIN; +while (`SELECT $a < $a0`) +{ + --eval INSERT INTO t1 SET a=$a, b='trx1' +--inc $a +} +COMMIT; +--let $fil_1 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx1 = query_get_value(SHOW MASTER STATUS, Position, 1) + +FLUSH LOGS; + +# $pos_0 the offset of the first event of trx2 in new file +--let $pos_0=query_get_value(SHOW MASTER STATUS, Position, 1) +# trx2 +--let $a=$a0 +BEGIN; +--eval UPDATE t1 SET b='trx2_0' WHERE a = $a +--eval UPDATE t1 SET b='trx2' WHERE a = $a +COMMIT; +--let $fil_2=query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx2=query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx3 +--let $a=$a0 +--inc $a +--eval INSERT INTO t1 SET a=$a,b='trx3' +--let $pos_trx3=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $a= + + +--echo *** case 1 UNTIL inside trx2 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 +--connection slave +--let $pos_until=`SELECT $pos_trx0 - 1` +--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until < trx0 and is within trx2" +CHANGE MASTER TO MASTER_USE_GTID=no; +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 2 UNTIL inside trx2 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_trx2 - 1` +--replace_result $pos_trx0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_trx0 <= $pos_until AND $pos_until < $pos_trx2 as "pos_until >= trx0 and is within trx2" +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--let $wait_condition= SELECT COUNT(*) > 0 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit" +--source include/wait_condition.inc + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = 1 as 'trx2 is committed' FROM t1 WHERE b = 'trx2' +--eval SELECT count(*) = 0 as 'trx3 is not committed' FROM t1 WHERE b = 'trx3' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 3 UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc + +--let $pos_until=`SELECT $pos_0 - 1` +--replace_result $pos_0 <pos_0> $pos_until <pos_until> $pos_trx2 <pos_trx2> +--eval SELECT $pos_until < $pos_0 as "pos_until before trx2 start position" +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +--replace_result $fil_2 file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL MASTER_LOG_FILE = '$fil_2', MASTER_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +if (`SELECT "$file_stop" != "$fil_2" OR $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $fil_2:$pos_until. + --die +} +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + +--echo *** case 4 Relay-log UNTIL inside trx1 + +--connection slave +--eval DELETE FROM t1 WHERE a <> $a0 +--eval UPDATE t1 SET b='trx0' WHERE a = $a0 + +--connection slave1 +# Blocker to hold off EXEC_MASTER_LOG_POS advance +BEGIN; + --eval INSERT INTO t1 SET a= 1; # block trx1 + +--connection slave +--source include/stop_slave.inc +--replace_result $fil_1 file_1 $pos_trx0 <pos_trx0> +--eval CHANGE MASTER TO MASTER_LOG_FILE = '$fil_1', MASTER_LOG_POS = $pos_trx0, MASTER_USE_GTID=no +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# The following test sets the stop coordinate is set to inside the first event +# of a relay log that holds events of a transaction started in an earlier log. +# Peek the stop position in the middle of trx1, not even on a event boundary. +--let $pos_until=255 +--let $file_rl=slave-relay-bin.000003 +--let $binlog_file=$file_rl + +--let $pos_xid=508 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_xid LIMIT 1, Info, 1) + +if (`SELECT "$info" NOT LIKE "COMMIT /* xid=% */" OR $pos_xid < $pos_until`) +{ + --echo *** Unexpected offset. Refine it to point to the correct XID event! + --die +} + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--connection slave1 +# unblock to see the slave applier stops at $until +ROLLBACK; + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_rl","$file_stop") > -1`) +{ + --echo *** ERROR: Slave stopped at $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--eval SELECT count(*) = $a0-1 as 'trx1 is committed' FROM t1 WHERE b = 'trx1' +--eval SELECT count(*) = 0 as 'trx2 is not committed' FROM t1 WHERE b = 'trx2' + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + + + +--echo *** case 5 Relay-log UNTIL inside a "big" trx that spawns few relay logs + +--connection master +CREATE TABLE t2 (a TEXT) ENGINE=InnoDB; +FLUSH LOGS; + +--sync_slave_with_master +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--let $records=`SELECT floor(4*@@global.max_relay_log_size / 1024) + 1` + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx4 +BEGIN; +--let $i=$records +while ($i) +{ + INSERT INTO t2 SET a=repeat('a',1024); + +--dec $i +} +COMMIT; + +# slave will stop there: +--let $file_trx4 = query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos_trx4 = query_get_value(SHOW MASTER STATUS, Position, 1) + +# trx5 +INSERT INTO t2 SET a='a'; +--let $pos_trx5 = query_get_value(SHOW MASTER STATUS, Position, 1) + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# Set position inside the transaction though the value +# specified is beyond that relay log file. +# The coordianate may point to in a different event in future changes +# but should not move away from inside this big group of events. +# So we don't test which event in the transaction it points to. +--let $pos_until= 4500 +--let $file_rl= slave-relay-bin.000010 + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +# It's showed the actual stop occurred before trx5 +if (`SELECT strcmp("$file_trx4", "$file_stop") <> 0 OR $pos_stop >= $pos_trx5 OR count(*) <> $records FROM t2`) +{ + --echo *** ERROR: Slave stopped at *binlog* $file_stop:$pos_stop which is not $file_trx4:$pos_trx4. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + + + +--echo *** case 6 Relay-log UNTIL inside a small trx inside a sequence of relay logs + +--connection slave +--source include/stop_slave.inc + +--connection master +# trx6 +--let $records=`SELECT count(*) FROM t2` +while ($records) +{ + BEGIN; + DELETE FROM t2 LIMIT 1; + COMMIT; +--dec $records +} +COMMIT; + +--connection slave +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--connection master +--source include/sync_slave_io_with_master.inc + +--connection slave +# The relay-log coordinate is not at an event boundary and +# also may change across the server version. +# The test makes its best to check its coherance. +--let $pos_until= 3130 +--let $file_rl= slave-relay-bin.000018 + +--let $pos_gtid = 2987 +--let $info= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_gtid LIMIT 1, Info, 1) + +if (`SELECT "$info" != "BEGIN GTID 0-1-23"`) +{ + --echo *** Unexpected offset. Refine it to point to the correct GTID! + --die +} +--let $pos_event = 3120 +--let $type= query_get_value(SHOW RELAYLOG EVENTS IN '$file_rl' FROM $pos_event LIMIT 1, Event_type, 1) +if (`SELECT "$type" != "Delete_rows_v1"`) +{ + --echo *** Unexpected offset. Refine it to point to the expected event! + --die +} + +--replace_result $file_rl file_2 $pos_until <pos_until> +--eval START SLAVE UNTIL RELAY_LOG_FILE = '$file_rl', RELAY_LOG_POS = $pos_until + +--echo Proof 1: Correct stop +--connection slave +--source include/wait_for_slave_sql_to_stop.inc +--let $file_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $pos_stop= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +if (`SELECT strcmp("$file_stop", "$file_rl") = -1 OR + strcmp("$file_stop", "$file_rl") = 0 AND $pos_stop < $pos_until`) +{ + --echo *** ERROR: Slave stopped at *relay* $file_stop:$pos_stop which is not $file_rl:$pos_until. + --die +} + +--echo Proof 2: Resume works out +--source include/start_slave.inc +--connection master +--sync_slave_with_master + +--let $diff_tables=master:t2,slave:t2 +--source include/diff_tables.inc + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +SET GLOBAL max_relay_log_size=@old_max_relay_log_size; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1, t2; + +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test new file mode 100644 index 00000000..35c22d1e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test @@ -0,0 +1,235 @@ +# The tests verify concurrent execution of replicated (MDEV-742) +# XA transactions in the parallel optimistic mode. + +--source include/have_innodb.inc +--source include/have_perfschema.inc +--source include/master-slave.inc + +# Tests' global declarations +--let $trx = _trx_ + +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); +call mtr.add_suppression("WSREP: handlerton rollback failed"); +#call mtr.add_suppression("Can't find record in 't1'"); +CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND'; + +--connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +--save_master_pos + +# Prepare to restart slave into optimistic parallel mode +--connection slave +--sync_with_master +--source include/stop_slave.inc +SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads; +SET @@global.slave_parallel_threads = 7; +SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode; +SET @@global.slave_parallel_mode ='optimistic'; +# Run the first part of the test with high batch size and see that +# old rows remain in the table. +SET @old_gtid_cleanup_batch_size = @@GLOBAL.gtid_cleanup_batch_size; +SET @@global.gtid_cleanup_batch_size = 1000000; + +CHANGE MASTER TO master_use_gtid=slave_pos; + +# LOAD GENERATOR creates XA:s interleaved in binlog when they are from +# different connections. All the following block XA:s of the same connection +# update the same data which challenges slave optimistic scheduler's correctness. +# Slave must eventually apply such load, and correctly (checked). + +--connection master +CREATE TABLE t0 (a int, b INT) ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); + + +# I. Logging some sequence of XA:s by one connection. +# +# The slave applier's task is to successfully execute a series of +# Prepare and Complete parts of a sequence of XA:s + +--let $trx_num = 300 +--let $i = $trx_num +--let $conn = master +--disable_query_log +while($i > 0) +{ + # 'decision' to commit 0, or rollback 1 + --let $decision = `SELECT $i % 2` + --eval XA START '$conn$trx$i' + --eval UPDATE t1 SET b = 1 - 2 * $decision WHERE a = 1 + --eval XA END '$conn$trx$i' + --let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)` + if (!$one_phase) + { + --eval XA PREPARE '$conn$trx$i' + --let $one_phase = + } + + --let $term = COMMIT + if ($decision) + { + --let $term = ROLLBACK + --let $one_phase = + } + --eval XA $term '$conn$trx$i' $one_phase + + --dec $i +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc + + +# II. Logging XS:s from multiple connections in random interweaving manner: +# +# in a loop ($i) per connection +# arrange an inner ($k) loop where +# start and prepare an XA; +# decide whether to terminate it and then continue to loop innerly +# OR disconnect to break the inner loop; +# the disconnected one's XA is taken care by 'master' connection +# +# Effectively binlog must collect a well mixed XA- prepared and terminated +# groups for slave to handle. + +--connection master +# Total # of connections +--let $conn_num=53 + +--let $i = $conn_num +--disable_query_log +while($i > 0) +{ + --connect (master_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,) +--dec $i +} +--enable_query_log + +--let $i = $conn_num +while($i > 0) +{ + --let $conn_i = conn$i + # $i2 indexes the current connection's "own" row + --let $i2 = `SELECT $i + 2` +--disable_query_log + --connection master_conn$i +--enable_query_log + --disable_query_log + --let $i_conn_id = `SELECT connection_id()` + + --let $decision = 0 + # the row id of the last connection that committed its XA + --let $c_max = 1 + --let $k = 0 + while ($decision < 3) + { + --inc $k + --eval XA START '$conn_i$trx$k' + # UPDATE depends on previously *committed* transactions + --eval UPDATE t1 SET b = b + $k + 1 WHERE a = $c_max + if (`SELECT $k % 2 = 1`) + { + --eval REPLACE INTO t1 VALUES ($i2, $k) + } + if (`SELECT $k % 2 = 0`) + { + --eval DELETE FROM t1 WHERE a = $i2 + } + CREATE TEMPORARY TABLE tmp LIKE t0; + --eval INSERT INTO tmp SET a=$i, b= $k + INSERT INTO t0 SELECT * FROM tmp; + DROP TEMPORARY TABLE tmp; + --eval XA END '$conn_i$trx$k' + + --let $term = COMMIT + --let $decision = `SELECT (floor(rand()*10 % 10) + ($i+$k)) % 4` + if ($decision == 1) + { + --let $term = ROLLBACK + } + if ($decision < 2) + { + --eval XA PREPARE '$conn_i$trx$k' + --eval XA $term '$conn_i$trx$k' + # Iteration counter is taken care *now* + } + if ($decision == 2) + { + --eval XA COMMIT '$conn_i$trx$k' ONE PHASE + } + } + + # $decision = 3 + --eval XA PREPARE '$conn_i$trx$k' + # disconnect now + --disconnect master_conn$i + --connection master + + --let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $i_conn_id + --source include/wait_condition.inc + + --disable_query_log + --let $decision = `SELECT ($i+$k) % 2` + --let $term = COMMIT + if ($decision == 1) + { + --let $term = ROLLBACK + } + --eval XA $term '$conn_i$trx$k' + --let $c_max = $i2 + +--dec $i +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +# +# Overall consistency check +# +--let $diff_tables= master:t0, slave:t0 +--source include/diff_tables.inc +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +set global log_warnings=default; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP VIEW v_processlist; +DROP TABLE t0, t1; +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc +# Check that old rows are deleted from mysql.gtid_slave_pos. +# Deletion is asynchronous, so use wait_condition.inc. +# Also, there is a small amount of non-determinism in the deletion of old +# rows, so it is not guaranteed that there can never be more than +# @@gtid_cleanup_batch_size rows in the table; so allow a bit of slack +# here. +let $wait_condition= + SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size + FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc +eval $wait_condition; +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; + +--connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt new file mode 100644 index 00000000..88cf77fd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off-slave.opt @@ -0,0 +1 @@ +--log-slave-updates=OFF diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test new file mode 100644 index 00000000..f82b522e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa_lsu_off.test @@ -0,0 +1,2 @@ +# --log-slave-updates OFF version of rpl_parallel_optimistic_xa +--source rpl_parallel_optimistic_xa.test diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test new file mode 100644 index 00000000..7be26eda --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_partial_binlog_trans.test @@ -0,0 +1 @@ +--source include/rpl_parallel_partial_binlog_trans.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_partition.test b/mysql-test/suite/rpl/t/rpl_parallel_partition.test new file mode 100644 index 00000000..ea6c5dca --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_partition.test @@ -0,0 +1,81 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,inject_wakeup_subsequent_commits_sleep"; +SET GLOBAL slave_parallel_threads=8; + +--echo *** MDEV-8147: Assertion `m_lock_type == 2' failed in handler::ha_close() during parallel replication *** +--connection server_1 +CREATE TABLE E ( + pk INTEGER AUTO_INCREMENT, + col_int_nokey INTEGER /*! NULL */, + col_int_key INTEGER /*! NULL */, + + col_date_key DATE /*! NULL */, + col_date_nokey DATE /*! NULL */, + + col_time_key TIME /*! NULL */, + col_time_nokey TIME /*! NULL */, + + col_datetime_key DATETIME /*! NULL */, + col_datetime_nokey DATETIME /*! NULL */, + + col_varchar_key VARCHAR(1) /*! NULL */, + col_varchar_nokey VARCHAR(1) /*! NULL */, + + PRIMARY KEY (pk), + KEY (col_int_key), + KEY (col_date_key), + KEY (col_time_key), + KEY (col_datetime_key), + KEY (col_varchar_key, col_int_key) + ) ENGINE=InnoDB; + +ALTER TABLE `E` PARTITION BY KEY() PARTITIONS 5; +ALTER TABLE `E` REMOVE PARTITIONING; +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF +--shutdown_server +--source include/wait_until_disconnected.inc +--connection default +--source include/wait_until_disconnected.inc +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart: +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc +CREATE TABLE t1 (a INT PRIMARY KEY); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master + +# Re-spawn worker threads to clear dbug injection. +--source include/stop_slave.inc +SET GLOBAL debug_dbug=@old_dbug; +SET GLOBAL slave_parallel_threads=0; +SET GLOBAL slave_parallel_threads=8; +--source include/start_slave.inc + + +# Clean up. +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE `E`; +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test new file mode 100644 index 00000000..4529a268 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_record_gtid_wakeup.test @@ -0,0 +1 @@ +--source include/rpl_parallel_record_gtid_wakeup.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry.test b/mysql-test/suite/rpl/t/rpl_parallel_retry.test new file mode 100644 index 00000000..97a3a709 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_retry.test @@ -0,0 +1,486 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** Test retry of transactions that fail to replicate due to deadlock or similar temporary error. *** + +--connection server_1 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1); +--save_master_pos + +# Use a stored function to inject a debug_sync into the appropriate THD. +# The function does nothing on the master, and on the slave it injects the +# desired debug_sync action(s). +SET sql_log_bin=0; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=5; +--source include/start_slave.inc +--sync_with_master +SET sql_log_bin=0; +--delimiter || +CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) + RETURNS INT DETERMINISTIC + BEGIN + IF d1 != '' THEN + SET debug_sync = d1; + END IF; + IF d2 != '' THEN + SET debug_sync = d2; + END IF; + RETURN x; + END +|| +--delimiter ; +SET sql_log_bin=1; +--source include/stop_slave.inc + +--connection server_1 +SET gtid_seq_no = 100; +BEGIN; +INSERT INTO t1 VALUES (2,1); +UPDATE t1 SET b=b+1 WHERE a=1; +INSERT INTO t1 VALUES (3,1); +COMMIT; +SELECT * FROM t1 ORDER BY a; +--save_master_pos + +--connection server_2 +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100"; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--source include/start_slave.inc +--sync_with_master +SET GLOBAL debug_dbug=@old_dbug; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log + +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test that double retry works when the first retry also fails with temp error *** +--source include/stop_slave.inc + +--connection server_1 +SET gtid_seq_no = 100; +SET @old_server_id = @@server_id; +SET server_id = 10; +BEGIN; +INSERT INTO t1 VALUES (4,1); +UPDATE t1 SET b=b+1 WHERE a=1; +INSERT INTO t1 VALUES (5,1); +INSERT INTO t1 VALUES (6,1); +COMMIT; +SET server_id = @old_server_id; +SELECT * FROM t1 ORDER BY a; +--save_master_pos + +--connection server_2 +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100,rpl_parallel_simulate_double_temp_err_gtid_0_x_100"; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--source include/start_slave.inc +--sync_with_master +SET GLOBAL debug_dbug=@old_dbug; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log + +SELECT * FROM t1 ORDER BY a; + + +--echo *** Test too many retries, eventually causing failure. *** +--source include/stop_slave.inc + +--connection server_1 +SET gtid_seq_no = 100; +SET @old_server_id = @@server_id; +SET server_id = 11; +BEGIN; +INSERT INTO t1 VALUES (7,1); +UPDATE t1 SET b=b+1 WHERE a=1; +INSERT INTO t1 VALUES (8,1); +INSERT INTO t1 VALUES (9,1); +COMMIT; +SET server_id = @old_server_id; +SELECT * FROM t1 ORDER BY a; +--save_master_pos + +--connection server_2 +SET sql_log_bin=0; +CALL mtr.add_suppression("Slave worker thread retried transaction 10 time\\(s\\) in vain, giving up"); +CALL mtr.add_suppression("Slave: Deadlock found when trying to get lock; try restarting transaction"); +CALL mtr.add_suppression("Slave worker thread retried transaction .* in vain, giving up"); +SET sql_log_bin=1; + +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100,rpl_parallel_simulate_infinite_temp_err_gtid_0_x_100"; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +START SLAVE; +--let $slave_sql_errno= 1213 +--source include/wait_for_slave_sql_error.inc +SET GLOBAL debug_dbug=@old_dbug; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log + +SELECT * FROM t1 ORDER BY a; +STOP SLAVE IO_THREAD; +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +--echo *** Test retry of event group that spans multiple relay log files. *** + +--connection server_1 +CREATE TABLE t2 (a int PRIMARY KEY, b BLOB) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,"Hulubullu"); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +SET @old_max= @@GLOBAL.max_relay_log_size; +SET GLOBAL max_relay_log_size=4096; + +--connection server_1 +--let $big= `SELECT REPEAT("*", 5000)` +SET gtid_seq_no = 100; +SET @old_server_id = @@server_id; +SET server_id = 12; +BEGIN; +--disable_query_log +eval INSERT INTO t2 VALUES (2, CONCAT("Hello ", "$big")); +eval INSERT INTO t2 VALUES (3, CONCAT("Long data: ", "$big")); +--enable_query_log +INSERT INTO t1 VALUES (10, 4); +COMMIT; +SET server_id = @old_server_id; +SELECT * FROM t1 WHERE a >= 10 ORDER BY a; +SELECT a, LENGTH(b) FROM t2 ORDER BY a; +--save_master_pos + +--connection server_2 +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_gtid_0_x_100"; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--source include/start_slave.inc +--sync_with_master +SET GLOBAL debug_dbug=@old_dbug; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log + +SELECT * FROM t1 WHERE a >= 10 ORDER BY a; +SELECT a, LENGTH(b) FROM t2 ORDER BY a; + +--connection server_1 +INSERT INTO t1 VALUES (11,11); +--disable_query_log +eval INSERT INTO t2 VALUES (4, "$big"); +--enable_query_log +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 WHERE a >= 10 ORDER BY a; +SELECT a, LENGTH(b) FROM t2 ORDER BY a; +SET GLOBAL max_relay_log_size=@old_max; + + +--echo *** MDEV-7065: Incorrect relay log position in parallel replication after retry of transaction *** + +--connection server_2 +--source include/stop_slave.inc + +--connection server_1 +BEGIN; +INSERT INTO t1 VALUES (100, 0); +INSERT INTO t1 VALUES (101, 0); +INSERT INTO t1 VALUES (102, 0); +INSERT INTO t1 VALUES (103, 0); +COMMIT; +SELECT * FROM t1 WHERE a >= 100 ORDER BY a; +--save_master_pos + +--connection server_2 +# Inject a DBUG error insert to cause the XID event of the single transaction +# from the master to fail with a deadlock error and be retried. +# The bug was that the retry of the XID would leave the relay log position +# incorrect (off by the size of XID event). +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,rpl_parallel_simulate_temp_err_xid"; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--source include/start_slave.inc +--sync_with_master +SET GLOBAL debug_dbug=@old_dbug; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log + +SELECT * FROM t1 WHERE a >= 100 ORDER BY a; +# Stop the SQL thread. When the bug was there to give the incorrect relay log +# position, the restart of the SQL thread would read garbage data from the +# middle of an event and fail with relay log IO error. +--source include/stop_slave_sql.inc + +--connection server_1 +INSERT INTO t1 VALUES (104, 1); +INSERT INTO t1 VALUES (105, 1); +INSERT INTO t1 VALUES (106, 1); +INSERT INTO t1 VALUES (107, 1); +INSERT INTO t1 VALUES (108, 1); +INSERT INTO t1 VALUES (109, 1); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 WHERE a >= 100 ORDER BY a; + + +--echo *** MDEV-6917: Parallel replication: "Commit failed due to failure of an earlier commit on which this one depends", but no prior failure seen ** + +--connection server_1 +CREATE TABLE t3 (a INT PRIMARY KEY, b INT, KEY b_idx(b)) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,NULL), (2,2), (3,NULL), (4,4), (5, NULL), (6, 6); +CREATE TABLE t4 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; + +# We need statement binlog format to be able to inject debug_sync statements +# on the slave with calls to foo(). +SET @old_format= @@SESSION.binlog_format; +SET binlog_format='statement'; +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=no; + +--connection server_1 + +# Create a group commit with three transactions T1, T2, T3. +# T2 will block T1 on the slave where we will make it run first, so it will be +# deadlock killed. +# The bug was that in this case, T3 was signalled to fail due to T2 failing, +# even though the retry of T2 was later successful. + +--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET @old_format= @@SESSION.binlog_format; +SET binlog_format='statement'; +BEGIN; +INSERT INTO t4 VALUES (10, foo(1, 'before_execute_sql_command WAIT_FOR t1_start', '')); +UPDATE t3 SET b=NULL WHERE a=6; +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; +send COMMIT; +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued1'; + +--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET @old_format= @@SESSION.binlog_format; +SET binlog_format='statement'; +BEGIN; +INSERT INTO t4 VALUES (20, foo(2, 'group_commit_waiting_for_prior SIGNAL t2_waiting', '')); +DELETE FROM t3 WHERE b <= 3; +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2'; +send COMMIT; + +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued2'; + +--connect (con3,127.0.0.1,root,,test,$SERVER_MYPORT_1,) +SET @old_format= @@SESSION.binlog_format; +SET binlog_format='statement'; +BEGIN; +INSERT INTO t4 VALUES (30, foo(3, 'before_execute_sql_command WAIT_FOR t3_start', 'group_commit_waiting_for_prior SIGNAL t3_waiting')); +INSERT INTO t3 VALUES (7,7); +SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued3'; +send COMMIT; + +--connection server_1 +SET debug_sync='now WAIT_FOR master_queued3'; +SET debug_sync='now SIGNAL master_cont1'; + +--connection con1 +REAP; +SET binlog_format=@old_format; +--connection con2 +REAP; +SET binlog_format=@old_format; +--connection con3 +REAP; +SET debug_sync='RESET'; +SET binlog_format=@old_format; + +--connection server_1 +--save_master_pos +SELECT * FROM t3 ORDER BY a; + + +--connection server_2 +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +SET @old_dbug=@@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,thd_need_ordering_with_force"; +--source include/start_slave.inc +# First, wait for T2 to complete up to where it is waiting for T1 to group +# commit for both of them. This will set locks that will block T1, causing +# a deadlock kill and retry of T2. T1 and T3 are still blocked at the start +# of each their SQL statements. +SET debug_sync='now WAIT_FOR t2_waiting'; +# Now let T3 move on until the point where it is itself ready to commit. +SET debug_sync='now SIGNAL t3_start'; +SET debug_sync='now WAIT_FOR t3_waiting'; +# Now T2 and T3 are set up, so we can let T1 proceed. +SET debug_sync='now SIGNAL t1_start'; +# Now we can wait for the slave to catch up. +# We should see T2 being deadlock killed and retried. +# The bug was that T2 deadlock kill would cause T3 to fail due to failure +# of an earlier commit. This is wrong as T2 did not fail, it was only +# retried. +--sync_with_master +SET GLOBAL debug_dbug=@old_dbug; +SET debug_sync='RESET'; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry >= 1 AS retries; +--enable_query_log +SELECT * FROM t3 ORDER BY a; + + +--connection server_1 +SET binlog_format=@old_format; + + +# Clean up of the above part. +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1, t2, t3, t4; +DROP function foo; + +--sync_slave_with_master server_2 + +# +# MDEV-12746 rpl.rpl_parallel_optimistic_nobinlog fails committing out of order at retry +# + +--connection server_1 +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; + + +# Replicate create-t1 and prepare to re-start slave in optimistic mode +--sync_slave_with_master server_2 +--source include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET @@GLOBAL.slave_parallel_threads=5; +SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; +SET @@GLOBAL.slave_parallel_mode='aggressive'; +SET @old_lock_wait_timeout=@@GLOBAL.innodb_lock_wait_timeout; +SET @@GLOBAL.innodb_lock_wait_timeout=2; +SET @old_slave_transaction_retries=@@GLOBAL.slave_transaction_retries; +SET @@GLOBAL.slave_transaction_retries=1; + +--echo # Spoilers on the slave side causing temporary errors +--connect (spoiler_21,127.0.0.1,root,,test,$SLAVE_MYPORT) +BEGIN; + INSERT INTO t1 SET a=1,b=2; + +--connect (spoiler_22,127.0.0.1,root,,test,$SLAVE_MYPORT) +BEGIN; + INSERT INTO t1 SET a=2,b=2; + +--echo # Master payload +--connection server_1 +SET @@SESSION.GTID_SEQ_NO=1000; +INSERT INTO t1 SET a=1,b=1; +SET @@SESSION.GTID_SEQ_NO=1001; +INSERT INTO t1 SET a=2,b=1; + +--echo # Start slave whose both appliers is destined to being blocked +--connection server_2 +SET @old_dbug= @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="+d,rpl_parallel_simulate_wait_at_retry"; +--source include/start_slave.inc + +--echo # Make sure both workers are waiting at their sync points +--let $wait_condition= SELECT count(*)=2 FROM information_schema.processlist WHERE state LIKE '%debug sync point%'; +--source include/wait_condition.inc + + +--echo # Signal to the 1st to proceed after it has reached termination state +SET @@DEBUG_SYNC='now SIGNAL proceed_by_1000'; +--connection spoiler_21 +ROLLBACK; + +--let $wait_condition= SELECT count(*)=1 FROM information_schema.processlist WHERE state LIKE '%debug sync point%'; +--source include/wait_condition.inc + +--echo # Release the 2nd worker to proceed +--connection spoiler_22 +ROLLBACK; +--connection server_2 +SET @@DEBUG_SYNC='now SIGNAL proceed_by_1001'; + +--echo # observe how it all ends +if (`SELECT count(*) = 1 FROM t1 WHERE a = 1`) +{ + --echo "*** Unexpected commit by the first Worker ***" + SELECT * from t1; + --die +} + +--echo # Wait for the workers to go home and check the result of applying +--let $wait_condition=SELECT count(*) = 0 FROM information_schema.processlist WHERE command = 'Slave_worker' +--source include/wait_condition.inc +if (`SELECT count(*) = 1 FROM t1 WHERE a = 2`) +{ + --echo + --echo "*** Error: congrats, you hit MDEV-12746 issue. ***" + --echo + --die +} +--echo # which is OK + +# +# Clean up +# +--connection server_2 +--source include/stop_slave.inc +SET @@GLOBAL.slave_parallel_threads=@old_parallel_threads; +SET @@GLOBAL.slave_parallel_mode=@old_parallel_mode; +SET @@GLOBAL.innodb_lock_wait_timeout=@old_lock_wait_timeout; +SET @@GLOBAL.slave_transaction_retries=@old_slave_transaction_retries; +SET @@GLOBAL.debug_dbug=@old_dbug; +SET debug_sync='RESET'; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; + +--sync_slave_with_master server_2 + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test new file mode 100644 index 00000000..50b216b6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_retry_deadlock.test @@ -0,0 +1 @@ +--source include/rpl_parallel_retry_deadlock.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test new file mode 100644 index 00000000..f66375b7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_rollback_assert.test @@ -0,0 +1 @@ +--source include/rpl_parallel_rollback_assert.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test new file mode 100644 index 00000000..8c8892d5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_show_binlog_events_purge_logs.test @@ -0,0 +1 @@ +--source include/rpl_parallel_show_binlog_events_purge_logs.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test new file mode 100644 index 00000000..20919823 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_single_grpcmt.test @@ -0,0 +1 @@ +--source include/rpl_parallel_single_grpcmt.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test new file mode 100644 index 00000000..7b0f9485 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test @@ -0,0 +1 @@ +--source include/rpl_parallel_slave_bgc_kill.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test new file mode 100644 index 00000000..64b4cb77 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_on_con_kill.test @@ -0,0 +1 @@ +--source include/rpl_parallel_stop_on_con_kill.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test new file mode 100644 index 00000000..131ddc2e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test @@ -0,0 +1 @@ +--source include/rpl_parallel_stop_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt b/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt new file mode 100644 index 00000000..590d44a6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable-master.opt @@ -0,0 +1 @@ +--loose-skip-stack-trace --skip-core-file diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test new file mode 100644 index 00000000..04165ee4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test @@ -0,0 +1,271 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_binlog_format_statement.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--echo *** MDEV-6321: close_temporary_tables() in format description event not serialised correctly *** + +--connection server_2 +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=5; +CHANGE MASTER TO master_use_gtid= current_pos; +--source include/start_slave.inc + +--connection server_1 +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(100) CHARACTER SET utf8); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc + + +--connection server_1 +SET gtid_domain_id= 1; +INSERT INTO t1 VALUES (1, 0); + +CREATE TEMPORARY TABLE t2 (a int); + +--connection default +SET gtid_domain_id= 2; +CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY); +CREATE TEMPORARY TABLE t4 (a int); +INSERT INTO t3 VALUES (100); +INSERT INTO t4 SELECT a+1 FROM t3; + +--connection server_1 +INSERT INTO t2 VALUES (2), (4), (6), (8), (10), (12), (14), (16), (18), (20); +INSERT INTO t2 VALUES (3), (6), (9), (12), (15), (18); +INSERT INTO t2 VALUES (4), (8), (12), (16), (20); + +--connection default +INSERT INTO t3 SELECT a+2 FROM t4; +INSERT INTO t4 SELECT a+4 FROM t3; + +--connection server_1 +INSERT INTO t2 VALUES (5), (10), (15), (20); +INSERT INTO t2 VALUES (6), (12), (18); +INSERT INTO t2 VALUES (7), (14); +INSERT INTO t2 VALUES (8), (16); +INSERT INTO t2 VALUES (9), (18); +INSERT INTO t2 VALUES (10), (20); + +--connection default +INSERT INTO t3 SELECT a+8 FROM t4; +INSERT INTO t4 SELECT a+16 FROM t3; + +--connection server_1 +INSERT INTO t2 VALUES (11); +INSERT INTO t2 VALUES (12); +INSERT INTO t2 VALUES (13); + +--connection default +INSERT INTO t3 SELECT a+32 FROM t4; + +--connection server_1 +INSERT INTO t2 VALUES (14); +INSERT INTO t2 VALUES (15); +INSERT INTO t2 VALUES (16); + +--connection default +INSERT INTO t4 SELECT a+64 FROM t3; + +--connection server_1 +INSERT INTO t2 VALUES (17); +INSERT INTO t2 VALUES (18); +INSERT INTO t2 VALUES (19); + +--connection default +INSERT INTO t3 SELECT a+128 FROM t4; + +--connection server_1 +INSERT INTO t2 VALUES (20); + +--connection default +INSERT INTO t1 SELECT a, a MOD 7 FROM t3; +INSERT INTO t1 SELECT a, a MOD 7 FROM t4; + +--connection server_1 +INSERT INTO t1 SELECT a, COUNT(*) FROM t2 GROUP BY a; + +# Crash the master server, so that temporary tables are implicitly dropped. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +FLUSH TABLES; +SET SESSION debug_dbug="+d,crash_dispatch_command_before"; +--error 2006,2013 +SELECT 1; + +--source include/wait_until_disconnected.inc +--connection default +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (0, 1); +--save_master_pos + +--connection server_2 +# Start the slave replicating the events. +# The bug was that the format description event written after the crash could +# be fetched ahead of the execution of the temporary table events and executed +# out-of-band. This would cause drop of all temporary tables and thus failure +# for execution of remaining events. + +--source include/start_slave.inc +--sync_with_master + +SELECT * FROM t1 WHERE a <= 20 ORDER BY a; +SELECT COUNT(*) FROM t1 WHERE a BETWEEN 100+0 AND 100+256; +SHOW STATUS LIKE 'Slave_open_temp_tables'; + + +--echo *** Test that if master logged partial event group before crash, we finish that group correctly before executing format description event *** + +--source include/stop_slave.inc + +--connection server_1 +CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table, and writes to any of them"); +SET gtid_domain_id= 1; +DELETE FROM t1; +ALTER TABLE t1 ENGINE=InnoDB; +CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY); +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); + +--connection default +SET gtid_domain_id= 2; +CREATE TEMPORARY TABLE t3 (a INT PRIMARY KEY); +INSERT INTO t3 VALUES (10); +INSERT INTO t3 VALUES (20); + +--connection server_1 +INSERT INTO t1 SELECT a, 'server_1' FROM t2; + +--connection default +INSERT INTO t1 SELECT a, 'default' FROM t3; + +--connection server_1 +INSERT INTO t1 SELECT a+2, '+server_1' FROM t2; + +# Crash the master server in the middle of writing an event group. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +FLUSH TABLES; +SET SESSION debug_dbug="+d,crash_before_writing_xid"; +--error 2006,2013 +INSERT INTO t1 SELECT a+4, '++server_1' FROM t2; + +--source include/wait_until_disconnected.inc +--connection default +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF + +--connection default +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (0, 1); +#--save_master_pos +--source include/save_master_gtid.inc + +--connection server_2 +# Start the slave replicating the events. +# The main thing to test here is that the slave will know that it +# needs to abort the partially received event group, so that the +# execution of format_description event will not wait infinitely +# for a commit of the incomplete group that never happens. + +--source include/start_slave.inc +#--sync_with_master +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 ORDER BY a; +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +--connection server_1 +# This FLUSH can be removed once MDEV-6608 is fixed. +FLUSH LOGS; + + +--echo *** MDEV-7936: Assertion `!table || table->in_use == _current_thd()' failed on parallel replication in optimistic mode *** + +--connection server_1 +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; +SET @commit_id= 10000; +INSERT INTO t4 VALUES (30); +INSERT INTO t4 VALUES (31); +SET SESSION debug_dbug= @old_dbug; +INSERT INTO t1 SELECT a, "conservative" FROM t4; +DROP TEMPORARY TABLE t4; +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/stop_slave.inc +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=optimistic; + +--connection server_1 +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t4 VALUES (32); +INSERT INTO t4 VALUES (33); +INSERT INTO t1 SELECT a, "optimistic" FROM t4; +DROP TEMPORARY TABLE t4; + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_mode; +--source include/start_slave.inc + + +# Clean up. + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test new file mode 100644 index 00000000..3c920e15 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_binlog_order.test @@ -0,0 +1 @@ +--source include/rpl_parallel_wrong_binlog_order.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test new file mode 100644 index 00000000..9cd700f5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_wrong_exec_master_pos.test @@ -0,0 +1 @@ +--source include/rpl_parallel_wrong_exec_master_pos.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test b/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test new file mode 100644 index 00000000..888dd2f1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_xa_same_xid.test @@ -0,0 +1,138 @@ +# The tests verify concurrent execution of replicated (MDEV-742) +# XA transactions in the parallel optimistic mode. +# Prove optimistic scheduler handles xid-namesake XA:s. +# That is despite running in parallel there must be no conflicts +# caused by multiple transactions' same xid. + +--source include/have_binlog_format_mixed_or_row.inc +--source include/have_innodb.inc +--source include/have_perfschema.inc +--source include/master-slave.inc + +--let $xid_num = 19 +--let $repeat = 17 +--let $workers = 7 +--connection slave +call mtr.add_suppression("WSREP: handlerton rollback failed"); + +--source include/stop_slave.inc +# a measure against MDEV-20605 +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + +SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads; +--disable_query_log +--eval SET @@global.slave_parallel_threads = $workers +--enable_query_log +SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode; +SET @@global.slave_parallel_mode ='optimistic'; +--source include/start_slave.inc + +--connection master +CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB; + +--let $i = $xid_num +--let $t = t1 +--disable_query_log +while ($i) +{ +--let $k = $repeat +while ($k) +{ +--eval XA START 'xid_$i' +--eval INSERT INTO $t SET a=$i, b=$k +--eval XA END 'xid_$i' +--let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)` + if (!$one_phase) + { + --eval XA PREPARE 'xid_$i' + --eval XA COMMIT 'xid_$i' + } + if ($one_phase) + { + --eval XA COMMIT 'xid_$i' ONE PHASE + } + + if (!$one_phase) + { + --eval XA START 'xid_$i' + --eval INSERT INTO $t SET a=$i, b=$k + --eval XA END 'xid_$i' + --eval XA PREPARE 'xid_$i' + --eval XA ROLLBACK 'xid_$i' + } + +--dec $k +} + +--dec $i +} +--enable_query_log + + + +# Above-like test complicates execution env to create +# data conflicts as well. They will be resolved by the optmistic +# scheduler as usual. + +CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=InnoDB; + +--let $i = $xid_num +--let $t = t2 +--disable_query_log +while ($i) +{ +--let $k = $repeat +while ($k) +{ +--eval XA START 'xid_$i' +--eval INSERT INTO $t SET a=NULL, b=$k +--eval UPDATE $t SET b=$k + 1 WHERE a=last_insert_id() % $workers +--eval XA END 'xid_$i' +--let $one_phase = `SELECT IF(floor(rand()*10)%2, "ONE PHASE", 0)` + if (!$one_phase) + { + --eval XA PREPARE 'xid_$i' + --eval XA COMMIT 'xid_$i' + } + if ($one_phase) + { + --eval XA COMMIT 'xid_$i' ONE PHASE + } + +--eval XA START 'xid_$i' +--eval UPDATE $t SET b=$k + 1 WHERE a=last_insert_id() % $workers +--eval DELETE FROM $t WHERE a=last_insert_id() +--eval XA END 'xid_$i' +--eval XA PREPARE 'xid_$i' +--eval XA ROLLBACK 'xid_$i' + +--let $do_drop_create = `SELECT IF(floor(rand()*10)%100, 1, 0)` +if ($do_drop_create) +{ + DROP TABLE t1; + CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB; +} +--dec $k +} + +--dec $i +} +--enable_query_log + +--source include/sync_slave_sql_with_master.inc +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET GLOBAL slave_parallel_mode=@old_parallel_mode; +--source include/start_slave.inc + +--connection master +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_partition_archive.test b/mysql-test/suite/rpl/t/rpl_partition_archive.test new file mode 100644 index 00000000..5b64576d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_partition_archive.test @@ -0,0 +1,12 @@ +# Test of partitioning features with replication for archive +--source include/have_archive.inc +--source include/have_partition.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +let $engine_type= 'Archive'; + +--source suite/rpl/include/rpl_partition.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt new file mode 100644 index 00000000..0eed7aaa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_partition_innodb-master.opt @@ -0,0 +1 @@ +--innodb_autoinc_lock_mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_partition_innodb.test b/mysql-test/suite/rpl/t/rpl_partition_innodb.test new file mode 100644 index 00000000..098bc407 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_partition_innodb.test @@ -0,0 +1,12 @@ +# Test of partitioning features with replication for InnoDB +--source include/have_innodb.inc +--source include/have_partition.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +let $engine_type= 'InnoDB'; + +--source suite/rpl/include/rpl_partition.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_partition_memory.test b/mysql-test/suite/rpl/t/rpl_partition_memory.test new file mode 100644 index 00000000..4ce68d6f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_partition_memory.test @@ -0,0 +1,11 @@ +# Test of partitioning features with replication for Memory +--source include/have_partition.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +let $engine_type= 'Memory'; + +--source suite/rpl/include/rpl_partition.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_partition_myisam.test b/mysql-test/suite/rpl/t/rpl_partition_myisam.test new file mode 100644 index 00000000..56003d89 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_partition_myisam.test @@ -0,0 +1,11 @@ +# Test of partitioning features with replication for MyISAM +--source include/have_partition.inc +--source include/master-slave.inc + +# Set the default connection to 'master' + +let $engine_type= 'MyISAM'; + +--source suite/rpl/include/rpl_partition.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_password_boundaries.test b/mysql-test/suite/rpl/t/rpl_password_boundaries.test new file mode 100644 index 00000000..9e968594 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_password_boundaries.test @@ -0,0 +1,101 @@ +source include/not_embedded.inc; +source include/master-slave.inc; +source include/rpl_reset.inc; + +# Suppress warnings that might be generated during the test +disable_query_log; +connection master; +call mtr.add_suppression("Timeout waiting for reply of binlog"); +connection slave; +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); +enable_query_log; + +connection master; + +# wait for dying connections (if any) to disappear +let $wait_condition= select count(*) = 0 from information_schema.processlist where command='killed'; +--source include/wait_condition.inc + +# 32*3-character ASCII password should work all right + +set sql_log_bin=0; +grant replication slave on *.* to rpl32@127.0.0.1 identified by '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; +set sql_log_bin=1; + +connection slave; +source include/stop_slave.inc; +change master to master_user='rpl32',master_password='0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; +source include/start_slave.inc; + +connection master; +drop table if exists t1; +create table t1 (i int); +insert into t1 values (1); +sync_slave_with_master; +echo [ synchronized ]; + +connection master; + +# 32*3+1 -character ASCII password expected to fail +set sql_log_bin=0; +grant replication slave on *.* to rpl33@127.0.0.1 identified by '0123456789abcdef0123456789abcdef!'; +set sql_log_bin=1; + +connection slave; +source include/stop_slave.inc; +--error ER_WRONG_STRING_LENGTH +change master to master_user='rpl33',master_password='0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef!'; + +# Check also master_user and master_host +--error ER_WRONG_STRING_LENGTH +change master to master_user='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; +--error ER_WRONG_STRING_LENGTH +change master to master_host='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'; + +# 48-character cyrillic password should work all right +connection master; +set sql_log_bin=0; +grant replication slave on *.* to rpl16cyr@127.0.0.1 identified by 'воттакойужпарольвоттакойужпарольвоттакойужпароль'; +set sql_log_bin=1; + +connection slave; +SET NAMES utf8; +change master to master_user='rpl16cyr',master_password='воттакойужпарольвоттакойужпарольвоттакойужпароль'; +source include/start_slave.inc; + +connection master; +drop table if exists t1; +create table t1 (i int); +insert into t1 values (1); +sync_slave_with_master; +echo [ synchronized ]; + +# 48+1-character cyrillic password should fail + +connection master; +set sql_log_bin=0; +grant replication slave on *.* to rpl17mix@127.0.0.1 identified by 'воттакойужпарольвоттакойужпарольвоттакойужпароль!'; +set sql_log_bin=1; + +connection slave; +source include/stop_slave.inc; +--error ER_WRONG_STRING_LENGTH +change master to master_user='rpl17mix',master_password='воттакойужпарольвоттакойужпарольвоттакойужпароль!'; + +# Cleanup + +connection master; +set sql_log_bin=0; +drop user rpl32@127.0.0.1, rpl33@127.0.0.1, rpl16cyr@127.0.0.1, rpl17mix@127.0.0.1; +set sql_log_bin=1; + +connection slave; +change master to master_user='root',master_password=''; +source include/start_slave.inc; + +connection master; +drop table if exists t1; +sync_slave_with_master; + +connection master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_performance_schema.test b/mysql-test/suite/rpl/t/rpl_performance_schema.test new file mode 100644 index 00000000..18aabe52 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_performance_schema.test @@ -0,0 +1,10 @@ +--source include/have_perfschema.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +UPDATE performance_schema.setup_instruments SET ENABLED="NO"; + +--sync_slave_with_master +--source include/rpl_end.inc + +# End of test case diff --git a/mysql-test/suite/rpl/t/rpl_plugin_load.test b/mysql-test/suite/rpl/t/rpl_plugin_load.test new file mode 100644 index 00000000..c319479a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_plugin_load.test @@ -0,0 +1,59 @@ +# +# Bug#35807 - INSTALL PLUGIN replicates row-based, but not stmt-based +# +# The test verifies that INSTALL PLUGIN and UNINSTALL PLUGIN +# work with replication. +# +# The test tries to install and uninstall a plugin on master, +# and verifies that it does not affect the slave, +# and that it does not add anything to the binlog. + +--source include/not_embedded.inc +--source include/have_log_bin.inc +--source include/have_example_plugin.inc + +# Initialize replication. +--source include/master-slave.inc +--echo Verify that example engine is not installed. +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE'; +--echo Get binlog position before install plugin. +let $before_pos = query_get_value("SHOW MASTER STATUS", Position, 1); +--echo Install example engine. +--replace_regex /\.dll/.so/ +eval INSTALL PLUGIN example SONAME '$HA_EXAMPLE_SO'; +--echo Get binlog position after install plugin. +let $after_pos = query_get_value("SHOW MASTER STATUS", Position, 1); +--echo Compute the difference of the binlog positions. +--echo Should be zero as install plugin should not be replicated. +--disable_query_log +eval SELECT $after_pos - $before_pos AS Delta; +--enable_query_log +--echo Verify that example engine is installed. +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE'; +# Wait for slave to catch up with master. +sync_slave_with_master; +# + --echo Verify that example engine is not installed. + connection slave; + SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE'; +# +--echo Uninstall example engine. +connection master; +--echo Get binlog position before uninstall plugin. +let $before_pos = query_get_value("SHOW MASTER STATUS", Position, 1); +UNINSTALL PLUGIN example; +--echo Get binlog position after uninstall plugin. +let $after_pos = query_get_value("SHOW MASTER STATUS", Position, 1); +--echo Compute the difference of the binlog positions. +--echo Should be zero as uninstall plugin should not be replicated. +--disable_query_log +eval SELECT $after_pos - $before_pos AS Delta; +--enable_query_log +--echo Verify that example engine is not installed. +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='EXAMPLE'; +# Wait for slave to catch up with master. +sync_slave_with_master; +# +# Cleanup +--source include/rpl_end.inc +--echo End of test diff --git a/mysql-test/suite/rpl/t/rpl_ps.test b/mysql-test/suite/rpl/t/rpl_ps.test new file mode 100644 index 00000000..45ab55bf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ps.test @@ -0,0 +1,94 @@ +# +# Test of replicating user variables +# +source include/master-slave.inc; + +#sync_slave_with_master; +#reset master; +#connection master; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(n char(30)); + +prepare stmt1 from 'insert into t1 values (?)'; +set @var1= "from-master-1"; +execute stmt1 using @var1; +set @var1= "from-master-2-'',"; +execute stmt1 using @var1; +SELECT * FROM t1 ORDER BY n; + +set @var2= 'insert into t1 values (concat("from-var-", ?))'; +prepare stmt2 from @var2; +set @var1='from-master-3'; +execute stmt2 using @var1; + +sync_slave_with_master; +SELECT * FROM t1 ORDER BY n; + +connection master; + +drop table t1; + +sync_slave_with_master; +stop slave; +source include/wait_for_slave_to_stop.inc; +# End of 4.1 tests + +# +# Bug #25843 Changing default database between PREPARE and EXECUTE of statement +# breaks binlog. +# +# There were actually two problems discovered by this bug: +# +# 1. Default (current) database is not fixed at the creation time. +# That leads to wrong output of DATABASE() function. +# +# 2. Database attributes (@@collation_database) are not fixed at the creation +# time. That leads to wrong resultset. +# +# Binlog breakage and Query Cache wrong output happened because of the first +# problem. +# + +--echo +--echo ######################################################################## +--echo # +--echo # BUG#25843: Changing default database between PREPARE and EXECUTE of +--echo # statement breaks binlog. +--echo # +--echo ######################################################################## + +############################################################################### + +--connection slave + +START SLAVE; + +--connection master + +CREATE DATABASE mysqltest1; +CREATE TABLE t1(db_name CHAR(32), db_col_name CHAR(32)); + +PREPARE stmt_d_1 FROM 'INSERT INTO t1 VALUES(DATABASE(), @@collation_database)'; + +EXECUTE stmt_d_1; + +use mysqltest1; + +EXECUTE stmt_d_1; + +--sync_slave_with_master + +SELECT * FROM t1; + +--connection master + +DROP DATABASE mysqltest1; + +use test; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test b/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test new file mode 100644 index 00000000..1bc20c1e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rbr_to_sbr.test @@ -0,0 +1,31 @@ +-- source include/have_binlog_format_mixed.inc +-- source include/master-slave.inc + +# Test that the slave temporarily switches to ROW when seeing row +# events when it is in MIXED mode + +CREATE TABLE t1 (a INT, b LONG); +INSERT INTO t1 VALUES (1,1), (2,2); +INSERT INTO t1 VALUES (3,UUID()), (4,UUID()); +source include/show_binlog_events.inc; +sync_slave_with_master; +source include/show_binlog_events.inc; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql + +connection master; +DROP TABLE IF EXISTS t1; + +# Let's compare. Note: If they match test will pass, if they do not match +# the test will show that the diff statement failed and not reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching + +diff_files $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql; + +# If all is good, we can remove the files + +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_master.sql +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_rbr_to_sbr_slave.sql +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test b/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test new file mode 100644 index 00000000..1e2c8ce2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_read_new_relay_log_info.test @@ -0,0 +1,43 @@ +# ==== Purpose ==== +# +# - Verify that the post-WL#344 format of relay_log.info can be parsed. + +--source include/master-slave.inc + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +--sync_slave_with_master + +--echo ==== Check that we can understand the new format of relay-log.info ==== +--source include/stop_slave.inc + +RESET SLAVE; +--let $MYSQLD_DATADIR= `select @@datadir` + +# the new version of relay_log.info comes in two versions: with path +# separator '/' (most systems) and with path separator '\' (windows) +if ($SYSTEM_PATH_SEPARATOR != /) { + --let $file_suffix= -win +} +--copy_file $MYSQL_TEST_DIR/std_data/new-format-relay-log$file_suffix.info $MYSQLD_DATADIR/relay-log.info + +--echo # Read relay-log.info +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +--echo # Check that relay log coordinates are equal to those saved in new-format_relay-log.info +--let $master_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $master_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $relay_log_pos= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--echo $master_file= $master_file, $master_pos, $relay_log_file, $relay_log_pos +if (`SELECT "$master_file" != "" OR + "$master_pos" != "0" OR + "$relay_log_file" != "slave-relay-bin.000001" OR + "$relay_log_pos" != "4"`) { + --echo ERROR: log coordinates changed + --die log coordinates changed +} + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test new file mode 100644 index 00000000..ce345445 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_read_old_relay_log_info.test @@ -0,0 +1,44 @@ +# ==== Purpose ==== +# +# - Verify that the pre-WL#344 format of relay_log.info can still be +# parsed. + +--source include/master-slave.inc + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +--sync_slave_with_master + +--echo ==== Check that we still understand the old format of relay-log.info ==== +--source include/stop_slave.inc + +RESET SLAVE; +--let $MYSQLD_DATADIR= `select @@datadir` + +# the old version of relay_log.info comes in two versions: with path +# separator '/' (most systems) and with path separator '\' (windows) +if ($SYSTEM_PATH_SEPARATOR != /) { + --let $file_suffix= -win +} +--copy_file $MYSQL_TEST_DIR/std_data/old-format-relay-log$file_suffix.info $MYSQLD_DATADIR/relay-log.info + +--echo # Read relay-log.info +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +--echo # Check that relay log coordinates are equal to those we saved in old-format_relay-log.info +--let $master_file= query_get_value(SHOW SLAVE STATUS, Relay_Master_Log_File, 1) +--let $master_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) +--let $relay_log_pos= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1) +--echo $master_file= $master_file, $master_pos, $relay_log_file, $relay_log_pos +if (`SELECT "$master_file" != "" OR + "$master_pos" != "0" OR + "$relay_log_file" != "slave-relay-bin.000001" OR + "$relay_log_pos" != "4"`) { + --echo ERROR: log coordinates changed + --die log coordinates changed +} + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_read_only.test b/mysql-test/suite/rpl/t/rpl_read_only.test new file mode 100644 index 00000000..c4781bbb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_read_only.test @@ -0,0 +1,129 @@ +# Test case for BUG #11733 +-- source include/have_innodb.inc +-- source include/master-slave.inc + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +# Create a test and replicate it to slave +connection master; +create user test; +sync_slave_with_master; + +# Setting the master readonly : +# - the variable @@readonly is not replicated on the slave + +connect (master2,127.0.0.1,test,,test,$MASTER_MYPORT,); +connect (slave2,127.0.0.1,test,,test,$SLAVE_MYPORT,); + +connection master1; + +create table t1(a int) engine=InnoDB; +create table t2(a int) engine=MyISAM; +insert into t1 values(1001); +insert into t2 values(2001); + +connection master; +set global read_only=1; + +connection master1; +select @@read_only; +select * from t1; +select * from t2; + +sync_slave_with_master; +select @@read_only; +select * from t1; +select * from t2; + +# - replication of transactions +connection master; +set global read_only=0; + +connection master1; +BEGIN; + +connection master2; +BEGIN; + +connection master; +select @@read_only; +set global read_only=1; + +connection master1; +-- echo *** On SUPER USER connection *** +insert into t1 values(1002); +--disable_warnings +insert into t2 values(2002); +--enable_warnings + +connection master2; +-- echo *** On regular USER connection *** +--error ER_OPTION_PREVENTS_STATEMENT +insert into t1 values(1003); +--error ER_OPTION_PREVENTS_STATEMENT +insert into t2 values(2003); + +connection master1; +## works even with read_only=1, because master1 is root +-- echo *** SUPER USER COMMIT (must succeed) *** +COMMIT; + +connection master2; +-- echo *** regular USER COMMIT (must succeed - nothing to commit) *** +COMMIT; + +connection master; +select @@read_only; +set global read_only=0; + +connection master1; +insert into t1 values(1004); +insert into t2 values(2004); + +select * from t1; +select * from t2; + +sync_slave_with_master; +select * from t1; +select * from t2; + +# Setting the slave readonly : replication will pass +# +connection slave1; +set global read_only=1; + +connection slave; +select @@read_only; +# Make sure the replicated table is also transactional +show create table t1; +# Make sure the replicated table is not transactional +show create table t2; + +connection master; +insert into t1 values(1005); +insert into t2 values(2005); +select * from t1; +select * from t2; + +sync_slave_with_master; +connection slave; +select * from t1; +select * from t2; + +# Non root user can not write on the slave +connection slave2; +--error ER_OPTION_PREVENTS_STATEMENT +insert into t1 values(1006); +--error ER_OPTION_PREVENTS_STATEMENT +insert into t2 values(2006); + +## Cleanup +connection master; +drop user test; +drop table t1; +drop table t2; +sync_slave_with_master; +set global read_only=0; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_read_only2.test b/mysql-test/suite/rpl/t/rpl_read_only2.test new file mode 100644 index 00000000..da825c8f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_read_only2.test @@ -0,0 +1,30 @@ +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +--echo # +--echo # Ensure that read-only slave logs temporary table statements under statement based +--echo # replication. This is related to MDEV-17863. +--echo # + +connection slave; +set global read_only=1; + +connection master; + +create table t1(a int) engine=MyISAM; +create temporary table tmp1 (a int) engine=MyISAM; +insert into t1 values(1); +insert into tmp1 values (2); +insert into t1 select * from tmp1; +insert into t1 values(3); +select * from t1; +analyze table t1; +drop table t1; +drop temporary table tmp1; + +sync_slave_with_master; +--source include/show_binlog_events.inc +set global read_only=0; +connection master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_relay_max_extension.test b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test new file mode 100644 index 00000000..e1e087f2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test @@ -0,0 +1,109 @@ +# ==== Purpose ==== +# +# Test verifies that auto purging mechanism of relay logs works fine when the +# file extension grows beyond 999999. +# +# ==== Implementation ==== +# +# Steps: +# 0 - In master-slave setup clear all the relay logs on the slave server. +# 1 - Start the slave so that new relay logs starting from +# 'slave-relay-bin.000001' are created. +# 2 - Get the active relay-log file name by using SHOW SLAVE STATUS. +# Shutdown the slave server. +# 3 - Rename active relay log to '999997' in both 'relay-log.info' and +# 'slave-relay-bin.index' files. +# 4 - Restart the slave server by configuring 'slave_parallel_threads=1' +# and 'max_relay_log_size=100K'. +# 5 - Generate load on master such that few relay logs are generated on +# slave. The relay log sequence number will change to 7 digits. +# 6 - Sync slave with master to ensure that relay logs are applied on +# slave. They should have been automatically purged. +# 7 - Assert that there is no 'slave-relay-bin.999999' file in +# 'relay-log.info'. +# +# ==== References ==== +# +# MDEV-8134: The relay-log is not flushed after the slave-relay-log.999999 +# showed +# + +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc +--let $rpl_topology=1->2 +--source include/rpl_init.inc + +--connection server_2 +--source include/stop_slave.inc +RESET SLAVE; +--source include/start_slave.inc +--source include/stop_slave.inc +--let $relay_log=query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) + +--echo # +--echo # Stop slave server +--echo # + +--let $datadir = `select @@datadir` +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +--exec sed -i "s/$relay_log/slave-relay-bin.999997/g" $datadir/relay-log.info +--exec sed -i "s/$relay_log/slave-relay-bin.999997/g" $datadir/slave-relay-bin.index + +--echo # +--echo # Simulate file number get close to 999997 +--echo # by renaming relay logs and modifying index/info files + +--move_file $datadir/$relay_log $datadir/slave-relay-bin.999997 + +--echo # +--echo # Restart slave server +--echo # + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--enable_reconnect +--source include/wait_until_connected_again.inc +SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads; +SET @save_max_relay_log_size= @@GLOBAL.max_relay_log_size; + +SET GLOBAL slave_parallel_threads=1; +SET GLOBAL max_relay_log_size=100 * 1024; +--source include/start_slave.inc + +--connection server_1 +create table t1 (i int, c varchar(1024)); +--echo # +--echo # Insert some data to generate enough amount of binary logs +--echo # +--let $count = 1000 +--disable_query_log +while ($count) +{ + eval insert into t1 values (1001 - $count, repeat('a',1000)); + dec $count; +} +--enable_query_log +--save_master_pos + +--connection server_2 +--sync_with_master + +--let $relay_log=query_get_value(SHOW SLAVE STATUS, Relay_Log_File, 1) + +--echo # +--echo # Assert that 'slave-relay-bin.999999' is purged. +--echo # +let SEARCH_FILE=$datadir/slave-relay-bin.index; +let SEARCH_PATTERN=slave-relay-bin.999999; +source include/search_pattern_in_file.inc; + +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads= @save_slave_parallel_threads; +SET GLOBAL max_relay_log_size= @save_max_relay_log_size; +--source include/start_slave.inc + +--connection server_1 +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test b/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test new file mode 100644 index 00000000..ccb1424a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relay_space_innodb.test @@ -0,0 +1,3 @@ +-- source include/have_innodb.inc +let $engine_type=InnoDB; +-- source include/rpl_sv_relay_space.test diff --git a/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test b/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test new file mode 100644 index 00000000..6aa91dbc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relay_space_myisam.test @@ -0,0 +1,2 @@ +let $engine_type=MyISAM; +-- source include/rpl_sv_relay_space.test diff --git a/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt b/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt new file mode 100644 index 00000000..5cdfe28d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relayrotate-slave.opt @@ -0,0 +1,2 @@ +--max_relay_log_size=16384 +--log-warnings diff --git a/mysql-test/suite/rpl/t/rpl_relayrotate.test b/mysql-test/suite/rpl/t/rpl_relayrotate.test new file mode 100644 index 00000000..720739e1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relayrotate.test @@ -0,0 +1 @@ +--source include/rpl_relayrotate.inc diff --git a/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt b/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt new file mode 100644 index 00000000..06d96aa3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relayspace-slave.opt @@ -0,0 +1 @@ +--relay_log_space_limit=10 diff --git a/mysql-test/suite/rpl/t/rpl_relayspace.test b/mysql-test/suite/rpl/t/rpl_relayspace.test new file mode 100644 index 00000000..fc33d6bc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_relayspace.test @@ -0,0 +1,52 @@ +# The slave is started with relay_log_space_limit=10 bytes, +# to force the deadlock after one event. + +source include/master-slave.inc; +--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1) +connection slave; +--source include/stop_slave.inc +connection master; +# This will generate a master's binlog > 10 bytes +create table t1 (a int); +drop table t1; +create table t1 (a int); +drop table t1; +connection slave; +reset slave; +start slave io_thread; +# Give the I/O thread time to block. +let $slave_param= Slave_IO_State; +let $slave_param_value= Waiting for the slave SQL thread to free enough relay log space; +source include/wait_for_slave_param.inc; + +# A bug caused the I/O thread to refuse stopping. +--source include/stop_slave_io.inc +reset slave; +--source include/start_slave.inc + +# The I/O thread stops filling the relay log when it's >10b. And the +# SQL thread cannot purge this relay log as purge is done only when +# the SQL thread switches to another relay log, which does not exist +# here. So we should have a deadlock. If it is not resolved +# automatically we'll detect it with master_pos_wait that waits for +# farther than 1Ob; it will timeout after 300 seconds (which is inline +# with the default used for sync_slave_with_master and will protect us +# against slow test envs); also the slave will probably not cooperate +# to shutdown (as 2 threads are locked) +--let $outcome= `SELECT MASTER_POS_WAIT('$master_log_file',200,300) AS mpw;` + +# master_pos_wait returns: +# +# * >= 0, the number of events the slave had to wait to advance to the +# position +# +# * -1, if there was a timeout +# +# * NULL, if an error occurred, or the SQL thread was not started, +# slave master info is not initialized, the arguments are incorrect +--let $assert_text= Assert that master_pos_wait does not timeout nor it returns NULL +--let $assert_cond= $outcome IS NOT NULL AND $outcome <> -1 +--source include/assert.inc + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test b/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test new file mode 100644 index 00000000..2396dc34 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_reopen_temp_table.test @@ -0,0 +1,43 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +# Clean up old slave's binlogs (see rpl_temporary.test for explanation). +save_master_pos; +connection slave; +sync_with_master; +reset master; + +--echo # +--echo # MDEV-5535: Cannot reopen temporary table +--echo # + +connection master; +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +disable_warnings; +DROP TABLE IF EXISTS t1, t2, t3; +enable_warnings; + +CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); + +CREATE TEMPORARY TABLE t2 SELECT A.c1 a, B.c1 b FROM t1 AS A, t1 AS B; + +CREATE TABLE t3 SELECT * FROM t2; + +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 25 FROM t2; +SELECT COUNT(*) = 25 FROM t3; + +sync_slave_with_master; + +SELECT COUNT(*) = 25 FROM t3; + +connection master; +DROP TABLE t1, t2, t3; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt b/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt new file mode 100644 index 00000000..da345474 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_replicate_do-slave.opt @@ -0,0 +1 @@ +--replicate-do-table=test.t1 diff --git a/mysql-test/suite/rpl/t/rpl_replicate_do.test b/mysql-test/suite/rpl/t/rpl_replicate_do.test new file mode 100644 index 00000000..66ddf2df --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_replicate_do.test @@ -0,0 +1,65 @@ +# This test assumes we are ignoring updates on table t2, but doing +# updates on t1 +source include/master-slave.inc; +--disable_warnings +drop table if exists t11; +connection slave; +drop table if exists t11; +--enable_warnings + +create table t2 (n int); +insert into t2 values(4); +connection master; +create table t2 (s char(20)); +load data infile '../../std_data/words.dat' into table t2; +insert into t2 values('five'); +create table t1 (m int); +insert into t1 values(15),(16),(17); +update t1 set m=20 where m=16; +delete from t1 where m=17; +create table t11 select * from t1; +sync_slave_with_master; +select * from t1 ORDER BY m; +select * from t2; +--error 1146 +select * from t11; +connection master; +drop table if exists t1,t2,t11; +sync_slave_with_master; +# show slave status, just to see of it prints replicate-do-table +let $status_items= Replicate_Do_Table; +source include/show_slave_status.inc; + +# End of 4.1 tests + +# +# Bug#24478 DROP TRIGGER is not caught by replicate-*-table filters +# +connection master; +create table t1 (a int, b int); +create trigger trg1 before insert on t1 for each row set new.b=2; +create table t2 (a int, b int); +create trigger trg2 before insert on t2 for each row set new.b=2; +show tables; +--replace_column 6 # +show triggers; +sync_slave_with_master; +connection slave; +show tables; +--replace_column 6 # +show triggers; +connection master; +drop trigger trg1; +drop trigger trg2; +--replace_column 6 # +show triggers; +sync_slave_with_master; +connection slave; +show tables; +--replace_column 6 # +show triggers; +connection master; +drop table t1; +drop table t2; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt new file mode 100644 index 00000000..6e3aed44 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db-slave.opt @@ -0,0 +1 @@ +--replicate_ignore_db=mysqltest1 diff --git a/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test new file mode 100644 index 00000000..f1907456 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_replicate_ignore_db.test @@ -0,0 +1,31 @@ +# see if --replicate-ignore-db works + +--source include/master-slave.inc + +--disable_warnings +drop database if exists mysqltest1; +drop database if exists mysqltest2; +--enable_warnings +create database mysqltest1; +create database mysqltest2; + +use mysqltest1; +create table t1 (a int); +insert into t1 values(1); +sync_slave_with_master; +--error 1146 +select * from mysqltest1.t1; + +connection master; +use mysqltest2; +create table t1 (a int); +insert into t1 values(1); +sync_slave_with_master; +select * from mysqltest2.t1; + +# cleanup +connection master; +drop database mysqltest1; +drop database mysqltest2; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_report-slave.opt b/mysql-test/suite/rpl/t/rpl_report-slave.opt new file mode 100644 index 00000000..123e5c27 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_report-slave.opt @@ -0,0 +1,2 @@ +--report-host=127.0.0.1 --report-user='my_user' --report-password='my_password' --report-port=9308 + diff --git a/mysql-test/suite/rpl/t/rpl_report.test b/mysql-test/suite/rpl/t/rpl_report.test new file mode 100644 index 00000000..a7344291 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_report.test @@ -0,0 +1,22 @@ +# Verify that mysqld init time --report-{host,port,user,password} parameters +# are SHOW-able and SELECT-able FROM INFORMATION_SCHEMA.global_variables + +source include/master-slave.inc; + +connection slave; +select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_host'; +select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_port'; +select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_user'; +select * from Information_schema.GLOBAL_VARIABLES where variable_name like 'report_password'; +query_vertical show global variables like 'report_host'; +query_vertical show global variables like 'report_port'; +query_vertical show global variables like 'report_user'; +query_vertical show global variables like 'report_password'; + +# to demonstrate that report global variables are read-only +error ER_INCORRECT_GLOBAL_LOCAL_VAR; +set @@global.report_host='my.new.address.net'; + + +--echo end of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_report_port.test b/mysql-test/suite/rpl/t/rpl_report_port.test new file mode 100644 index 00000000..2a14d278 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_report_port.test @@ -0,0 +1,74 @@ +# +#BUG#13333431 : INCORRECT DEFAULT PORT IN 'SHOW SLAVE HOSTS' OUTPUT +# +# ==== Purpose ==== +# +# The test show the default value printed for the slave's port number if the +# --report-port= <some value> is not set on the slave. This is different from +# the present scenario which show 3306 as the default value if the report-port +# is not set on the slave. +# +#====Method==== +# +# Start replication with report port set to 9000 and restart the slave. +# In this case on doing SHOW SLAVE HOSTS on the master, we get the port number +# of the slave to be 9000. +# In the second case restart the slave server with report port not set. In this +# case on doing SHOW SLAVE HOSTS on the master, we get the actual port number +# of the slave (ie. SLAVE_PORT). + +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +connection master; + +# Start the server with some value being passed to the report_port= <option> +# this will be used incase we have to mask the value of the slave's port +# number in certain situations. + +--let $rpl_server_number= 2 +--let $rpl_server_parameters= --report-port=9000 +--source include/rpl_restart_server.inc + +connection slave; +--source include/start_slave.inc +--let $slave_param= Slave_IO_State +--let $slave_param_value= Waiting for master to send event +--source include/wait_for_slave_param.inc + +--echo [Slave restarted with the report-port set to some value] +connection master; + +# 9000 is the value of the port we should get. +--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1) +--let assert_text= The value shown for the slave's port number is user specified port number which is the value set for report-port. +--let assert_cond= $report_port = "9000" +--source include/assert.inc + +# Start the server with the report-port being passed with no value. So on SHOW SLAVE HOSTS +# on the master the value of slave's port should be the actual value of the slave port. +connection master; + +--let $rpl_server_number= 2 +--let $rpl_server_parameters= +--source include/rpl_restart_server.inc + +connection slave; +--source include/start_slave.inc +--let $slave_param= Slave_IO_State +--let $slave_param_value= Waiting for master to send event +--source include/wait_for_slave_param.inc + +connection master; +sync_slave_with_master; +--echo [Slave restarted with the report-port set to the value of slave's port number] + +connection master; + +# The value reported is the actual value of the slave's port. +--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1) +--let assert_text= The default value shown for the slave's port number is the actual port number of the slave. +--let assert_cond= $report_port = "$SLAVE_MYPORT" +--source include/assert.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test new file mode 100644 index 00000000..021dc76d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_reset_slave_fail.test @@ -0,0 +1,91 @@ +############################################################################### +# Bug#24901077: RESET SLAVE ALL DOES NOT ALWAYS RESET SLAVE +# +# Problem: +# ======= +# If you have a relay log index file that has ended up with +# some relay log files that do not exists, then RESET SLAVE +# ALL is not enough to get back to a clean state. +############################################################################### +# Remove all slave-relay-bin.0* files (do not remove slave-relay-bin.index) +# During server restart rli initialization will fail as there are no +# relay logs. In case of bug RESET SLAVE will not do the required clean up +# as rli is not inited and subsequent START SLAVE will fail. +# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found" +# because it is different on Unix and Windows systems. + +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--connection master +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 (c1) VALUES (1); +--sync_slave_with_master + +--connection slave +--source include/stop_slave_sql.inc +--let $MYSQLD_SLAVE_DATADIR= `select @@datadir` + +--connection master +# Generate more relay logs on slave. +FLUSH LOGS; +FLUSH LOGS; +INSERT INTO t1 (c1) VALUES (2); + +--source include/sync_slave_io_with_master.inc +call mtr.add_suppression("File '.*slave-relay-bin."); +call mtr.add_suppression("Could not open log file"); +call mtr.add_suppression("Failed to open the relay log"); +call mtr.add_suppression("Failed to initialize the master info structure"); + +# Stop slave +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +# Delete file(s) +--echo # Removing $remove_pattern file(s) +--let $remove_pattern= slave-relay-bin.0* +--remove_files_wildcard $MYSQLD_SLAVE_DATADIR $remove_pattern + +# Start slave +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +# Start slave must fail because of the removed file(s). +--error ER_MASTER_INFO +START SLAVE; + +# Try a second time, it must fail again. +--error ER_MASTER_INFO +START SLAVE; + +# Retrieve master executed position before reset slave. +--let $master_exec_file= query_get_value("SHOW SLAVE STATUS", Relay_Master_Log_File, 1) +--let $master_exec_pos= query_get_value("SHOW SLAVE STATUS", Exec_Master_Log_Pos, 1) + +# Reset slave. +# Disable "Warning 1612 Being purged log ./slave-relay-bin.0* was not found" +# because it is different on Unix and Windows systems. +--disable_warnings +RESET SLAVE; +--enable_warnings +DROP TABLE t1; +--replace_result $master_exec_file MASTER_LOG_FILE $master_exec_pos MASTER_LOG_POS +--eval START SLAVE UNTIL MASTER_LOG_FILE= '$master_exec_file', MASTER_LOG_POS= $master_exec_pos; +--source include/wait_for_slave_sql_to_stop.inc +--source include/stop_slave_io.inc + +# Start slave. +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +# Check consistency. +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + +# Cleanup +--connection master +DROP TABLE t1; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt b/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt new file mode 100644 index 00000000..84059110 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rewrt_db-slave.opt @@ -0,0 +1 @@ +"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1 -> test" "--replicate-rewrite-db=x -> y" "--replicate-rewrite-db=database_master_temp_01->database_slave_temp_01" "--replicate-rewrite-db=database_master_temp_02->database_slave_temp_02" "--replicate-rewrite-db=database_master_temp_03->database_slave_temp_03" diff --git a/mysql-test/suite/rpl/t/rpl_rewrt_db.test b/mysql-test/suite/rpl/t/rpl_rewrt_db.test new file mode 100644 index 00000000..aa0370c8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rewrt_db.test @@ -0,0 +1,250 @@ +# TBF - difference in row level logging +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc + +--connection slave +set sql_log_bin=0; +create database y; +set sql_log_bin=1; + +--connection master +--disable_warnings +drop database if exists mysqltest1; +drop database if exists x; +--enable_warnings +create database mysqltest1; +set sql_log_bin=0; +create database x; +set sql_log_bin=1; + +use mysqltest1; +create table t1 (a int); +insert into t1 values(9); +use x; +create table t1 (a int); +insert into t1 values(9); +select * from mysqltest1.t1; +select * from x.t1; +sync_slave_with_master; +#TODO no it is no empty +show databases like 'mysqltest1'; # should be empty +select * from test.t1; +select * from y.t1; +# cleanup +connection master; +use mysqltest1; +drop table t1; +drop database mysqltest1; +sync_slave_with_master; + +# +# BUG#6353: +# Option --replicate-rewrite-db should work together with LOAD DATA INFILE +# + +connection slave; +--disable_warnings +drop database if exists rewrite; +--enable_warnings +create database rewrite; + +connection master; +use test; +create table t1 (a date, b date, c date not null, d date); +load data infile '../../std_data/loaddata1.dat' ignore into table t1 fields terminated by ','; +load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; +sync_slave_with_master; + +connection slave; +select * from rewrite.t1; + +connection master; +truncate table t1; +load data infile '../../std_data/loaddata1.dat' ignore into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d); +sync_slave_with_master; + +connection slave; +select * from rewrite.t1; + +connection master; +drop table t1; +create table t1 (a text, b text); +load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +sync_slave_with_master; + +connection slave; +select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1; + +connection master; +drop table t1; +create table t1 (a int, b char(10)); +load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; +sync_slave_with_master; + +connection slave; +select * from rewrite.t1; + +connection master; +truncate table t1; +load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; +sync_slave_with_master; + +connection slave; +# The empty line last comes from the end line field in the file +select * from rewrite.t1; + +set sql_log_bin= 0; +drop database rewrite; +set sql_log_bin= 1; + +connection master; +set sql_log_bin= 0; +drop table t1; +set sql_log_bin= 1; + +# End of 4.1 tests + +--echo +--echo **** +--echo **** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db +--echo **** +--echo + +--echo **** +--echo **** Preparing the environment +--echo **** +connection master; + +connect (con_temp_03,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con_temp_02,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con_temp_01,127.0.0.1,root,,test,$MASTER_MYPORT,); + +connection master; +SET sql_log_bin= 0; +CREATE DATABASE database_master_temp_01; +CREATE DATABASE database_master_temp_02; +CREATE DATABASE database_master_temp_03; +SET sql_log_bin= 1; + +connection slave; +SET sql_log_bin= 0; +CREATE DATABASE database_slave_temp_01; +CREATE DATABASE database_slave_temp_02; +CREATE DATABASE database_slave_temp_03; +SET sql_log_bin= 1; + +--echo +--echo **** +--echo **** Creating temporary tables on different databases with different connections +--echo **** +--echo **** con_temp_01 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** +--echo **** con_temp_02 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02 +--echo **** +--echo **** con_temp_02 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02 +--echo **** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03 +--echo **** + +connection con_temp_01; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); + +connection con_temp_02; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); + +connection con_temp_03; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); +USE database_master_temp_03; +CREATE TEMPORARY TABLE t_03_01_temp(a int); +INSERT INTO t_03_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_02_temp(a int); +INSERT INTO t_03_02_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_03_temp(a int); +INSERT INTO t_03_03_temp VALUES(1); + +--echo +--echo **** Dropping the connections +--echo **** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no +--echo **** guarantee that logging of the terminated con1 has been done yet.a To be +--echo **** sure that logging has been done, we use a user lock. +--echo +connection master; +sync_slave_with_master; +connection slave; +show status like 'Slave_open_temp_tables'; + +connection master; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +connection con_temp_01; +select get_lock("con_01",10); +connection master; +disconnect con_temp_01; +select get_lock("con_01",10); + +connection con_temp_02; +select get_lock("con_02",10); +connection master; +disconnect con_temp_02; +select get_lock("con_02",10); + +connection con_temp_03; +select get_lock("con_03",10); +connection master; +disconnect con_temp_03; +select get_lock("con_03",10); + +--echo +--echo **** Checking the binary log and temporary tables +--echo +connection master; +sync_slave_with_master; +connection slave; +show status like 'Slave_open_temp_tables'; + +connection master; +--source include/show_binlog_events.inc + +--echo **** +--echo **** Cleaning up the test case +--echo **** +connection master; +SET sql_log_bin= 0; +DROP DATABASE database_master_temp_01; +DROP DATABASE database_master_temp_02; +DROP DATABASE database_master_temp_03; +DROP DATABASE x; +SET sql_log_bin= 1; + +connection slave; +SET sql_log_bin= 0; +DROP DATABASE database_slave_temp_01; +DROP DATABASE database_slave_temp_02; +DROP DATABASE database_slave_temp_03; +DROP DATABASE y; +SET sql_log_bin= 1; + +connection master; +sync_slave_with_master; + +# end of 5.0 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf b/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf new file mode 100644 index 00000000..7e676dc2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.cnf @@ -0,0 +1,6 @@ +!include ../rpl_1slave_base.cnf + +[mysqld.1] +max_binlog_size=4096 + + diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.test b/mysql-test/suite/rpl/t/rpl_rotate_logs.test new file mode 100644 index 00000000..0d65a05b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test @@ -0,0 +1,200 @@ +# This test uses chmod, can't be run with root permissions +-- source include/not_as_root.inc + +-- source include/have_log_bin.inc + +# +# Test is run with max_binlog_size=2048 to force automatic rotation of the +# binary log +# Tests done: +# - Check that slaves reports correct failures if master.info has strange +# modes/information +# - Automatic binary log rotation +# - Ensure that temporary tables works over flush logs and binary log +# changes +# - Test creating a duplicate key error and recover from it + +# Requires statement logging +-- source include/have_binlog_format_mixed_or_statement.inc + +connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); +connect (slave,localhost,root,,test,$SLAVE_MYPORT,$SLAVE_MYSOCK); + +# Create empty file +let $MYSQLD_SLAVE_DATADIR= `select @@datadir`; +write_file $MYSQLD_SLAVE_DATADIR/master.info; +EOF +chmod 0000 $MYSQLD_SLAVE_DATADIR/master.info; +connection slave; + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); +# START SLAVE will fail because it can't read the file (mode 000) +# (system error 13) +--replace_result $MYSQL_TEST_DIR TESTDIR +--error 1105,1105,29 +start slave; +chmod 0600 $MYSQLD_SLAVE_DATADIR/master.info; +# It will fail again because the file is empty so the slave cannot get valuable +# info about how to connect to the master from it (failure in +# init_strvar_from_file() in init_master_info()). +--error 1201 +start slave; +--replace_result $MASTER_MYPORT MASTER_PORT + +# CHANGE MASTER will fail because it first parses master.info before changing +# it (so when master.info is bad, people have to use RESET SLAVE first). +--error 1201 +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; +reset slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; +connection master; +reset master; +connection slave; +start slave; +--source include/wait_for_slave_to_start.inc +connection master; + +# +# Test FLUSH LOGS +# +create temporary table temp_table (a char(80) not null); +insert into temp_table values ("testing temporary tables"); +create table t1 (s text); +insert into t1 values('Could not break slave'),('Tried hard'); +sync_slave_with_master; +let $status_items= Master_Log_File, Relay_Master_Log_File; +source include/show_slave_status.inc; +source include/check_slave_is_running.inc; +select * from t1; +connection master; +flush logs; +create table t2(m int not null auto_increment primary key); +insert into t2 values (34),(67),(123); +flush logs; +source include/show_binary_logs.inc; +create table t3 select * from temp_table; + +sync_slave_with_master; + +select * from t3; +connection master; +drop table temp_table, t3; + +# +# Now lets make some duplicate key mess and see if we can recover from it +# + +# First insert a value on the slave +connection slave; +insert into t2 values(1234); + +#same value on the master +connection master; +set insert_id=1234; +insert into t2 values(NULL); +connection slave; +# 1062 = ER_DUP_ENTRY +call mtr.add_suppression("Slave SQL.*Error .Duplicate entry .1234. for key .PRIMARY.. on query.* error.* 1062"); +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error_and_skip.inc + +connection master; + +#let slave catch up +sync_slave_with_master; +connection master; +purge master logs to 'master-bin.000002'; +source include/show_master_logs.inc; +# we just tests if synonyms are accepted +purge binary logs to 'master-bin.000002'; +source include/show_binary_logs.inc; +--source include/wait_for_binlog_checkpoint.inc + +# Set the purge time 1 second after the last modify time of master-bin.000002. +perl; +open F, ">>".$ENV{'MYSQLTEST_VARDIR'}.'/tmp/rpl_rotate_logs.tmp' or die "Tmp file rpl_rotate_logs.tmp not found"; +my $binlogpath = $ENV{'MYSQLTEST_VARDIR'}.'/mysqld.1/data/master-bin.000002'; +my @array = stat($binlogpath); +my $filemodifytime = $array[9]; +my @t = localtime $filemodifytime; +my $modifytime = sprintf "%04u-%02u-%02u %02u:%02u:%02u",$t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0]; +printf F ("let \$tmpval = %s;",$modifytime); +close F; +EOF + +--source $MYSQLTEST_VARDIR/tmp/rpl_rotate_logs.tmp +remove_file $MYSQLTEST_VARDIR/tmp/rpl_rotate_logs.tmp; + +--disable_result_log +--replace_result $tmpval tmpval +--eval SELECT @time_for_purge:=DATE_ADD('$tmpval', INTERVAL 1 SECOND) +--enable_result_log + +purge master logs before (@time_for_purge); +source include/show_binary_logs.inc; +insert into t2 values (65); +sync_slave_with_master; +source include/show_slave_status.inc; +source include/check_slave_is_running.inc; +select * from t2; + +# +# Test forcing the replication log to rotate +# + +connection master; +create temporary table temp_table (a char(80) not null); +insert into temp_table values ("testing temporary tables part 2"); + +# the nummber of produced logs is sensitive to whether checksum is NONE or CRC32 +# the value of 103 makes it even +let $1=103; + +create table t3 (n int); +disable_query_log; +while ($1) +{ +#eval means expand $ expressions + eval insert HIGH_PRIORITY into t3 values($1 + 4); + dec $1; +} +enable_query_log; +select count(*) from t3 where n >= 4; +create table t4 select * from temp_table; +source include/show_binary_logs.inc; +source include/show_master_status.inc; +sync_slave_with_master; +select * from t4; + +source include/show_slave_status.inc; +source include/check_slave_is_running.inc; +# because of concurrent insert, the table may not be up to date +# if we do not lock +lock tables t3 read; +select count(*) from t3 where n >= 4; +unlock tables; +#clean up +connection master; +drop table if exists t1,t2,t3,t4; +drop temporary table temp_table; +sync_slave_with_master; + +--echo End of 4.1 tests + +# +# Bug #29420: crash with show and purge binlogs +# +--error 1220 +show binlog events in 'non existing_binlog_file'; +purge master logs before now(); +--error 1220 +show binlog events in ''; +purge master logs before now(); + +--echo End of 5.0 tests +--echo #cleanup + +--remove_file $MYSQLD_SLAVE_DATADIR/master.info +--source include/stop_slave.inc +reset slave all; diff --git a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt new file mode 100644 index 00000000..f71317fc --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock-master.opt @@ -0,0 +1 @@ +--max-binlog-size=4k --expire-logs-days=1 diff --git a/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test new file mode 100644 index 00000000..6db4e2be --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_rotate_purge_deadlock.test @@ -0,0 +1,96 @@ +# +# Bug#11763573 - 56299: MUTEX DEADLOCK WITH COM_BINLOG_DUMP, BINLOG PURGE, AND PROCESSLIST/KILL +# +source include/have_debug_sync.inc; +source include/have_binlog_format_row.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +# +# Testing that execution of two concurrent INSERTing connections both +# triggering the binlog rotation is correct even though their execution +# is interleaved. +# The test makes the first connection to complete the rotation part +# and yields control to the second connection that rotates as well and +# gets first on purging. And the fact of interleaving does not create +# any issue. +# + +connection master; +source include/show_binary_logs.inc; +create table t1 (f text) engine=innodb; +SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; +send insert into t1 set f=repeat('a', 4096); + +connection master1; + +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE like "debug sync point: at_purge_logs_before_date%"; +--source include/wait_condition.inc + +--echo *** there must be two logs in the list *** +source include/show_binary_logs.inc; + +insert into t1 set f=repeat('b', 4096); + +--echo *** there must be three logs in the list *** +source include/show_binary_logs.inc; + +SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; +SET DEBUG_SYNC = 'RESET'; + +# the first connection finally completes its INSERT +connection master; +reap; +SET DEBUG_SYNC = 'RESET'; + +sync_slave_with_master; + + +# +# Testing the reported deadlock involving DUMP, KILL and INSERT threads +# + +connection master; +SET DEBUG_SYNC = 'at_purge_logs_before_date WAIT_FOR rotated'; +SET DEBUG_SYNC = 'after_purge_logs_before_date SIGNAL continued'; +send insert into t1 set f=repeat('b', 4096); + +connection master1; + +# make sure INSERT reaches waiting point +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE like "debug sync point: at_purge_logs_before_date%"; +--source include/wait_condition.inc + +# find and kill DUMP thread +let $_tid= `select id from information_schema.processlist where command = 'Binlog Dump' limit 1`; +--disable_query_log +eval kill query $_tid; +--enable_query_log + +# +# Now the proof is that the new DUMP thread has executed +# a critical section of the deadlock without any regression and is UP +# +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE command = 'Binlog Dump' and STATE like "Master has sent all binlog to slave%"; +--source include/wait_condition.inc + +SET DEBUG_SYNC = 'now SIGNAL rotated'; +SET DEBUG_SYNC = 'now WAIT_FOR continued'; +SET DEBUG_SYNC = 'RESET'; + +connection master; +reap; +SET DEBUG_SYNC = 'RESET'; +drop table t1; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_001.test b/mysql-test/suite/rpl/t/rpl_row_001.test new file mode 100644 index 00000000..f66c61ff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_001.test @@ -0,0 +1,51 @@ +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# Test if the slave SQL thread can be more than 16K behind the slave +# I/O thread (> IO_SIZE) + +# we'll use table-level locking to delay slave SQL thread +eval CREATE TABLE t1 (n INT); +sync_slave_with_master; +connection master; +RESET MASTER; +connection slave; +STOP SLAVE; +RESET SLAVE; + +connection master; +let $1=5000; +# Generate 16K of relay log +disable_query_log; +while ($1) +{ + eval INSERT INTO t1 VALUES($1); + dec $1; +} +enable_query_log; +SELECT COUNT(*) FROM t1; +save_master_pos; + +# Try to cause a large relay log lag on the slave by locking t1 +connection slave; +LOCK TABLES t1 READ; +START SLAVE; +UNLOCK TABLES; +sync_with_master; +SELECT COUNT(*) FROM t1; + +connection master; +DROP TABLE t1; +CREATE TABLE t1 (n INT); +INSERT INTO t1 VALUES(3456); +sync_slave_with_master; +SELECT n FROM t1; + +connection master; +DROP TABLE t1; + +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt b/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt new file mode 100644 index 00000000..3073fa4f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_4_bytes-master.opt @@ -0,0 +1,2 @@ +--loose-debug=d,"old_row_based_repl_4_byte_map_id_master" +--log-bin-use-v1-row-events=1 diff --git a/mysql-test/suite/rpl/t/rpl_row_4_bytes.test b/mysql-test/suite/rpl/t/rpl_row_4_bytes.test new file mode 100644 index 00000000..6130f749 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_4_bytes.test @@ -0,0 +1,34 @@ +# This test is to make sure that slaves can read a binlog containining +# table map ids stored in 4 bytes, even though we now store them in 6 +# bytes. This is for backward-compatibility. +# If the slave does not detect that the master stores the table map id +# in 4 bytes, slave will read 6 bytes, and so will read the 2 bytes of +# flags at the place where there actually is data, so the test should +# fail. + +-- source include/have_binlog_format_row.inc +-- source include/have_debug.inc +-- source include/master-slave.inc + +connection master; +--disable_warnings +drop database if exists mysqltest1; +create database mysqltest1; +--enable_warnings +use mysqltest1; +CREATE TABLE t1 (a char(3)); +CREATE TABLE t2 (a char(3)); +insert into t1 values("ANN"); +insert into t1 values("GUI"); +insert into t2 values("LIL"); +insert into t2 values("ABE"); +insert into t2 values("ANG"); +sync_slave_with_master; +use mysqltest1; +select * from t1 order by a; +select * from t2 order by a; + +connection master; +DROP DATABASE mysqltest1; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_NOW.test b/mysql-test/suite/rpl/t/rpl_row_NOW.test new file mode 100644 index 00000000..d732c6e6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_NOW.test @@ -0,0 +1,75 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +# Updated 08/30/2005 Added dumps and diff # +############################################################################# +#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=12480 # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +create database if not exists mysqltest1; +DROP TABLE IF EXISTS mysqltest1.t1; +--enable_warnings + + +# Begin test section 1 +CREATE TABLE mysqltest1.t1 (n MEDIUMINT NOT NULL AUTO_INCREMENT, + a TIMESTAMP DEFAULT '2005-05-05 01:01:01', + b TIMESTAMP DEFAULT '2005-05-05 01:01:01', + PRIMARY KEY(n)); +delimiter |; +CREATE FUNCTION mysqltest1.f1() RETURNS TIMESTAMP +BEGIN + DECLARE v1 INT DEFAULT 300; + WHILE v1 > 0 DO + SET v1 = v1 - 1; + END WHILE; + RETURN NOW(); +END| +delimiter ;| + +INSERT INTO mysqltest1.t1 VALUES(NULL,NOW(),mysqltest1.f1()); + +delimiter |; +CREATE TRIGGER mysqltest1.trig1 BEFORE INSERT ON mysqltest1.t1 +FOR EACH ROW BEGIN + SET new.b = mysqltest1.f1(); +END| +delimiter ;| + +INSERT INTO mysqltest1.t1 SET n = NULL, a = now(); + +sync_slave_with_master; + +connection master; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/NOW_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/NOW_slave.sql + +# lets cleanup +DROP TABLE IF EXISTS mysqltest1.t1; +DROP FUNCTION mysqltest1.f1; +DROP DATABASE mysqltest1; + +# Lets compare. Note: If they match test will pass, if they do not match +# the test will show that the diff statement failed and not reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching :-) The failed dump +# files will be located in $MYSQLTEST_VARDIR/tmp + +diff_files $MYSQLTEST_VARDIR/tmp/NOW_master.sql $MYSQLTEST_VARDIR/tmp/NOW_slave.sql; + +# If all is good, when can cleanup our dump files. +--remove_file $MYSQLTEST_VARDIR/tmp/NOW_master.sql +--remove_file $MYSQLTEST_VARDIR/tmp/NOW_slave.sql + +sync_slave_with_master; +# End of 5.1 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_USER.test b/mysql-test/suite/rpl/t/rpl_row_USER.test new file mode 100644 index 00000000..405f609f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_USER.test @@ -0,0 +1,59 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +############################################################################# +# TEST: To test the USER() and CURRENT_USER() in rbr # +############################################################################# +# Change Author: JBM +# Change Date: 2006-01-16 +########## + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +set local sql_mode=""; + +# Begin clean up test section +connection master; +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +CREATE DATABASE mysqltest1; +--enable_warnings + +# Section 1 test +CREATE USER tester IDENTIFIED BY 'test'; +GRANT ALL ON mysqltest1.* TO 'tester'@'%' IDENTIFIED BY 'test'; +GRANT ALL ON mysqltest1.* TO ''@'localhost%'; +FLUSH PRIVILEGES; +connect (m_1,localhost,tester,,mysqltest1); + +connection m_1; +CREATE TABLE mysqltest1.t1 (a INT, users VARCHAR(255), PRIMARY KEY(a)); +INSERT INTO mysqltest1.t1 VALUES(1,USER()); +INSERT INTO mysqltest1.t1 VALUES(2,CURRENT_USER()); +delimiter |; +create procedure mysqltest1.p1() +begin + INSERT INTO mysqltest1.t1 VALUES(3,USER()); + INSERT INTO mysqltest1.t1 VALUES(4,CURRENT_USER()); +end| +delimiter ;| + +CALL mysqltest1.p1(); +connection master; +SELECT * FROM mysqltest1.t1 ORDER BY a; +--sync_slave_with_master +SELECT * FROM mysqltest1.t1 ORDER BY a; + +connection master; +# Lets cleanup + +DROP DATABASE mysqltest1; +REVOKE ALL ON mysqltest1.* FROM 'tester'@'%'; +REVOKE ALL ON mysqltest1.* FROM ''@'localhost%'; +DROP USER tester@'%'; +DROP USER ''@'localhost%'; +FLUSH PRIVILEGES; +--sync_slave_with_master +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_UUID.test b/mysql-test/suite/rpl/t/rpl_row_UUID.test new file mode 100644 index 00000000..8e1aa6d2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_UUID.test @@ -0,0 +1,8 @@ +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=myisam; +--source include/rpl_row_UUID.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt new file mode 100644 index 00000000..18de9bd1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do-slave.opt @@ -0,0 +1 @@ +--log-slave-updates --replicate-annotate-row-events --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2 diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_do.test b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test new file mode 100644 index 00000000..ffaae314 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_annotate_do.test @@ -0,0 +1,16 @@ +############################################################################### +# WL47: Store in binlog text of statements that caused RBR events +# Wrapper for extra/rpl/rpl_row_annotate.test. +# Intended to test that if the --replicate-annotate-row-events option +# is switched on on slave then Annotate_events: +# - are reproduced on slave +# - are reproduced only once for "multi-table-maps" rbr queries +# - are not reproduced when the corresponding queries are filtered away +# on replication +# - are reproduced when the corresponding queries are filtered away partialy +# (e.g. in case of multi-delete) +# - are not generated on slave for queries that are not annotated on master. +############################################################################### + +--source include/have_binlog_format_row.inc +--source include/rpl_row_annotate.test diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt new file mode 100644 index 00000000..feef43f7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont-slave.opt @@ -0,0 +1 @@ +--log-slave-updates --skip-replicate-annotate-row-events --replicate-ignore-table=test1.xt1 --replicate-ignore-table=test1.xt2 diff --git a/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test new file mode 100644 index 00000000..24dd2a1c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_annotate_dont.test @@ -0,0 +1,9 @@ +############################################################################### +# WL47: Store in binlog text of statements that caused RBR events +# Wrapper for extra/rpl/rpl_row_annotate.test. +# Intended to test that if the --replicate-annotate-row-events option +# is switched off on slave then Annotate_events are not reproduced. +############################################################################### + +--source include/have_binlog_format_row.inc +--source include/rpl_row_annotate.test diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt new file mode 100644 index 00000000..bd772813 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs-master.opt @@ -0,0 +1,2 @@ +--binlog_ignore_db=test_ignore --default-storage-engine=MyISAM + diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test new file mode 100644 index 00000000..b875b97d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test @@ -0,0 +1,242 @@ +-- source include/have_query_cache.inc +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc + +let $SERVER_VERSION=`select version()`; + +--source include/master-slave.inc + +# Add suppression for expected warning(s) in slaves error log +call mtr.add_suppression("Can't find record in 't.'"); + +# Bug#15942 (RBR ignores --binlog_ignore_db and tries to map to table +# on slave for writes) + +CREATE DATABASE test_ignore; # --binlog_ignore_db=mysqltest_ignore + +SHOW DATABASES; +USE test; +CREATE TABLE t1 (a INT, b INT); +SHOW TABLES; +INSERT INTO t1 VALUES (1,1), (2,2); +USE test_ignore; +CREATE TABLE t2 (a INT, b INT); +SHOW TABLES; +INSERT INTO t2 VALUES (3,3), (4,4); +source include/show_binlog_events.inc; +sync_slave_with_master; +SHOW DATABASES; +USE test; +SHOW TABLES; +--error 1049 +USE test_ignore; + +connection master; +DROP DATABASE test_ignore; +USE test; +DROP TABLE t1; +sync_slave_with_master; +USE test; + + +# Bug#19995: Extreneous table maps generated for statements that does +# not generate rows +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t1 (a INT); +DELETE FROM t1; +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a = 0; +UPDATE t1 SET a=99 WHERE a = 0; +source include/show_binlog_events.inc; + +DROP TABLE t1; +--sync_slave_with_master + +# BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on +# slave +--echo ================ Test for BUG#17620 ================ +--source include/rpl_reset.inc + +connection slave; +SET GLOBAL QUERY_CACHE_SIZE=0; +call mtr.add_suppression("Slave SQL.*Could not execute Update_rows event on table test.t1.* error.* 1032"); + +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); + +sync_slave_with_master; +SET GLOBAL QUERY_CACHE_SIZE=16*1024*1024; + +connection master; +INSERT INTO t1 VALUES (4),(5),(6); + +sync_slave_with_master; +SELECT * FROM t1; + +connection master; +INSERT INTO t1 VALUES (7),(8),(9); + +sync_slave_with_master; +SELECT * FROM t1; + +SET GLOBAL QUERY_CACHE_SIZE=default; +--connection master +DROP TABLE t1; + + +# Bug#22550: Replication of BIT columns failing +--echo ================ Test for BUG#22550 ================ +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t1 (a BIT(1), b INT) ENGINE=MYISAM; +sync_slave_with_master; + +connection master; +INSERT INTO t1 VALUES(1,2); +SELECT HEX(a),b FROM t1; +sync_slave_with_master; +SELECT HEX(a),b FROM t1; + +connection master; +UPDATE t1 SET a=0 WHERE b=2; +SELECT HEX(a),b FROM t1; +sync_slave_with_master; +SELECT HEX(a),b FROM t1; + +connection master; +DROP TABLE IF EXISTS t1; +sync_slave_with_master; + +# BUG#22583: RBR between MyISAM and non-MyISAM tables containing a BIT +# field does not work + +--echo ================ Test for BUG#22583 ================ +--source include/rpl_reset.inc + +# disabling warnings temporarily for ENGINE=INNODB to work without InnoDB +--disable_warnings +connection master; +CREATE TABLE t1_myisam (k INT, a BIT(1), b BIT(9)) ENGINE=MYISAM; +CREATE TABLE t1_innodb (k INT, a BIT(1), b BIT(9)) ENGINE=INNODB; +CREATE TABLE t2_myisam (k INT, a BIT(1) NOT NULL, b BIT(4) NOT NULL) ENGINE=MYISAM; +CREATE TABLE t2_innodb (k INT, a BIT(1) NOT NULL, b BIT(4) NOT NULL) ENGINE=INNODB; +sync_slave_with_master; +ALTER TABLE t1_myisam ENGINE=INNODB; +ALTER TABLE t1_innodb ENGINE=MYISAM; +ALTER TABLE t2_myisam ENGINE=INNODB; +ALTER TABLE t2_innodb ENGINE=MYISAM; +--enable_warnings + +connection master; +INSERT INTO t1_myisam VALUES(1, b'0', 257); +INSERT INTO t1_myisam VALUES(2, b'1', 256); +INSERT INTO t1_innodb VALUES(1, b'0', 257); +INSERT INTO t1_innodb VALUES(2, b'1', 256); +SELECT k, HEX(a),HEX(b) FROM t1_myisam; +SELECT k, HEX(a),HEX(b) FROM t1_innodb; +INSERT INTO t2_myisam VALUES(1, b'0', 9); +INSERT INTO t2_myisam VALUES(2, b'1', 8); +INSERT INTO t2_innodb VALUES(1, b'0', 9); +INSERT INTO t2_innodb VALUES(2, b'1', 8); +SELECT k, HEX(a),HEX(b) FROM t2_myisam; +SELECT k, HEX(a),HEX(b) FROM t2_innodb; +sync_slave_with_master; +SELECT k, HEX(a),HEX(b) FROM t1_myisam; +SELECT k, HEX(a),HEX(b) FROM t1_innodb; +SELECT k, HEX(a),HEX(b) FROM t2_myisam; +SELECT k, HEX(a),HEX(b) FROM t2_innodb; + +connection master; +UPDATE t1_myisam SET a=0 WHERE k=2; +SELECT k, HEX(a),HEX(b) FROM t1_myisam; +UPDATE t1_innodb SET a=0 WHERE k=2; +SELECT k, HEX(a),HEX(b) FROM t1_innodb; +UPDATE t2_myisam SET a=0 WHERE k=2; +SELECT k, HEX(a),HEX(b) FROM t2_myisam; +UPDATE t2_innodb SET a=0 WHERE k=2; +SELECT k, HEX(a),HEX(b) FROM t2_innodb; +sync_slave_with_master; +SELECT k, HEX(a),HEX(b) FROM t1_myisam; +SELECT k, HEX(a),HEX(b) FROM t1_innodb; +SELECT k, HEX(a),HEX(b) FROM t2_myisam; +SELECT k, HEX(a),HEX(b) FROM t2_innodb; + +connection master; +DROP TABLE IF EXISTS t1_myisam, t1_innodb, t2_myisam, t2_innodb; +sync_slave_with_master; + +# +# Bug#27716 multi-update did partially and has not binlogged +# + +connection master; + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings +CREATE TABLE `t1` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; + +CREATE TABLE `t2` ( + `a` int(11) NOT NULL auto_increment, + `b` int(11) default NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; + +# testing multi_update::send_error() effective update +insert into t1 values (1,1),(2,2); +insert into t2 values (1,1),(4,4); + +connection master; +error ER_DUP_ENTRY; +UPDATE t2,t1 SET t2.a=t1.a+2; +select * from t2 /* must be (3,1), (4,4) */; +sync_slave_with_master; + +connection slave; +select * from t2 /* must be (3,1), (4,4) */; + +connection master; +drop table t1,t2; + +sync_slave_with_master; + +# +# BUG#31702: Missing row on slave causes assertion failure under +# row-based replication +# + +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY, b SET('master','slave')); +INSERT INTO t1 VALUES (1,'master,slave'), (2,'master,slave'); +sync_slave_with_master; +UPDATE t1 SET a = 5, b = 'slave' WHERE a = 1; +SELECT * FROM t1 ORDER BY a; +# since bug#31552/31609 idempotency is not default any longer. In +# order for the preceding test UPDATE t1 to pass, the mode is switched +# temprorarily +set @@global.slave_exec_mode= 'IDEMPOTENT'; +connection master; +UPDATE t1 SET a = 5, b = 'master' WHERE a = 1; +SELECT * FROM t1 ORDER BY a; +sync_slave_with_master; +set @@global.slave_exec_mode= default; +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +SELECT * FROM t1 ORDER BY a; + +connection master; +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test b/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test new file mode 100644 index 00000000..f1e836c6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_basic_2myisam.test @@ -0,0 +1,11 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +let $type= 'MYISAM' ; +let $extra_index= ; +-- source include/rpl_row_basic.test + +connection slave; +call mtr.add_suppression("Can't find record in 't1'"); + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test b/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test new file mode 100644 index 00000000..b84a4c13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_basic_3innodb.test @@ -0,0 +1,11 @@ +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +connection slave; +let $bit_field_special = ALL_LOSSY; +let $type= 'INNODB' ; +let $extra_index= ; +-- source include/rpl_row_basic.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test b/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test new file mode 100644 index 00000000..7a477056 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_basic_8partition.test @@ -0,0 +1,190 @@ +############################################################ +# Author: MATZ # +# Date: 2006-03-22 # +# Purpose: See if replication of partition tables work # +# Most of this test is copied from the rpl_xxx2yyy tests, # +# but here we just test some simple basic replication of # +# partition tables with same engine (MyISAM) in both ends. # +############################################################ + +--source include/have_binlog_format_row.inc +--source include/have_partition.inc +--source include/master-slave.inc +connection master; +--disable_warnings +DROP TABLE IF EXISTS t1; + +SET @@BINLOG_FORMAT = ROW; + +--echo **** Partition RANGE testing **** + +# Create table that is partitioned by range on year i.e. year(t) and +# replicate basice operations such at insert, update delete between 2 +# different storage engines Alter table and ensure table is handled +# Correctly on the slave +# Note that the storage engine should not be explicit: the default +# storage engine is used on master and slave. + +CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255), + bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, + f FLOAT DEFAULT 0, total BIGINT UNSIGNED, + y YEAR, t DATE) + PARTITION BY RANGE (YEAR(t)) + (PARTITION p0 VALUES LESS THAN (1901), + PARTITION p1 VALUES LESS THAN (1946), + PARTITION p2 VALUES LESS THAN (1966), + PARTITION p3 VALUES LESS THAN (1986), + PARTITION p4 VALUES LESS THAN (2005), + PARTITION p5 VALUES LESS THAN MAXVALUE); + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +connection master; +# Check that simple Alter statements are replicated correctly +ALTER TABLE t1 MODIFY vc TEXT; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +# Perform basic operation on master and ensure replicated correctly +--source include/rpl_multi_engine3.inc + +connection master; +DROP TABLE IF EXISTS t1; + +######################################################## + +--echo **** Partition LIST testing **** + +# Create table that is partitioned by list on id i.e. (2,4). Pretend +# that we missed one and alter to add. Then replicate basice +# operations such at insert, update delete between 2 different storage +# engines Alter table and ensure table is handled Correctly on the +# slave. + + +CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255), + bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, + f FLOAT DEFAULT 0, total BIGINT UNSIGNED, + y YEAR, t DATE) + PARTITION BY LIST(id) + (PARTITION p0 VALUES IN (2, 4), + PARTITION p1 VALUES IN (42, 142), + PARTITION p2 VALUES IN (412)); + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +# Perform basic operation on master and ensure replicated correctly +--source include/rpl_multi_engine3.inc + +connection master; +# Check that simple Alter statements are replicated correctly --- +ALTER TABLE t1 MODIFY vc TEXT; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +# Perform basic operation on master and ensure replicated correctly +--source include/rpl_multi_engine3.inc + +connection master; +DROP TABLE IF EXISTS t1; + +######################################################## + +--echo **** Partition HASH testing **** + +# Create table that is partitioned by hash on year i.e. YEAR(t). Then +# replicate basice operations such at insert, update delete between 2 +# different storage engines Alter table and ensure table is handled +# Correctly on the slave + +CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255), + bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, + f FLOAT DEFAULT 0, total BIGINT UNSIGNED, + y YEAR, t DATE) + PARTITION BY HASH( YEAR(t) ) + PARTITIONS 4; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +# Check that simple Alter statements are replicated correctly +ALTER TABLE t1 MODIFY vc TEXT; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +connection master; +DROP TABLE IF EXISTS t1; + +######################################################## + +# This part does not work +--echo **** Partition by KEY **** + +# Create table that is partitioned by key on id with 4 parts. Then +# replicate basice operations such at insert, update delete between 2 +# different storage engines Alter table and ensure table is handled +# Correctly on the slave + +CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc VARCHAR(255), + bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, + f FLOAT DEFAULT 0, total BIGINT UNSIGNED, + y YEAR, t DATE,PRIMARY KEY(id)) + PARTITION BY KEY() + PARTITIONS 4; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +connection master; +# Check that simple Alter statements are replicated correctly +ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(id, total); + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +connection master; +# Check that simple Alter statements are replicated correctly +ALTER TABLE t1 MODIFY vc TEXT; + +SHOW CREATE TABLE t1; + +sync_slave_with_master; +SHOW CREATE TABLE t1; + +--source include/rpl_multi_engine3.inc + +DROP TABLE IF EXISTS t1; + +# End of 5.1 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt b/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt new file mode 100644 index 00000000..7c3d2411 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id.opt @@ -0,0 +1 @@ +--verbose=1 diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id.test b/mysql-test/suite/rpl/t/rpl_row_big_table_id.test new file mode 100644 index 00000000..4bfdceef --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id.test @@ -0,0 +1,57 @@ +################################################################## +# rpl_row_big_table_id +# +# MDEV-17803 Row-based event is not applied when +# table map id is greater 32 bit int +# +# This test is depending on that the server was restarted before test was run +# +# Verify row-based events applying when table map id value is about and greater +# than 1 << 32. +################################################################## +--source include/word_size.inc +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +SET @old_debug_dbug= @@debug_dbug; +SET @@debug_dbug="+d,simulate_big_table_id"; +CREATE TABLE t (a int); + +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +INSERT INTO t SET a= 0; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 1; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 2; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 3; + +# display simulated big table_id +--let $_in_from=in '$binlog_file' from $binlog_pos +--replace_result "$_in_from" "in <file> from <pos>" +--replace_column 2 # 5 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ +--eval show binlog events in '$binlog_file' from $binlog_pos + + +--sync_slave_with_master + +if (`SELECT sum(a) != 6 FROM t`) +{ + --echo *** unexpected result; check slave applier *** + --die +} + + +# Cleanup + +--connection master +SET debug_dbug=@old_debug_dbug; + +DROP TABLE t; + +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test new file mode 100644 index 00000000..a4db32cf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_binlog_max_cache_size.test @@ -0,0 +1,8 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--source include/rpl_binlog_max_cache_size.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test b/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test new file mode 100644 index 00000000..57f3e91a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_blob_innodb.test @@ -0,0 +1,13 @@ +################################# +# Wrapper for rpl_row_blob.test# +################################# +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=InnoDB; +-- source include/rpl_row_blob.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test b/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test new file mode 100644 index 00000000..246d38f4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_blob_myisam.test @@ -0,0 +1,12 @@ +################################# +# Wrapper for rpl_row_blob.test# +################################# +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=myisam; +-- source include/rpl_row_blob.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_colSize.test b/mysql-test/suite/rpl/t/rpl_row_colSize.test new file mode 100644 index 00000000..21c68b55 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_colSize.test @@ -0,0 +1,173 @@ +################################################################## +# rpl_colSize # +# # +# This test is designed to test the changes included in WL#3228. # +# The changes include the ability to replicate with the master # +# having columns that are smaller (shorter) than the slave. # +################################################################## + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + + +--echo **** Testing WL#3228 changes. **** +--echo *** Create "wider" table on slave *** +sync_slave_with_master; + +# +# Check each column type to verify error 1532 fires (BUG#22086) +# This check covers only those fields that require additional +# metadata from the master to be replicated to the slave. These +# field types are: +# MYSQL_TYPE_NEWDECIMAL: +# MYSQL_TYPE_FLOAT: +# MYSQL_TYPE_BIT: +# MYSQL_TYPE_SET: +# MYSQL_TYPE_STRING: +# MYSQL_TYPE_ENUM: +# MYSQL_TYPE_VARCHAR: +# MYSQL_TYPE_BLOB: + +# +# Test: Checking MYSQL_TYPE_NEWDECIMAL fields +# +--echo Checking MYSQL_TYPE_NEWDECIMAL fields +let $test_table_master = CREATE TABLE t1 (a DECIMAL(20, 10)); +let $test_table_slave = CREATE TABLE t1 (a DECIMAL(5,2)); +let $test_insert = INSERT INTO t1 VALUES (901251.90125); +source include/test_fieldsize.inc; + +let $test_table_master = CREATE TABLE t1 (a DECIMAL(27, 18)); +let $test_table_slave = CREATE TABLE t1 (a DECIMAL(27, 9)); +let $test_insert = INSERT INTO t1 VALUES (901251.90125); +source include/test_fieldsize.inc; + +let $test_table_master = CREATE TABLE t1 (a NUMERIC(20, 10)); +let $test_table_slave = CREATE TABLE t1 (a NUMERIC(5,2)); +let $test_insert = INSERT INTO t1 VALUES (901251.90125); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_FLOAT fields +# +--echo Checking MYSQL_TYPE_FLOAT fields +let $test_table_master = CREATE TABLE t1 (a FLOAT(47)); +let $test_table_slave = CREATE TABLE t1 (a FLOAT(20)); +let $test_insert = INSERT INTO t1 VALUES (901251.90125); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_BIT fields +# +--echo Checking MYSQL_TYPE_BIT fields +let $test_table_master = CREATE TABLE t1 (a BIT(64)); +let $test_table_slave = CREATE TABLE t1 (a BIT(5)); +let $test_insert = INSERT INTO t1 VALUES (B'10101'); +source include/test_fieldsize.inc; + +let $test_table_master = CREATE TABLE t1 (a BIT(12)); +let $test_table_slave = CREATE TABLE t1 (a BIT(11)); +let $test_insert = INSERT INTO t1 VALUES (B'10101'); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_SET fields +# +--echo Checking MYSQL_TYPE_SET fields +let $test_table_master = CREATE TABLE t1 (a SET('1','2','3','4','5','6','7','8','9')); +let $test_table_slave = CREATE TABLE t1 (a SET('4')); +let $test_insert = INSERT INTO t1 VALUES ('4'); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_STRING fields +# +--echo Checking MYSQL_TYPE_STRING fields +let $test_table_master = CREATE TABLE t1 (a CHAR(20)); +let $test_table_slave = CREATE TABLE t1 (a CHAR(10)); +let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_ENUM fields +# +--echo Checking MYSQL_TYPE_ENUM fields +let $test_table_master = CREATE TABLE t1 (a ENUM( + '01','02','03','04','05','06','07','08','09', + '11','12','13','14','15','16','17','18','19', + '21','22','23','24','25','26','27','28','29', + '31','32','33','34','35','36','37','38','39', + '41','42','43','44','45','46','47','48','49', + '51','52','53','54','55','56','57','58','59', + '61','62','63','64','65','66','67','68','69', + '71','72','73','74','75','76','77','78','79', + '81','82','83','84','85','86','87','88','89', + '91','92','93','94','95','96','97','98','99', + '101','102','103','104','105','106','107','108','109', + '111','112','113','114','115','116','117','118','119', + '121','122','123','124','125','126','127','128','129', + '131','132','133','134','135','136','137','138','139', + '141','142','143','144','145','146','147','148','149', + '151','152','153','154','155','156','157','158','159', + '161','162','163','164','165','166','167','168','169', + '171','172','173','174','175','176','177','178','179', + '181','182','183','184','185','186','187','188','189', + '191','192','193','194','195','196','197','198','199', + '201','202','203','204','205','206','207','208','209', + '211','212','213','214','215','216','217','218','219', + '221','222','223','224','225','226','227','228','229', + '231','232','233','234','235','236','237','238','239', + '241','242','243','244','245','246','247','248','249', + '251','252','253','254','255','256','257','258','259', + '261','262','263','264','265','266','267','268','269', + '271','272','273','274','275','276','277','278','279', + '281','282','283','284','285','286','287','288','289', + '291','292','293','294','295','296','297','298','299' + )); +let $test_table_slave = CREATE TABLE t1 (a ENUM('44','54')); +let $test_insert = INSERT INTO t1 VALUES ('44'); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_VARCHAR fields +# +--echo Checking MYSQL_TYPE_VARCHAR fields +let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000)); +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(100)); +let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); +source include/test_fieldsize.inc; + +let $test_table_master = CREATE TABLE t1 (a VARCHAR(200)); +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(10)); +let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); +source include/test_fieldsize.inc; + +let $test_table_master = CREATE TABLE t1 (a VARCHAR(2000)); +let $test_table_slave = CREATE TABLE t1 (a VARCHAR(1000)); +let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); +source include/test_fieldsize.inc; + +# +# Test: Checking MYSQL_TYPE_BLOB fields +# +--echo Checking MYSQL_TYPE_BLOB fields +let $test_table_master = CREATE TABLE t1 (a LONGBLOB); +let $test_table_slave = CREATE TABLE t1 (a TINYBLOB); +let $test_insert = INSERT INTO t1 VALUES ('This is a test.'); +source include/test_fieldsize.inc; + +connection slave; +call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 0 ...e mismatch.* error.* 1535"); +call mtr.add_suppression("Slave SQL.*Column 0 of table .test.t1. cannot be converted from type.* error.* 1677"); + +--echo *** Cleanup *** +connection master; +DROP TABLE IF EXISTS t1; +sync_slave_with_master; +# END 5.1 Test Case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_conflicts.test b/mysql-test/suite/rpl/t/rpl_row_conflicts.test new file mode 100644 index 00000000..adf37d99 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_conflicts.test @@ -0,0 +1,33 @@ +# See the top of mysql-test/include/rpl_conflicts.test for +# explanation of what this test does. +# +# This test file is for row-logging mode. It runs the test twice, with +# slave_exec_mode=STRICT and slave_exec_mode=IDEMPOTENT, respectively. + +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +connection slave; +call mtr.add_suppression("Slave: Can\'t find record in \'t1\' error.* .*"); +call mtr.add_suppression("Can't find record in 't.'"); + +connection slave; +SET @old_slave_exec_mode= @@global.slave_exec_mode; + + +--echo ######## Run with slave_exec_mode=STRICT ######## + +SET @@global.slave_exec_mode = 'STRICT'; +source include/rpl_conflicts.test; + +--source include/rpl_reset.inc + + +--echo ######## Run with slave_exec_mode=IDEMPOTENT ######## + +set @@global.slave_exec_mode= 'IDEMPOTENT'; +source include/rpl_conflicts.test; + + +SET @@global.slave_exec_mode= @old_slave_exec_mode; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt b/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt new file mode 100644 index 00000000..da199510 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t2_11753004_ign diff --git a/mysql-test/suite/rpl/t/rpl_row_corruption.test b/mysql-test/suite/rpl/t/rpl_row_corruption.test new file mode 100644 index 00000000..d78df905 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_corruption.test @@ -0,0 +1,115 @@ +# +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# BUG#11753004: 44360: REPLICATION FAILED + +## assert that we get an error when checking the +## identifiers at the slave (instead of a crash or +## different table being updated) + +--let $t1= t1_11753004 +--let $t2= t2_11753004 +--let $t2_ign= t2_11753004_ign + +## test #1: assert that we get an error raised when multiple +## tables in the same RBR statement are mapped with the +## same identifier + +--eval CREATE TABLE $t1 (c1 INT) +--eval CREATE TABLE $t2 (c1 INT) +--eval INSERT INTO $t1 VALUES (1) +--eval INSERT INTO $t2 VALUES (2) + +--sync_slave_with_master +call mtr.add_suppression(".*Found table map event mapping table id 0 which was already mapped but with different settings.*"); + +# stop the slave and inject corruption +--source include/stop_slave.inc +SET @saved_debug= @@global.debug_dbug; +SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table"; +--source include/start_slave.inc +--connection master +# both tables get mapped to 0 (in a way, simulating scenario +# originated by BUG#56226) +--eval UPDATE $t1, $t2 SET $t1.c1=3, $t2.c1=4 WHERE $t1.c1=1 OR $t2.c1=2 +--connection slave + +# wait for error 1593 (ER_SLAVE_FATAL_ERROR) +--let $slave_sql_errno=1593 +--source include/wait_for_slave_sql_error.inc +--source include/stop_slave.inc + +# clean up +SET @@global.debug_dbug=@saved_debug; +--source include/start_slave.inc +--connection master +--source include/rpl_reset.inc +--eval DROP TABLE $t1, $t2 +--sync_slave_with_master + +## test #2: assert that ignored tables that may have been mapped +## with the same identifier are skipped, thus no error +## is raised. + +--connection slave +--source include/stop_slave.inc +SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table"; +--source include/start_slave.inc +--source include/rpl_reset.inc +--connection master +--eval CREATE TABLE $t1 (c1 INT) +--eval CREATE TABLE $t2_ign (c1 INT) +--eval INSERT INTO $t1 VALUES (1) +--eval INSERT INTO $t2_ign VALUES (2) +--eval UPDATE $t1, $t2_ign SET $t1.c1=3, $t2_ign.c1=4 WHERE $t1.c1=1 OR $t2_ign.c1=2 + +# must not raise error as second table is filtered +--sync_slave_with_master + + +## test #3: check that BINLOG statements will also raise an +## error if containing table map events mapping different +## tables to same table identifier. + +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +# FD event +BINLOG ' +SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8= +'/*!*/; + +#110708 12:21:44 server id 1 end_log_pos 774 Table_map: `test`.`t1` mapped to number 66 +# at 774 +#110708 12:21:44 server id 1 end_log_pos 815 Table_map: `test`.`t2` mapped to number 67 +# at 815 +#110708 12:21:44 server id 1 end_log_pos 855 Update_rows: table id 66 +# at 855 +#110708 12:21:44 server id 1 end_log_pos 895 Update_rows: table id 67 flags: STMT_END_F +SET @@global.debug_dbug="d,inject_tblmap_same_id_maps_diff_table"; +--error ER_SLAVE_FATAL_ERROR +BINLOG ' +SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE= +SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE= +SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA== +SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA== +'/*!*/; + + +# clean up +DROP TABLE t1,t2; +--connection slave +SET @@global.debug_dbug=@saved_debug; +--connection master +--eval DROP TABLE $t1 +--eval DROP TABLE $t2_ign +--sync_slave_with_master +SET @@global.debug_dbug= @save_debug; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_create_select.test b/mysql-test/suite/rpl/t/rpl_row_create_select.test new file mode 100644 index 00000000..d870b68f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_create_select.test @@ -0,0 +1,30 @@ +# Testing table creations for row-based replication. + +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--echo # +--echo # BUG#17994219: CREATE TABLE .. SELECT PRODUCES INVALID STRUCTURE, +--echo # BREAKS RBR +--echo # + +connection master; +--echo #After the patch, the display width is set to a default +--echo #value of 21. +SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR +CREATE TABLE t1 AS SELECT REPEAT('A', 1000) DIV 1 AS a; +SHOW CREATE TABLE t1; + +SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR +CREATE TABLE t2 AS SELECT CONVERT(REPEAT('A', 255) USING UCS2) DIV 1 AS a; +SHOW CREATE TABLE t2; + +--echo #After the patch, no error is reported. +sync_slave_with_master; + +connection master; +DROP TABLE t1; +DROP TABLE t2; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_row_create_table.test b/mysql-test/suite/rpl/t/rpl_row_create_table.test new file mode 100644 index 00000000..b62955e2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test @@ -0,0 +1,285 @@ +# Testing table creations for row-based replication. + +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc +connection slave; +--source include/have_innodb.inc +connection master; + +# Set the default storage engine to different values on master and +# slave. We need to stop the slave for the server variable to take +# effect, since the variable is only read on start-up. +sync_slave_with_master; +--disable_query_log +set @@default_storage_engine = @@global.default_storage_engine; +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +SET GLOBAL default_storage_engine=memory; +START SLAVE; +--source include/wait_for_slave_to_start.inc +--enable_query_log + +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t1 (a INT); +CREATE OR REPLACE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT, b INT) ENGINE=Merge; +CREATE TABLE t3 (a INT, b INT) CHARSET=utf8; +CREATE TABLE t4 (a INT, b INT) ENGINE=Merge CHARSET=utf8; +--source include/show_binlog_events.inc +--query_vertical SHOW CREATE TABLE t1 +--query_vertical SHOW CREATE TABLE t2 +--query_vertical SHOW CREATE TABLE t3 +sync_slave_with_master; +--query_vertical SHOW CREATE TABLE t1 +--query_vertical SHOW CREATE TABLE t2 +--query_vertical SHOW CREATE TABLE t3 + +connection master; +CREATE TABLE t5 (b INT, c INT) SELECT * FROM t3; + +CREATE TEMPORARY TABLE tt3 (a INT, b INT); +INSERT INTO tt3 VALUES (1,2), (2,4), (3,6), (4,2), (5,10), (6,12); +CREATE TABLE t6 (b INT, c INT) SELECT * FROM tt3; +--query_vertical SHOW CREATE TABLE t5 +SELECT * FROM t5 ORDER BY a,b,c; +--query_vertical SHOW CREATE TABLE t6 +SELECT * FROM t6 ORDER BY a,b,c; +sync_slave_with_master; +--query_vertical SHOW CREATE TABLE t5 +SELECT * FROM t5 ORDER BY a,b,c; +--query_vertical SHOW CREATE TABLE t6 +SELECT * FROM t6 ORDER BY a,b,c; + +--source include/rpl_reset.inc + +connection master; +# Test for erroneous constructions +--error ER_DUP_ENTRY +CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3; +# Shouldn't be written to the binary log +--source include/show_binlog_events.inc + +# Test that INSERT-SELECT works the same way as for SBR. +CREATE TABLE t7 (a INT, b INT UNIQUE); +--error ER_DUP_ENTRY +INSERT INTO t7 SELECT a,b FROM tt3; +SELECT * FROM t7 ORDER BY a,b; +# Should be written to the binary log +--source include/show_binlog_events.inc +sync_slave_with_master; +SELECT * FROM t7 ORDER BY a,b; + +--source include/rpl_reset.inc + +connection master; +CREATE TEMPORARY TABLE tt4 (a INT, b INT); +INSERT INTO tt4 VALUES (4,8), (5,10), (6,12); +BEGIN; +INSERT INTO t7 SELECT a,b FROM tt4; +ROLLBACK; +--source include/show_binlog_events.inc +SELECT * FROM t7 ORDER BY a,b; +sync_slave_with_master; +SELECT * FROM t7 ORDER BY a,b; + +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t8 LIKE t4; +CREATE TABLE t9 LIKE tt4; +CREATE TEMPORARY TABLE tt5 LIKE t4; +CREATE TEMPORARY TABLE tt6 LIKE tt4; +CREATE TEMPORARY TABLE tt7 SELECT 1; +--query_vertical SHOW CREATE TABLE t8 +--query_vertical SHOW CREATE TABLE t9 +--source include/show_binlog_events.inc +sync_slave_with_master; +--query_vertical SHOW CREATE TABLE t8 +--query_vertical SHOW CREATE TABLE t9 + +connection master; +DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9; +sync_slave_with_master; +# Here we reset the value of the default storage engine +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +SET GLOBAL default_storage_engine=@@default_storage_engine; +START SLAVE; +--source include/wait_for_slave_to_start.inc +--enable_ps_protocol + +# BUG#22864 (Rollback following CREATE ... SELECT discards 'CREATE +# table' from log): +--echo ================ BUG#22864 ================ + +--source include/rpl_reset.inc + +connection master; +SET AUTOCOMMIT=0; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); + +CREATE TABLE t2 ENGINE=INNODB SELECT * FROM t1; +ROLLBACK; + +CREATE TABLE t3 ENGINE=INNODB SELECT * FROM t1; +INSERT INTO t3 VALUES (4),(5),(6); +ROLLBACK; + +CREATE TABLE t4 ENGINE=INNODB SELECT * FROM t1; +INSERT INTO t1 VALUES (4),(5),(6); +ROLLBACK; + +SHOW TABLES; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a; +--source include/show_binlog_events.inc +sync_slave_with_master; +SHOW TABLES; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; +SELECT * FROM t4 ORDER BY a; + +connection master; +DROP TABLE IF EXISTS t1,t2,t3,t4; +SET AUTOCOMMIT=1; +sync_slave_with_master; + +# Some tests with temporary tables +--source include/rpl_reset.inc + +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); + +CREATE TABLE t2 (a INT) ENGINE=INNODB; + +BEGIN; +INSERT INTO t2 SELECT a*a FROM t1; +CREATE TEMPORARY TABLE tt1 +SELECT a+1 AS a + FROM t1 + WHERE a MOD 2 = 1; +INSERT INTO t2 SELECT a+2 FROM tt1; +COMMIT; + +SELECT * FROM t2 ORDER BY a; +--source include/show_binlog_events.inc +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + +connection master; +TRUNCATE TABLE t2; +sync_slave_with_master; + +--source include/rpl_reset.inc + +connection master; +BEGIN; +INSERT INTO t2 SELECT a*a FROM t1; +CREATE TEMPORARY TABLE tt2 +SELECT a+1 AS a + FROM t1 + WHERE a MOD 2 = 1; +INSERT INTO t2 SELECT a+2 FROM tt2; +ROLLBACK; + +SELECT * FROM t2 ORDER BY a; +source include/show_binlog_events.inc; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + +connection master; +DROP TABLE t1,t2; +sync_slave_with_master; + +# +# bug#35762 Failing CREATE-SELECT produces bad binlog in row mode +# + +connection master; + +CREATE TABLE t1 (a INT); + +INSERT INTO t1 VALUES (1),(1); +--error ER_DUP_ENTRY +CREATE TABLE t2 (a INT UNIQUE) ENGINE=INNODB SELECT * FROM t1; +INSERT INTO t1 VALUES (2); + +sync_slave_with_master; +# connection slave; + +--echo *** the proof of the fix: +--echo select must show that the last insert performed on the slave *** +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +sync_slave_with_master; + +# +# BUG#34707: Row based replication: slave creates table within wrong database +# + +--source include/rpl_reset.inc + +connection master; +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +--enable_warnings +CREATE DATABASE mysqltest1; + +CREATE TABLE mysqltest1.without_select (f1 BIGINT); +CREATE TABLE mysqltest1.with_select AS SELECT 1 AS f1; +source include/show_binlog_events.inc; +sync_slave_with_master; + +connection master; +DROP DATABASE mysqltest1; +sync_slave_with_master; + +# +# BUG#48506: crash in CREATE TABLE <existing_view> IF NOT EXISTS LIKE +# <tmp_tbl> with RBL +# + +--source include/rpl_reset.inc + +connection master; +CREATE TEMPORARY TABLE t7(c1 INT); +CREATE TABLE t5(c1 INT); +CREATE TABLE t4(c1 INT); +CREATE VIEW bug48506_t1 AS SELECT 1; +CREATE VIEW bug48506_t2 AS SELECT * FROM t4; +CREATE VIEW bug48506_t3 AS SELECT t5.c1 AS A, t4.c1 AS B FROM t5, t4; +CREATE TABLE bug48506_t4(c1 INT); +--disable_warnings +sync_slave_with_master; +DROP VIEW bug48506_t1, bug48506_t2, bug48506_t3; +DROP TABLE bug48506_t4; + +connection master; +CREATE TABLE IF NOT EXISTS bug48506_t1 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t2 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t3 LIKE t7; +CREATE TABLE IF NOT EXISTS bug48506_t4 LIKE t7; +--enable_warnings +sync_slave_with_master; + +SHOW TABLES LIKE 'bug48506%'; + +connection master; +DROP VIEW IF EXISTS bug48506_t1, bug48506_t2, bug48506_t3; +DROP TEMPORARY TABLES t7; +DROP TABLES t4, t5; +DROP TABLES IF EXISTS bug48506_t4; + +--source include/rpl_end.inc + +--echo end of the tests diff --git a/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test b/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test new file mode 100644 index 00000000..603af398 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_delayed_ins.test @@ -0,0 +1,2 @@ +let $engine_type=myisam; +-- source include/rpl_row_delayed_ins.test diff --git a/mysql-test/suite/rpl/t/rpl_row_drop.test b/mysql-test/suite/rpl/t/rpl_row_drop.test new file mode 100644 index 00000000..4df6e2ad --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_drop.test @@ -0,0 +1,38 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# Bug#12415: DROP of temporary table on master stops slave +connection master; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (a int); +CREATE TEMPORARY TABLE t2 (a int, b int); +SHOW TABLES; +sync_slave_with_master; +SHOW TABLES; +connection master; +DROP TABLE t2; # Dropping the temporary table +SHOW TABLES; +sync_slave_with_master; +SHOW TABLES; # There should be two tables on the slave + +connection master; +CREATE TEMPORARY TABLE t2 (a int, b int); +SHOW TABLES; +sync_slave_with_master; +SHOW TABLES; +connection master; +# Should drop the non-temporary table t1 and the temporary table t2 +DROP TABLE t1,t2; +source include/show_binlog_events.inc; +SHOW TABLES; +sync_slave_with_master; +SHOW TABLES; + +--disable_query_log +--disable_warnings +connection master; +DROP TABLE IF EXISTS t2; +sync_slave_with_master; +--enable_warnings +--enable_query_log +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test new file mode 100644 index 00000000..bc5c6074 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_drop_create_temp_table.test @@ -0,0 +1,11 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. Specifically when drop temporary tables and create temporary tables +# are used. +################################################################################### +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--source include/rpl_drop_create_temp_table.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test new file mode 100644 index 00000000..ba3770d3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_drop_temp_table.test @@ -0,0 +1,54 @@ +# ==== Purpose ==== +# +# Test verifies that plain DROP TEMPORARY TABLE IF EXISTS statements are not +# replicated during row based replication. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Have a read_only master and slave. Binlog format should be "ROW". +# 1 - Create a procedure which executes DROP TEMPORARY TABLE IF EXISTS +# statements prior to CREATE TEMPORARY TABLE. +# 2 - Execute the procedure. +# 3 - Verify that the DROP TEMPORARY TABLE IF EXISTS statements within the +# procedure are not written to the binary log. +# +# ==== References ==== +# +# MDEV-20091: DROP TEMPORARY table is logged despite no CREATE was logged +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +connection slave; +SET GLOBAL read_only=1; + +connection master; +DELIMITER |; +CREATE PROCEDURE testproc() +BEGIN + DROP TEMPORARY TABLE IF EXISTS t1_tmp; + DROP TEMPORARY TABLE IF EXISTS t2_tmp; + CREATE TEMPORARY TABLE IF NOT EXISTS t1_tmp ( t1 varchar(400) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TEMPORARY TABLE IF NOT EXISTS t2_tmp ( t2 varchar(16) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +END| +DELIMITER ;| +SET GLOBAL read_only=1; +CALL testproc(); +--echo ******** None of the above DROP TEMPORARY TABLE statement should be found in binary log ******** +--source include/show_binlog_events.inc +--sync_slave_with_master +SELECT @@read_only; + +--echo ======== CLEAN UP ========= +connection master; +DROP TEMPORARY TABLE t1_tmp; +DROP TEMPORARY TABLE t2_tmp; +DROP PROCEDURE testproc; +SET GLOBAL read_only=0; +--sync_slave_with_master +SET GLOBAL read_only=0; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt new file mode 100644 index 00000000..144bbca0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss-master.opt @@ -0,0 +1,2 @@ +--binlog-row-event-max-size=8192 + diff --git a/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test new file mode 100644 index 00000000..5b2d99f3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_end_of_statement_loss.test @@ -0,0 +1,66 @@ +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +# Loss of STMT_END flagged event must error out the IO thread +--connection slave +call mtr.add_suppression("Slave IO thread did not receive an expected Rows-log end-of-statement"); +call mtr.add_suppression("Relay log write failure: could not queue event from master"); + +SET @save_debug= @@global.debug; +SET GLOBAL debug_dbug="+d,simulate_stmt_end_rows_event_loss"; +--source include/stop_slave.inc +--replace_result $MASTER_MYPORT MASTER_PORT +--eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, MASTER_USE_GTID=SLAVE_POS + +--connection master +--let $max_row_size=8192 +--eval CREATE TABLE t (a INT, b text($max_row_size)); +--eval INSERT INTO t values (1, repeat('b', $max_row_size)), (1, repeat('b', $max_row_size)) + +# Prove that the missed STMT_END marked rows-event causes the io thread stop. +--connection slave +START SLAVE IO_THREAD; +--let $slave_io_errno=1595 +--source include/wait_for_slave_io_error.inc +SET GLOBAL debug_dbug="-d,simulate_stmt_end_rows_event_loss"; +--source include/start_slave.inc + +--connection master +sync_slave_with_master; + +# Compressed version of the above +--connection slave +--source include/stop_slave.inc + +--connection master +SET @save_log_bin_compress= @@GLOBAL.log_bin_compress; +SET @save_log_bin_compress_min_len= @@GLOBAL.log_bin_compress_min_len; + +SET @@GLOBAL.log_bin_compress=ON; +SET @@GLOBAL.log_bin_compress_min_len=10; + +--eval INSERT INTO t values (2, repeat('b', $max_row_size)), (2, repeat('b', $max_row_size)) + +# Prove that the missed STMT_END marked rows-event causes the io thread stop. +--connection slave +SET GLOBAL debug_dbug="+d,simulate_stmt_end_rows_event_loss"; +START SLAVE IO_THREAD; +--let $slave_io_errno=1595 +--source include/wait_for_slave_io_error.inc +SET GLOBAL debug_dbug="-d,simulate_stmt_end_rows_event_loss"; +--source include/start_slave.inc + +--connection master +sync_slave_with_master; + +# cleanup + +--connection master +SET @@GLOBAL.log_bin_compress= @save_log_bin_compress; +SET @@GLOBAL.log_bin_compress_min_len= @save_log_bin_compress_min_len; +DROP TABLE t; +sync_slave_with_master; +SET GLOBAL debug_dbug= @save_debug; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt new file mode 100644 index 00000000..83ed8522 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-master.opt @@ -0,0 +1 @@ +--binlog-format=row diff --git a/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt new file mode 100644 index 00000000..4cb7a31d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_err_daisychain-slave.opt @@ -0,0 +1 @@ +--binlog-format=statement --log-slave-updates diff --git a/mysql-test/suite/rpl/t/rpl_row_find_row.test b/mysql-test/suite/rpl/t/rpl_row_find_row.test new file mode 100644 index 00000000..444706ac --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_find_row.test @@ -0,0 +1,103 @@ +# BUG#47312: RBR: Disabling key on slave breaks replication: +# HA_ERR_WRONG_INDEX +# +# Description +# =========== +# +# This test case checks whether disabling a key on a slave breaks +# replication or not. +# +# Case #1, shows that while not using ALTER TABLE... DISABLE KEYS and +# the slave has no key defined while the master has one, replication +# won't break. +# +# Case #2, shows that before patch for BUG#47312, if defining key on +# slave table, and later disable it, replication would break. This +# has been fixed. +# + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# +# Case #1: master has key, but slave has not. +# Replication does not break. +# + +SET SQL_LOG_BIN=0; +CREATE TABLE t (a int, b int, c int, key(b)); +SET SQL_LOG_BIN=1; + +-- connection slave + +CREATE TABLE t (a int, b int, c int); + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master + +# +# Case #2: master has key, slave also has one, +# but it gets disabled sometime. +# Replication does not break anymore. +# +--source include/rpl_reset.inc +-- connection master + +CREATE TABLE t (a int, b int, c int, key(b)); + +-- sync_slave_with_master + +ALTER TABLE t DISABLE KEYS; + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master + +# +# BUG#53893: RBR: nullable unique key can lead to out-of-sync slave +# + +# +# We insert two rows. Both with part of UNIQUE KEY set to null. +# Then we update the last row inserted. On master the correct +# row is updated. On the slave the wrong row would be updated +# because the engine would look it up by the NULL Unique KEY. +# As a consquence, the wrong row would be updated. +# + +-- source include/rpl_reset.inc +-- connection master + +CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 INT, UNIQUE KEY(c1,c3), KEY(c2)); +INSERT INTO t1(c1,c2) VALUES(1,1); +INSERT INTO t1(c1,c2) VALUES(1,2); +UPDATE t1 SET c1=1000 WHERE c2=2; +-- sync_slave_with_master + +-- let $diff_tables= master:t1, slave:t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test new file mode 100644 index 00000000..e3edabe2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test @@ -0,0 +1,57 @@ +# +# Bug#11760927: 53375: RBR + NO PK => HIGH LOAD ON SLAVE (TABLE SCAN/CPU) => SLAVE FAILURE +# +--source include/have_binlog_format_row.inc +--source include/have_debug.inc +--source include/master-slave.inc + +# SETUP +# - setup log_warnings and debug +--connection slave +--source include/stop_slave.inc +SET @saved_dbug = @@GLOBAL.debug_dbug; +--let $log_warnings_save= `SELECT @@GLOBAL.log_warnings` + +SET GLOBAL log_warnings = 2; + +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Assign env variable LOG_ERROR +let LOG_ERROR=$log_error_; + +# force printing the notes to the error log +SET GLOBAL debug_dbug="d,inject_long_find_row_note"; +--source include/start_slave.inc + +# test +--connection master +CREATE TABLE t1 (c1 INT); +--sync_slave_with_master +--connection master + +INSERT INTO t1 VALUES (1), (2); +UPDATE t1 SET c1= 1000 WHERE c1=2; +DELETE FROM t1; +DROP TABLE t1; +--sync_slave_with_master + +--echo # Check if any note related to long DELETE_ROWS and UPDATE_ROWS appears in the error log +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=The slave is applying a ROW event on behalf of an UPDATE statement on table t1 and is currently taking a considerable amount +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=The slave is applying a ROW event on behalf of a DELETE statement on table t1 and is currently taking a considerable amount +--source include/search_pattern_in_file.inc + +# cleanup +--source include/stop_slave.inc +SET @@GLOBAL.debug_dbug = @saved_dbug; +--eval SET GLOBAL log_warnings = $log_warnings_save +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test new file mode 100644 index 00000000..c10b3570 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_flsh_tbls.test @@ -0,0 +1,7 @@ +# depends on the binlog output +-- source include/have_binlog_format_row.inc +--source include/binlog_start_pos.inc + +let $rename_event_pos= `select @binlog_start_pos + 819`; + +-- source include/rpl_flsh_tbls.test diff --git a/mysql-test/suite/rpl/t/rpl_row_func001.test b/mysql-test/suite/rpl/t/rpl_row_func001.test new file mode 100644 index 00000000..6ff97388 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_func001.test @@ -0,0 +1,58 @@ +############################################################################# +# This test is being created to test out the non deterministic items with # +# row based replication. # +# Original Author: JBM # +# Original Date: Aug/10/2005 # +# Update: 08/29/2005 change name to initails # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +--error 0,1305 +DROP FUNCTION test.f1; +DROP TABLE IF EXISTS test.t1; + + +--enable_warnings + +# Section 1 test from bug #12487 Uses stored function to insert rows to see what is replicated. + +create table test.t1 (a int, PRIMARY KEY(a)); + +delimiter //; +create function test.f1(i int) returns int +begin +insert into test.t1 values(i); +return 0; +end// +delimiter ;// + +select test.f1(1); +select test.f1(2); +select * from test.t1; + +save_master_pos; +sync_slave_with_master; +connection slave; +#show create table test.t1; +select * from test.t1; + +connection master; + +#Used for debugging +#show binlog events; + +# Cleanup + +DROP FUNCTION test.f1; +DROP TABLE test.t1; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_func002.test b/mysql-test/suite/rpl/t/rpl_row_func002.test new file mode 100644 index 00000000..2f4e3fdd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_func002.test @@ -0,0 +1,105 @@ +############################################################################# +# This test is being created to test out the non deterministic items with # +# row based replication. # +# Original Author: JBM # +# Original Date: Aug/10/2005 # +# Update: 08/29/2005 Turn on diff # +############################################################################# +# Note: Many lines are commented out in this test case. These were used for # +# creating the test case and debugging and are being left for # +# debugging, but they can not be used for the regular testing as the # +# Time changes and is not deteministic, so instead we dump both the # +# master and slave and diff the dumps. If the dumps differ then the # +# test case will fail. To run during diff failuers, comment out the # +# diff. # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +--error 0,1305 +DROP FUNCTION test.f1; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; + +--enable_warnings + +# Section 1 test from Peter G. This test changes uses a stored function to update rows and return the timestamp. We change the value of the time stamp on the master to see what is replicated. + +CREATE TABLE test.t1 (a INT NOT NULL AUTO_INCREMENT, t TIMESTAMP, t2 TIMESTAMP, PRIMARY KEY(a)); +CREATE TABLE test.t2 (a INT NOT NULL AUTO_INCREMENT, t TIMESTAMP, t2 TIMESTAMP, PRIMARY KEY(a)); + +delimiter //; +create function test.f1() RETURNS TIMESTAMP +BEGIN +UPDATE test.t1 SET t = CURRENT_TIMESTAMP; +RETURN CURRENT_TIMESTAMP; +END// +delimiter ;// + +INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP); +#select * from test.t1; +#save_master_pos; +#sync_slave_with_master; +#connection slave; +#select * from test.t1; +#connection master; + + +SET TIMESTAMP=2; +INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP); +#select * from test.t1; +#save_master_pos; +#sync_slave_with_master; +#connection slave; +#select * from test.t1; +#connection master; + +#sleep 3; +SET TIMESTAMP=1; +INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP); +#select * from test.t1; +#save_master_pos; +#sync_slave_with_master; +#connection slave; +#select * from test.t1; +#connection master; + + +SET TIMESTAMP=333300000; +INSERT INTO test.t2 VALUES (null,f1(),CURRENT_TIMESTAMP); + +# We need a sync to ensure that the slave has caught up before +# dumping the database. +sync_slave_with_master; + +connection master; +#Used for debugging +#show binlog events; + +# time to dump the databases and so we can see if they match + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/func002_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/func002_slave.sql + +# Cleanup +DROP FUNCTION test.f1; +DROP TABLE test.t1; +DROP TABLE test.t2; +sync_slave_with_master; + +# the test will show that the diff statement failed and no reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching :-). The files are located +# in mysql-test/var/tmp + +diff_files $MYSQLTEST_VARDIR/tmp/func002_master.sql $MYSQLTEST_VARDIR/tmp/func002_slave.sql; + +# End of 5.0 test case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_func003.test b/mysql-test/suite/rpl/t/rpl_row_func003.test new file mode 100644 index 00000000..def987fa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_func003.test @@ -0,0 +1,12 @@ +################################### +# Wrapper for rpl_row_func003.test# +################################### +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=INNODB; +-- source include/rpl_row_func003.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_idempotency.test b/mysql-test/suite/rpl/t/rpl_row_idempotency.test new file mode 100644 index 00000000..85775832 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_idempotency.test @@ -0,0 +1,333 @@ +# Testing various forms of idempotency for replication. This file is +# for tests that should only be executed in row mode. + +source include/have_binlog_format_row.inc; +source include/master-slave.inc; +connection master; +source include/have_innodb.inc; +connection slave; +source include/have_innodb.inc; + +# Add suppression for expected warning(s) in slaves error log +call mtr.add_suppression("Can.t find record in .t[12].* error.* 1032"); +call mtr.add_suppression("Cannot delete or update a parent row: a foreign key constraint fails .* error.* 1451"); +call mtr.add_suppression("Cannot add or update a child row: a foreign key constraint fails .* error.* 1452"); +call mtr.add_suppression("Duplicate entry .1. for key .PRIMARY.* error.* 1062"); +call mtr.add_suppression("Can't find record in 't1'"); +call mtr.add_suppression("Can't find record in 't2'"); + + +# bug#31609 Not all RBR slave errors reported as errors +# bug#31552 Replication breaks when deleting rows from out-of-sync table +# without PK + +# The default for slave-exec-mode option and server +# variable slave_exec_mode is 'STRICT'. +# When 'STRICT' mode is set, the slave SQL thread will stop whenever +# the row to change is not found. In 'IDEMPOTENT' mode, the SQL thread +# will continue running and apply the row - replace if it's Write_rows event - +# or skip to the next event. + +# the previous part of the tests was with IDEMPOTENT slave's mode. + + +# +# Other than above idempotent errors dealing with foreign keys constraint +# +connection slave; + +set @old_slave_exec_mode= @@global.slave_exec_mode; +set @@global.slave_exec_mode= IDEMPOTENT; + +connection master; + +create table ti1 (b int primary key) engine = innodb; +create table ti2 (a int primary key, b int, foreign key (b) references ti1(b)) + engine = innodb; +set foreign_key_checks=1 /* ensure the check */; + +insert into ti1 values (1),(2),(3); +insert into ti2 set a=2, b=2; + +sync_slave_with_master; + +#connection slave; +select * from ti1 order by b /* must be (1),(2),(3) */; +insert into ti2 set a=1, b=1; +select * from ti2 order by b /* must be (1,1) (2,2) */; + +connection master; + +# from now on checking rbr specific idempotent errors +set @save_binlog_format= @@session.binlog_format; +set @@session.binlog_format= row; +delete from ti1 where b=1; + +select * from ti1 order by b /* must be (2),(3) */; + +# slave must catch up (expect some warnings in error.log) +sync_slave_with_master; + +#connection slave; +select * from ti1 order by b /* must stays as were on master (1),(2),(3) */; + +delete from ti1 where b=3; + +connection master; +insert into ti2 set a=3, b=3; + +# slave must catch up (expect some warnings in error.log) +sync_slave_with_master; + +#connection slave; +select * from ti2 order by b /* must be (1,1),(2,2) - not inserted */; + + +# +# Checking the new global sys variable +# + +connection slave; + +set global slave_exec_mode='IDEMPOTENT'; +set global slave_exec_mode='STRICT'; + +# checking mutual exclusion for the options +--error ER_WRONG_VALUE_FOR_VAR +set global slave_exec_mode='IDEMPOTENT,STRICT'; + +select @@global.slave_exec_mode /* must be STRICT */; + +# +# Checking stops. +# In the following sections strict slave sql thread is going to +# stop when faces an idempotent error. In order to proceed +# the mode is temporarily switched to indempotent. +# + +# +--echo *** foreign keys errors as above now forces to stop +# + +connection master; + +set foreign_key_checks=0; +drop table ti2, ti1; + +create table ti1 (b int primary key) engine = innodb; +create table ti2 (a int primary key, b int, foreign key (b) references ti1(b)) + engine = innodb; +set foreign_key_checks=1 /* ensure the check */; + +insert into ti1 values (1),(2),(3); +insert into ti2 set a=2, b=2; + +sync_slave_with_master; + +#connection slave; +select * from ti1 order by b /* must be (1),(2),(3) */; +--echo *** conspire future problem +insert into ti2 set a=1, b=1; +select * from ti2 order by b /* must be (1,1) (2,2) */; + +connection master; + +delete from ti1 where b=1 /* offending delete event */; +select * from ti1 order by b /* must be (2),(3) */; + +# foreign key: row is referenced + +--echo *** slave must stop (Trying to delete a referenced foreing key) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +select * from ti1 order by b /* must be (1),(2),(3) - not deleted */; +set foreign_key_checks= 0; +delete from ti2 where b=1; +set foreign_key_checks= 1; +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + +connection master; + +sync_slave_with_master; + +#connection slave; +--echo *** conspire the following insert failure +# foreign key: no referenced row + +--echo *** conspire future problem +delete from ti1 where b=3; + +connection master; +insert into ti2 set a=3, b=3 /* offending write event */; + +--echo *** slave must stop (Trying to insert an invalid foreign key) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +select * from ti2 order by b /* must be (2,2) */; +set foreign_key_checks= 0; +insert into ti1 set b=3; +set foreign_key_checks= 1; +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + +connection master; + +sync_slave_with_master; + +select * from ti2 order by b /* must be (2,2),(3,3) */; + +# +--echo *** other errors +# + +# dup key insert + +#connection slave; +--echo *** conspiring query +insert into ti1 set b=1; + +connection master; +insert into ti1 set b=1 /* offending write event */; + +--echo *** slave must stop (Trying to insert a dupliacte key) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +set foreign_key_checks= 0; +delete from ti1 where b=1; +set foreign_key_checks= 1; +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + +# key not found + +connection master; + +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT); +INSERT INTO t1 VALUES (-1),(-2),(-3); +INSERT INTO t2 VALUES (-1),(-2),(-3); +sync_slave_with_master; + +#connection slave; +DELETE FROM t1 WHERE a = -2; +DELETE FROM t2 WHERE a = -2; +connection master; +DELETE FROM t1 WHERE a = -2; + +--echo *** slave must stop (Key was not found) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + +connection master; +DELETE FROM t2 WHERE a = -2; +--echo *** slave must stop (Key was not found) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + +UPDATE t1 SET a = 1 WHERE a = -1; +UPDATE t2 SET a = 1 WHERE a = -1; + +connection master; +UPDATE t1 SET a = 1 WHERE a = -1; + +--echo *** slave must stop (Key was not found) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +set global slave_exec_mode='STRICT'; + + +connection master; +UPDATE t2 SET a = 1 WHERE a = -1; + +--echo *** slave must stop (Key was not found) +connection slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; + +set global slave_exec_mode='IDEMPOTENT'; +start slave sql_thread; +connection master; +sync_slave_with_master; +#connection slave; +SET @@global.slave_exec_mode= @old_slave_exec_mode; + +# cleanup for bug#31609 tests + +connection master; + +drop table t1,t2,ti2,ti1; +sync_slave_with_master; +set @@global.slave_exec_mode= @old_slave_exec_mode; + +--echo *** end of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_img.cnf b/mysql-test/suite/rpl/t/rpl_row_img.cnf new file mode 100644 index 00000000..ed9a4292 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img.cnf @@ -0,0 +1,21 @@ +!include include/default_mysqld.cnf + +[mysqld.1] +log-slave-updates +innodb +innodb_flush_log_at_trx_commit= 0 + +[mysqld.2] +log-slave-updates +innodb +innodb_flush_log_at_trx_commit= 0 + +[mysqld.3] +log-slave-updates +innodb +innodb_flush_log_at_trx_commit= 0 + +[ENV] +SERVER_MYPORT_1= @mysqld.1.port +SERVER_MYPORT_2= @mysqld.2.port +SERVER_MYPORT_3= @mysqld.3.port diff --git a/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf b/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf new file mode 100644 index 00000000..d758d29f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_blobs.cnf @@ -0,0 +1 @@ +!include suite/rpl/t/rpl_row_img.cnf diff --git a/mysql-test/suite/rpl/t/rpl_row_img_blobs.test b/mysql-test/suite/rpl/t/rpl_row_img_blobs.test new file mode 100644 index 00000000..21f224f5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_blobs.test @@ -0,0 +1,59 @@ +#Want to skip this test from daily Valgrind execution +--source include/no_valgrind_without_big.inc + +# +# This file contains tests for WL#5096. +# + +--let $rpl_topology= 1->2->3 +--source include/rpl_init.inc +-- source include/have_binlog_format_row.inc + +-- connection server_1 +-- source include/have_innodb.inc +-- connection server_2 +-- source include/have_innodb.inc +-- connection server_3 +-- source include/have_innodb.inc +-- connection server_1 + +# +# WL#5096 Tests. +# + +# +# Tests combinations of binlog-row-image against mixes of MyISAM and InnoDB +# storage engines on all three servers. +# +# All the combinarions need not to be separated into their own files as +# the tests for indexes and engines mixes are, because noblobs test script +# does not take too long time, thence we do not risk triggering PB2 timeout +# on valgrind runs. +# + +## NOBLOB + +-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y +-- source include/rpl_row_img_set.inc + +-- let $row_img_test_script= include/rpl_row_img_blobs.test +-- source include/rpl_row_img_general_loop.inc + +## MINIMAL + +-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y +-- source include/rpl_row_img_set.inc + +-- let $row_img_test_script= include/rpl_row_img_blobs.test +-- source include/rpl_row_img_general_loop.inc + +## FULL + +-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y +-- source include/rpl_row_img_set.inc + +-- let $row_img_test_script= include/rpl_row_img_blobs.test +-- source include/rpl_row_img_general_loop.inc + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf new file mode 100644 index 00000000..d758d29f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.cnf @@ -0,0 +1 @@ +!include suite/rpl/t/rpl_row_img.cnf diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test new file mode 100644 index 00000000..06764fe8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_min.test @@ -0,0 +1,39 @@ +#Want to skip this test from daily Valgrind execution +--source include/no_valgrind_without_big.inc +# +# This file contains tests for WL#5096 and bug fixes. +# + +--let $rpl_topology= 1->2->3 +--source include/rpl_init.inc +-- source include/have_binlog_format_row.inc + +-- connection server_1 +-- source include/have_innodb.inc +-- connection server_2 +-- source include/have_innodb.inc +-- connection server_3 +-- source include/have_innodb.inc +-- connection server_1 + +# +# WL#5096 +# + +# +# Tests for different storage engines on each server, +# but same index structure on tables. The tests are conducted +# using MINIMAL binlog-row-image on all servers. +# + +-- let $row_img_set=server_1:MINIMAL:N,server_2:MINIMAL:Y,server_3:MINIMAL:Y +-- source include/rpl_row_img_set.inc + +-- let $row_img_test_script= include/rpl_row_img.test +-- source include/rpl_row_img_general_loop.inc + +-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y +-- source include/rpl_row_img_set.inc + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf new file mode 100644 index 00000000..d758d29f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.cnf @@ -0,0 +1 @@ +!include suite/rpl/t/rpl_row_img.cnf diff --git a/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test new file mode 100644 index 00000000..7f4944b5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_img_eng_noblob.test @@ -0,0 +1,39 @@ +#Want to skip this test from daily Valgrind execution +--source include/no_valgrind_without_big.inc +# +# This file contains tests for WL#5096 and bug fixes. +# + +--let $rpl_topology= 1->2->3 +--source include/rpl_init.inc +-- source include/have_binlog_format_row.inc + +-- connection server_1 +-- source include/have_innodb.inc +-- connection server_2 +-- source include/have_innodb.inc +-- connection server_3 +-- source include/have_innodb.inc +-- connection server_1 + +# +# WL#5096 +# + +# +# Tests for different storage engines on each server, +# but same index structure on tables. The tests are conducted +# using NOBLOB binlog-row-image on all servers. +# + +-- let $row_img_set=server_1:NOBLOB:N,server_2:NOBLOB:Y,server_3:NOBLOB:Y +-- source include/rpl_row_img_set.inc + +-- let $row_img_test_script= include/rpl_row_img.test +-- source include/rpl_row_img_general_loop.inc + +-- let $row_img_set=server_1:FULL:N,server_2:FULL:Y,server_3:FULL:Y +-- source include/rpl_row_img_set.inc + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test new file mode 100644 index 00000000..ba204b05 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_implicit_commit_binlog.test @@ -0,0 +1,12 @@ +################################################################################ +# Check file include/rpl_implicit_commit_binlog.test +################################################################################ +--source include/have_udf.inc +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--let $engine=Innodb +set session default_storage_engine=innodb; +--source include/rpl_implicit_commit_binlog.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_index_choice.test b/mysql-test/suite/rpl/t/rpl_row_index_choice.test new file mode 100644 index 00000000..958fa235 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_index_choice.test @@ -0,0 +1,243 @@ +--source include/have_binlog_format_row.inc +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +# Bug#58997: Row-based replication breaks on table with only fulltext index: +connection master; +CREATE TABLE t1 (a int, b varchar(100), fulltext(b)) engine=MyISAM; +INSERT INTO t1 VALUES (1,"a"), (2,"b"); +UPDATE t1 SET b='A' WHERE a=1; +DELETE FROM t1 WHERE a=2; + +sync_slave_with_master; + +connection slave; + +SELECT * FROM t1 ORDER BY a; + +connection master; +DROP TABLE t1; + + +# A utility table used to populate subsequent tables in various ways. +connection master; +CREATE TABLE t1 (d INT PRIMARY KEY) ENGINE=myisam; +INSERT INTO t1 VALUES (0); +INSERT INTO t1 SELECT d+1 FROM t1; +INSERT INTO t1 SELECT d+2 FROM t1; +INSERT INTO t1 SELECT d+4 FROM t1; +INSERT INTO t1 SELECT d+8 FROM t1; +INSERT INTO t1 SELECT d+16 FROM t1; +INSERT INTO t1 SELECT d+32 FROM t1; +INSERT INTO t1 SELECT d+64 FROM t1; +INSERT INTO t1 SELECT d+128 FROM t1; +INSERT INTO t1 SELECT d+256 FROM t1; +INSERT INTO t1 SELECT d+512 FROM t1; + +# Test that we pick the better multi-column index, even if the +# single-column index is more selective in the first column. +CREATE TABLE t2 (a INT, b INT, c INT, d INT, + KEY wrong_key(a), + KEY expected_key(b,c), + KEY wrong_key2(c)) ENGINE=myisam; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1; + +sync_slave_with_master; +connection slave; +ANALYZE TABLE t2; +--echo # Slave will crash if using the wrong or no index +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +# Test that we don't pick a unique index with NULLS over a more selective +# non-unique index. +connection master; +DROP TABLE t2; +CREATE TABLE t2 (a INT, b INT, c INT, d INT NOT NULL, e INT, + UNIQUE wrong_key3(a,e), + KEY wrong_key4(b,c), + UNIQUE expected_key(d)) ENGINE=myisam; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, NULL FROM t1; + +sync_slave_with_master; +connection slave; +ANALYZE TABLE t2; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + +# Test that we pick a reasonable index when there is no rec_per_key[] +# information (no ANALYZE TABLE). +CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL, + KEY wrong_key5(b), + UNIQUE expected_key(d), + KEY wrong_key6(c)) ENGINE=myisam; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1; + +sync_slave_with_master; +connection slave; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +# Also test without ANALYZE when we pick the sub-optimal index. +# In this case the key on (d) is the best one, but without ANALYZE TABLE we +# have no information and will pick the first one on (b). +# (This test should be updated if we improve the index selection, of course). +CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL, + KEY expected_key(b), + KEY wrong_key7(d), + KEY wrong_key8(c)) ENGINE=myisam; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1; + +sync_slave_with_master; +connection slave; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +# Test that we pick the primary key for InnoDB, if available. +CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, + UNIQUE wrong_key9(d), + KEY wrong_key10(a), + PRIMARY KEY expected_key(c,b)) ENGINE=innodb; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1; + +sync_slave_with_master; +connection slave; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan,slave_crash_if_index_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +# Test that we pick a good index for InnoDB when primary key is not available. +CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT, + UNIQUE wrong_key11(e), + KEY wrong_key12(a), + KEY expected_key(c,b)) ENGINE=innodb; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1; + +sync_slave_with_master; +connection slave; +ANALYZE TABLE t2; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +# When there is no ANALYZE TABLE, InnoDB will just report "1" for index +# cardinality for all indexes in rec_per_key. So currently we cannot choose +# index to use intelligently. Just test that we work as expected (select +# first index, remember that unique keys are sorted first by server). +CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT, + KEY wrong_key13(a), + UNIQUE expected_key(e), + KEY wrong_key14(c,b)) ENGINE=innodb; +INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1; + +sync_slave_with_master; +connection slave; +--echo # Slave will crash if using the wrong or no index +SET GLOBAL debug_dbug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan"; + +connection master; +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SET GLOBAL debug_dbug=""; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +# Finally, test behaviour when no indexes are available at all. +CREATE TABLE t2 (a INT NOT NULL, d INT) ENGINE=innodb; +INSERT INTO t2 SELECT d DIV 10, d FROM t1; + +UPDATE t2 SET d=10042 WHERE d=42; +DELETE FROM t2 WHERE d=53; + +sync_slave_with_master; +connection slave; +SELECT * FROM t2 WHERE d IN (10042,53); + +connection master; +DROP TABLE t2; + + +connection master; +DROP TABLE t1; +sync_slave_with_master; +connection slave; +SET @@GLOBAL.debug_dbug = @saved_dbug; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test b/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test new file mode 100644 index 00000000..907e309a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test @@ -0,0 +1,40 @@ +# ==== Purpose ==== +# +# Verify that slave gives an error message if master updates a table +# that slave does not have. +# +# ==== Method ==== +# +# Create a table on master, wait till it's on slave, remove it from +# slave. Then update the table on master. + +--source include/have_binlog_format_row.inc + +source include/master-slave.inc; + +--echo ==== Setup table on master but not on slave ==== +CREATE TABLE t1 (a INT); + +sync_slave_with_master; +DROP TABLE t1; + +--echo ==== Modify table on master ==== +connection master; +INSERT INTO t1 VALUES (1); + +--echo ==== Verify error on slave ==== +connection slave; +# slave should have stopped because can't find table t1 +# 1146 = ER_NO_SUCH_TABLE +call mtr.add_suppression("Slave SQL.*Error executing row event: .Table .test.t1. doesn.t exist., error.* 1146"); +--let $slave_sql_errno= 1146 +--source include/wait_for_slave_sql_error.inc + +--echo ==== Clean up ==== +source include/stop_slave_io.inc; +RESET SLAVE; + +connection master; +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt new file mode 100644 index 00000000..7624b013 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames-slave.opt @@ -0,0 +1 @@ +--replicate-do-db=bug_37656 --replicate-ignore-table=buG_37656.T1 --replicate-do-table=bUg_37656.T2 --replicate-do-table=bUg_37656.T3 --lower-case-table-names=1 diff --git a/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test new file mode 100644 index 00000000..44c04dd6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_lcase_tblnames.test @@ -0,0 +1,12 @@ +# BUG#37656 +# +# For details look into extra/rpl_tests/rpl_lower_case_table_names.test +# + +-- source include/master-slave.inc +-- source include/have_innodb.inc +-- source include/not_windows.inc +-- source include/have_binlog_format_row.inc + +-- let $engine=InnoDB +-- source include/rpl_lower_case_table_names.test diff --git a/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test new file mode 100644 index 00000000..c2cb2b4a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_loaddata_concurrent.test @@ -0,0 +1,13 @@ +-- source include/have_log_bin.inc +-- source include/have_binlog_format_row.inc + +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CREATE TABLE t1 (c1 char(50)) engine=myisam; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +-- source include/show_binlog_events.inc +DROP TABLE t1; + +let $lock_option= CONCURRENT; +let $engine_type=MyISAM; +-- source include/rpl_loaddata.test diff --git a/mysql-test/suite/rpl/t/rpl_row_log-master.opt b/mysql-test/suite/rpl/t/rpl_row_log-master.opt new file mode 100644 index 00000000..e0d075c3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_log-master.opt @@ -0,0 +1 @@ +--skip-external-locking diff --git a/mysql-test/suite/rpl/t/rpl_row_log-slave.opt b/mysql-test/suite/rpl/t/rpl_row_log-slave.opt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_log-slave.opt @@ -0,0 +1 @@ + diff --git a/mysql-test/suite/rpl/t/rpl_row_log.test b/mysql-test/suite/rpl/t/rpl_row_log.test new file mode 100644 index 00000000..25fcc4f4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_log.test @@ -0,0 +1,15 @@ +################################### +# Wrapper for rpl_row_log.test # +# Added wrapper so that MyISAM & # +# Innodb could all use the# +# Same test +################################### +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=MyISAM; +-- source include/rpl_log.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt new file mode 100644 index 00000000..773ec62b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_log_innodb-master.opt @@ -0,0 +1,2 @@ +--skip-external-locking +--default-storage-engine=MyISAM diff --git a/mysql-test/suite/rpl/t/rpl_row_log_innodb.test b/mysql-test/suite/rpl/t/rpl_row_log_innodb.test new file mode 100644 index 00000000..92fe0eb9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_log_innodb.test @@ -0,0 +1,13 @@ +################################### +# Wrapper for rpl_row_log.test # +# Added wrapper so that MyISAM & # +# Innodb could all use the# +# Same test. +################################### +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc +let $engine_type=InnoDB; +-- source include/rpl_log.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test b/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test new file mode 100644 index 00000000..0ec85244 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_max_relay_size.test @@ -0,0 +1,9 @@ +# Test of options max_binlog_size and max_relay_log_size and +# how they act (if max_relay_log_size == 0, use max_binlog_size +# for relay logs too). +# Test of manual relay log rotation with FLUSH LOGS. + +# Requires statement logging +source include/have_binlog_format_row.inc; + +source include/rpl_max_relay_size.test; diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test new file mode 100644 index 00000000..c28d4a89 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test @@ -0,0 +1,52 @@ +# +# BUG#47103 +# +# This test case checks whether the slave crashes or not when there is +# a merge table in use. +# +# Description +# =========== +# +# The test case creates two regular MyISAM tables on the master and +# one MERGE table. Then it populates the MyISAM tables, updates and +# deletes their contents through the merge table. Finally, the slave +# is synchronized with the master and (after the fix) it won't crash. +# +--source include/have_binlog_format_row.inc +--source include/master-slave.inc +--connection master + +CREATE TABLE t1 (a int) ENGINE=MyISAM; +CREATE TABLE t2 (a int) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (4), (5), (6); +# Changed a little to check also an issue reported on BUG#20574550 +CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1; +ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TABLE t1_merge LIKE tt1_merge; + +--sync_slave_with_master + +--let diff_tables=master:test.t1, slave:test.t1 +--source include/diff_tables.inc + +--let diff_tables=master:test.t2, slave:test.t2 +--source include/diff_tables.inc + +--connection master +UPDATE t1_merge SET a=10 WHERE a=1; +DELETE FROM t1_merge WHERE a=10; + +--sync_slave_with_master +--connection master + +--let diff_tables=master:test.t1, slave:test.t1 +--source include/diff_tables.inc + +--let diff_tables=master:test.t2, slave:test.t2 +--source include/diff_tables.inc + +DROP TABLE t1_merge, t1, t2; +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test new file mode 100644 index 00000000..c1a13cd9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_mixing_engines.test @@ -0,0 +1,12 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt new file mode 100644 index 00000000..07d12817 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog-master.opt @@ -0,0 +1 @@ +--max-binlog-size=1040384 diff --git a/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test new file mode 100644 index 00000000..a249043f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_mysqlbinlog.test @@ -0,0 +1,285 @@ +################################################################## +# Author: JBM # +# Date: 2006-02-22 # +# Purpose: To test changes to mysqlbinlog for row based bin logs # +# We are using .opt file since we need small binlog size # +################################################################## +-- source include/have_binlog_format_row.inc +-- source include/not_embedded.inc +-- source include/have_cp932.inc +-- source include/master-slave.inc + +--echo ---Setup Section -- + +# we need this for getting fixed timestamps inside of this test +set timestamp=1000000000; + +CREATE TABLE t1(word VARCHAR(20)); +CREATE TABLE t2(id INT AUTO_INCREMENT NOT NULL PRIMARY KEY); +--let position= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE TABLE t3(c1 INT NOT NULL PRIMARY KEY, c2 LONGBLOB, c3 TIMESTAMP, c4 TEXT, c5 FLOAT); +--let stop_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let stop_position1=`select $stop_position - 1` +--let binlog_start_pos=query_get_value(SHOW BINLOG EVENTS LIMIT 1, End_log_pos, 1) + +# Test Section +# Lets start by putting some data into the tables. + +INSERT INTO t1 VALUES ("abirvalg"); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; + +# d1 length 3000 +set @d1 = 'dd1'; +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); +set @d1 = concat(@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1,@d1); + +--disable_query_log +let count=500; +while ($count) +{ + INSERT INTO t2 VALUES (NULL); + eval INSERT INTO t3 VALUES ($count,@d1,'20060222000000','Tested in Texas',$count*2.2); + dec $count; +} +--enable_query_log + +--echo ---Test 1 check table load -- + +# Lets Check the tables on the Master +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; + +# Should have the same on the slave; + +sync_slave_with_master; +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; + +# Okay time to get busy, back to master + +connection master; + +# simple query to show more in second binlog +insert into t1 values ("Alas"); +flush logs; + +# delimiters are for easier debugging in future +--echo --- Test 1 Dump binlog to file -- + +# +# Prepare local temporary file to recreate what we have currently. +let MYSQLD_DATADIR= `select @@datadir;`; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/master.sql + +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/master.sql + +# Now that we have our file, lets get rid of the current database. +# Cleanup the master and the slave and try to recreate. +--echo --- Test 1 delete tables, clean master and slave -- + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +sync_slave_with_master; +stop slave; +--source include/wait_for_slave_to_stop.inc +connection master; +reset master; +connection slave; +reset slave; +start slave; +--source include/wait_for_slave_to_start.inc +connection master; + +# We should be clean at this point, now we will run in the file from above. +--echo --- Test 1 Load from Dump binlog file -- + +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/master.sql" + +--echo --- Test 1 Check Load Results -- + +# Lets Check the tables on the Master +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; + +# Should have the same on the slave; + +sync_slave_with_master; +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; +connection master; + +# We should be gold by the time, so I will get rid of our file. + +remove_file $MYSQLTEST_VARDIR/tmp/master.sql; + + +# this test for start-position option +# By setting this position to 416, we should only get the create of t3 +--echo --- Test 2 position test -- +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --start-position=$position --stop-position=$stop_position $MYSQLD_DATADIR/master-bin.000001 + +# These are tests for remote binlog. +# They should return the same as previous test. + +--echo --- Test 3 First Remote test -- + +# This is broken now +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$stop_position --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 + +--echo --- Test 4 Second Remote test -- +--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --to-last-log master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql + +# Now that we have our file, lets get rid of the current database. +# Cleanup the master and the slave and try to recreate. + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +sync_slave_with_master; + +stop slave; +--source include/wait_for_slave_to_stop.inc +connection master; +reset master; +connection slave; +reset slave; +start slave; +--source include/wait_for_slave_to_start.inc +connection master; + +# We should be clean at this point, now we will run in the file from above. + +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/remote.sql" + +# Lets Check the tables on the Master + +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; + +# Should have the same on the slave; + +sync_slave_with_master; +SELECT COUNT(*) from t1; +SELECT COUNT(*) from t2; +SELECT COUNT(*) from t3; +SELECT * FROM t1 ORDER BY word LIMIT 5; +SELECT * FROM t2 ORDER BY id LIMIT 5; +SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5; +connection master; + +# We should be gold by the time, so I will get rid of our file. + +--remove_file $MYSQLTEST_VARDIR/tmp/remote.sql +################### End Bug 17654 ###################### + +# What is the point of this test? It seems entirely pointless. It +# might make sense for statement-based replication, but for row-based +# replication the LOAD DATA INFILE is printed just as empty +# transactions. /Matz + +# LOAD DATA +--echo --- Test 5 LOAD DATA -- +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --stop-position=$binlog_start_pos --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 + +# Bug#7853 (mysqlbinlog does not accept input from stdin) + +--echo --- Test 6 reading stdin -- +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL_BINLOG --short-form --stop-position=$stop_position1 - < $MYSQLD_DATADIR/master-bin.000001 + +--echo --- Test 7 reading stdin w/position -- +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--exec $MYSQL_BINLOG --short-form --start-position=$position --stop-position=$stop_position - < $MYSQLD_DATADIR/master-bin.000001 + +# Bug#16217 (mysql client did not know how not switch its internal charset) +--echo --- Test 8 switch internal charset -- +sync_slave_with_master; + +stop slave; +--source include/wait_for_slave_to_stop.inc +connection master; +reset master; +connection slave; +reset slave; +start slave; +--source include/wait_for_slave_to_start.inc +connection master; + +create table t4 (f text character set utf8); +create table t5 (f text character set cp932); +--exec $MYSQL --default-character-set=utf8 test -e "insert into t4 values(_utf8'ソ')" +--exec $MYSQL --default-character-set=cp932 test -e "insert into t5 values(_cp932'ƒ\');" +flush logs; +rename table t4 to t04, t5 to t05; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL --default-character-set=utf8 +# original and recovered data must be equal +select HEX(f) from t04; +select HEX(f) from t4; +select HEX(f) from t05; +select HEX(f) from t5; + +# slave should have same +sync_slave_with_master; +select HEX(f) from t04; +select HEX(f) from t4; +select HEX(f) from t05; +select HEX(f) from t5; + +--echo --- Test cleanup -- +# clean up +connection master; +sync_slave_with_master; + +connection master; +DROP TABLE t1, t2, t3, t04, t05, t4, t5; + +# BUG#17654 also test mysqlbinlog to ensure it can read the binlog from a remote server +# and ensure that the results are the same as if read from a file (the same file). + +CREATE TABLE t1 (a INT NOT NULL KEY, b INT); +INSERT INTO t1 VALUES(1,1); +SELECT * FROM t1; +FLUSH LOGS; + +--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/local.sql + +--diff_files $MYSQLTEST_VARDIR/tmp/local.sql $MYSQLTEST_VARDIR/tmp/remote.sql +--remove_file $MYSQLTEST_VARDIR/tmp/remote.sql +--remove_file $MYSQLTEST_VARDIR/tmp/local.sql +DROP TABLE t1; + +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test b/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test new file mode 100644 index 00000000..39149f6b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_rec_comp_innodb.test @@ -0,0 +1,11 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +# +# BUG#52868 Wrong handling of NULL value during update, replication out of sync +# + +-- let $engine= InnoDB +-- source include/rpl_record_compare.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test b/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test new file mode 100644 index 00000000..d9c06d6b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_rec_comp_myisam.test @@ -0,0 +1,32 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +-- let $engine= MyISAM + +# +# BUG#52868 Wrong handling of NULL value during update, replication out of sync +# + + +-- echo ## coverage purposes - Field_bits +-- echo ## 1 X bit + 2 Null bits + 5 bits => last_null_bit_pos==0 + +--source include/rpl_reset.inc +-- connection master + +-- eval CREATE TABLE t1 (c1 bigint(20) DEFAULT 0, c2 bit(5)) ENGINE=$engine DEFAULT CHARSET=latin1 + +INSERT INTO t1(c1,c2) VALUES (10, b'1'); +INSERT INTO t1(c1,c2) VALUES (NULL, b'1'); +UPDATE t1 SET c1= 0; +-- sync_slave_with_master + +-- let $diff_tables= master:t1, slave:t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +-- source include/rpl_record_compare.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_reset_slave.test b/mysql-test/suite/rpl/t/rpl_row_reset_slave.test new file mode 100644 index 00000000..284c6154 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_reset_slave.test @@ -0,0 +1,5 @@ +# TBF - difference in row level logging +# Temp tables are not replicated in rbr, but it is still good to hit rbr with everthing +-- source include/have_binlog_format_row.inc +-- source include/rpl_reset_slave.test + diff --git a/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test b/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test new file mode 100644 index 00000000..9bc812bb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_rollback_to_savepoint.test @@ -0,0 +1,312 @@ +############################################################################### +# Bug#76727: SLAVE ASSERTION IN UNPACK_ROW WITH ROLLBACK TO +# SAVEPOINT IN ERROR HANDLER +# +# Problem: +# ======== +# "SAVEPOINT", "ROLLBACK TO savepoint" wipe out table map on slave during +# execution binary log events. For trigger the map is written to binary log once +# for all trigger body and if trigger contains "SAVEPOINT" or +# "ROLLBACK TO savepoint" statements any trigger's events after these +# statements will not have table map. This results in an assert on slave. +# +# Test: +# ===== +# Test case 1: +# Create a trigger with exception handler which rolls back to a savepoint. +# Test proves that there will not be any assert during execution of rolling +# back to savepoint. +# +# Test case 2: +# Create a trigger which calls a procedure which in turn calls an exception +# handler which rolls back to a savepoint. Prove that it doesn't cause any +# assertion during execution. +# +# Test case 3: +# Create a simple trigger which does SAVEPOINT and ROLLBACK TO SAVEPOINT +# and doesn't follow with any other DML statement. Prove that it doesn't cause +# any assertion during execution. +# +# Test case 4: +# Create a trigger with SAVEPOINT and follows with a DML without ROLLBACK TO +# savepoint. Ensure that data is replicated properly. +# +# Test case 5: +# Create a trigger with SAVEPOINT and it does nothing. Do few DMLs following +# the trigger ensure that the data is replicated properly +# +# Test case 6: +# Create a stored function which does SAVEPOINT and ROLLBACK TO +# SAVEPOINT. Do few inserts following the stored function call and ensure that +# no assert is generated on slave and all the rows are replicated to slave. +# +# Test case 7: +# Create a stored function which creates a SAVEPOINT alone and follows with +# DMLs without ROLLBACK TO savepoint. Ensure that data is replicated properly. +# +# Test case 8: +# Create a stored function which has SAVEPOINT inside it and does noting. It +# should follow with other DMLs. Ensure that data is replicated properly. +############################################################################### +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--echo #Test case 1: +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE t3 (f1 INTEGER PRIMARY KEY) ENGINE=INNODB; +DELIMITER |; + +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW +BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK TO event_logging_1; + INSERT t3 VALUES (1); + END; + SAVEPOINT event_logging_1; + INSERT INTO t2 VALUES (1); + RELEASE SAVEPOINT event_logging_1; +END| +DELIMITER ;| + +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); + +--source include/show_binlog_events.inc + +--sync_slave_with_master + +connection master; + +DROP TRIGGER tr1; +DELETE FROM t1; +DELETE FROM t2; +DELETE FROM t3; + +--echo # Test case 2: + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK TO event_logging_2; + INSERT t3 VALUES (3); + END; + SAVEPOINT event_logging_2; + INSERT INTO t2 VALUES (1); + RELEASE SAVEPOINT event_logging_2; +END| + +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW CALL p1()| + +DELIMITER ;| + +INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (1); + +--source include/show_binlog_events.inc + +--sync_slave_with_master + +connection master; + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +DROP PROCEDURE p1; + +--echo # Test case 3: +--source include/rpl_reset.inc +connection master; + +CREATE TABLE t (f1 int(10) unsigned NOT NULL, PRIMARY KEY (f1)) ENGINE=InnoDB; + +--delimiter | +CREATE TRIGGER t_insert_trig AFTER INSERT ON t FOR EACH ROW +BEGIN + SAVEPOINT savepoint_1; + ROLLBACK TO savepoint_1; +END | +--delimiter ; + +INSERT INTO t VALUES (2); +INSERT INTO t VALUES (3); + +--source include/show_binlog_events.inc + +SELECT * FROM t; + +--source include/sync_slave_sql_with_master.inc + +SELECT * FROM t; + +connection master; +DROP TABLE t; + +--echo # Test case 4: +--source include/rpl_reset.inc +connection master; +CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB; +CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB; + +--delimiter | +CREATE TRIGGER t_insert_trig BEFORE INSERT ON t FOR EACH ROW +BEGIN + SAVEPOINT savepoint_1; + INSERT INTO t1 VALUES (5); +END | +--delimiter ; + +INSERT INTO t VALUES (2), (3); +INSERT INTO t1 VALUES (30); +--source include/show_binlog_events.inc + +SELECT * FROM t; +SELECT * FROM t1; +--source include/sync_slave_sql_with_master.inc + +SELECT * FROM t; +SELECT * FROM t1; + +connection master; +DROP TABLE t; +DROP TABLE t1; + +--echo # Test case 5: +--source include/rpl_reset.inc +connection master; +CREATE TABLE t (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB; +CREATE TABLE t1 (f1 int(10) unsigned NOT NULL) ENGINE=InnoDB; + +--delimiter | +CREATE TRIGGER t_insert_trig BEFORE INSERT ON t +FOR EACH ROW +BEGIN + +SAVEPOINT savepoint_1; +END | + +--delimiter ; + +INSERT INTO t VALUES (2), (3); +INSERT INTO t1 VALUES (30); +--source include/show_binlog_events.inc + +SELECT * FROM t; +SELECT * FROM t1; +--source include/sync_slave_sql_with_master.inc + +SELECT * FROM t; +SELECT * FROM t1; + +connection master; +DROP TABLE t; +DROP TABLE t1; + +--echo # Test case 6: +--source include/rpl_reset.inc +connection master; +CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB; +CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB; + +--delimiter | + +CREATE FUNCTION f1() RETURNS INT +BEGIN + SAVEPOINT event_logging_2; + INSERT INTO t1 VALUES (1); + ROLLBACK TO event_logging_2; + RETURN 0; +END| + +--delimiter ; + +BEGIN; +INSERT INTO t2 VALUES (1), (f1()), (2), (4); +COMMIT; +INSERT INTO t2 VALUES (10); +--source include/show_binlog_events.inc + +connection master; +SELECT * FROM t2; +SELECT * FROM t1; +--source include/sync_slave_sql_with_master.inc +SELECT * FROM t2; +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION f1; + +--echo # Test case 7: +--source include/rpl_reset.inc +connection master; +CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB; +CREATE TABLE t2 (f1 INTEGER ) ENGINE=INNODB; + +--delimiter | + +CREATE FUNCTION f1() RETURNS INT +BEGIN + SAVEPOINT event_logging_2; + INSERT INTO t1 VALUES (1); + RETURN 0; +END| + +--delimiter ; + +BEGIN; +INSERT INTO t2 VALUES (1), (f1()), (2), (4); +COMMIT; +INSERT INTO t2 VALUES (10); +--source include/show_binlog_events.inc + +connection master; +SELECT * FROM t2; +SELECT * FROM t1; +--source include/sync_slave_sql_with_master.inc +SELECT * FROM t2; +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION f1; + +--echo # Test case 8: +--source include/rpl_reset.inc +connection master; +CREATE TABLE t1 (f1 INTEGER ) ENGINE=INNODB; + +--delimiter | + +CREATE FUNCTION f1() RETURNS INT +BEGIN + SAVEPOINT event_logging_2; + RETURN 0; +END| + +--delimiter ; + +BEGIN; +INSERT INTO t1 VALUES (1), (f1()), (2), (4); +COMMIT; +INSERT INTO t1 VALUES (10); +--source include/show_binlog_events.inc + +connection master; +SELECT * FROM t1; +--source include/sync_slave_sql_with_master.inc +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +DROP FUNCTION f1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test b/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test new file mode 100644 index 00000000..3d4b8f1e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_show_relaylog_events.test @@ -0,0 +1,19 @@ +# BUG#28777 SHOW BINLOG EVENTS does not work on relay log files +# +# GOAL +# ==== +# +# Test that SHOW BINLOG EVENTS and the new SHOW RELAYLOG EVENTS works after +# the patch, both on master and slave. +# +# HOW +# === +# +# This test issues SHOW [BINLOG|RELAYLOG] EVENTS both on master and slave after +# some statements have been issued. + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +-- source include/rpl_show_relaylog_events.inc +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp001.test b/mysql-test/suite/rpl/t/rpl_row_sp001.test new file mode 100644 index 00000000..99db5e7f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp001.test @@ -0,0 +1,145 @@ +############################################################################# +# This test is being created to test out the non deterministic items with # +# row based replication. # +# Original Author: JBM # +# Original Date: Aug/09/2005 # +# Updated: Aug/29/2005 +############################################################################# +# Test: Includes two stored procedure tests. First test uses SP to insert # +# values from RAND() and NOW() into a table. # +# The second test uses SP with CASE structure to decide what to text # +# to update a given table with. # +############################################################################ + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +-- disable_query_log +-- disable_result_log + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; + +-- enable_query_log +-- enable_result_log + +# Begin test section 1 for non deterministic SP +let $message=<Begin test section 1 (non deterministic SP)>; +--source include/show_msg.inc + +create table test.t1 (n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n)); + +delimiter //; +create procedure test.p1() +begin + INSERT INTO test.t1 (f,d) VALUES (RAND(),NOW()); +end// +delimiter ;// + +# show binlog events; + +-- disable_query_log +-- disable_result_log +SET @wait_count=1; +let $1=10; +while ($1) +{ + call test.p1(); + let $wait_condition= SELECT COUNT(*) = @wait_count FROM test.t1; + -- source include/wait_condition.inc + -- disable_query_log + SET @wait_count = @wait_count + 1; + dec $1; +} +-- enable_result_log +-- enable_query_log + +## Used for debugging +#show binlog events; +#select * from test.t1; +#sync_slave_with_master; +#select * from test.t1; +#connection master; + +let $message=<End test section 1 (non deterministic SP)>; +--source include/show_msg.inc + + +CREATE TABLE test.t2 (a INT NOT NULL AUTO_INCREMENT, t CHAR(4), PRIMARY KEY(a)); + +delimiter //; +CREATE PROCEDURE test.p2(n int) +begin +CASE n +WHEN 1 THEN + UPDATE test.t2 set t ='Tex'; +WHEN 2 THEN + UPDATE test.t2 set t ='SQL'; +ELSE + UPDATE test.t2 set t ='NONE'; +END CASE; +end// +delimiter ;// + +INSERT INTO test.t2 VALUES(NULL,'NEW'),(NULL,'NEW'),(NULL,'NEW'),(NULL,'NEW'); + +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + +connection master; +call test.p2(1); +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + + +connection master; +call test.p2(2); +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + +connection master; +call test.p2(3); +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY a; + +##Used for debugging +#show binlog events; + +# time to dump the databases and so we can see if they match + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp001_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp001_slave.sql + +# First lets cleanup + +connection master; +DROP PROCEDURE test.p1; +DROP PROCEDURE test.p2; +DROP TABLE test.t1; +DROP TABLE test.t2; +sync_slave_with_master; + +# Lets compare. Note: If they match test will pass, if they do not match +# the test will show that the diff statement failed and not reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching :-) Failed dump files +# will be located in $MYSQLTEST_VARDIR/tmp + +diff_files $MYSQLTEST_VARDIR/tmp/sp001_master.sql $MYSQLTEST_VARDIR/tmp/sp001_slave.sql; + +# If all is good, when can cleanup our dump files. +--remove_file $MYSQLTEST_VARDIR/tmp/sp001_master.sql +--remove_file $MYSQLTEST_VARDIR/tmp/sp001_slave.sql + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test b/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test new file mode 100644 index 00000000..f096c157 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp002_innodb.test @@ -0,0 +1,3 @@ +-- source include/have_innodb.inc +let $engine_type=INNODB; +-- source include/rpl_row_sp002.test diff --git a/mysql-test/suite/rpl/t/rpl_row_sp003.test b/mysql-test/suite/rpl/t/rpl_row_sp003.test new file mode 100644 index 00000000..0a361202 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp003.test @@ -0,0 +1,16 @@ +################################# +# Wrapper for rpl_row_sp003.test# +################################# +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +# Slow test, don't run during staging part +-- source include/not_staging.inc +--source include/long_test.inc +-- source include/master-slave.inc + +let $engine_type=INNODB; +-- source include/rpl_row_sp003.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp005.test b/mysql-test/suite/rpl/t/rpl_row_sp005.test new file mode 100644 index 00000000..865f2e94 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp005.test @@ -0,0 +1,102 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/15/2005 # +# Updated: Aug/29/2005: Removed sleeps # +############################################################################# +# Test: Tests SPs with cursors, flow logic, and alter sp. In addition the # +# tests SPs with insert and update operations. # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t3; +--enable_warnings +# End of cleanup + +# Begin test section 1 +CREATE TABLE IF NOT EXISTS test.t1(id INT, data CHAR(16),PRIMARY KEY(id)); +CREATE TABLE IF NOT EXISTS test.t2(id2 INT,PRIMARY KEY(id2)); +CREATE TABLE IF NOT EXISTS test.t3(id3 INT,PRIMARY KEY(id3), c CHAR(16)); + +delimiter |; +CREATE PROCEDURE test.p1() +BEGIN +DECLARE done INT DEFAULT 0; + DECLARE spa CHAR(16); + DECLARE spb,spc INT; + DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1 ORDER BY id; + DECLARE cur2 CURSOR FOR SELECT id2 FROM test.t2 ORDER BY id2; + DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; + + OPEN cur1; + OPEN cur2; + + REPEAT + FETCH cur1 INTO spb, spa; + FETCH cur2 INTO spc; + IF NOT done THEN + IF spb < spc THEN + INSERT INTO test.t3 VALUES (spb,spa); + ELSE + INSERT INTO test.t3 VALUES (spc,spa); + END IF; + END IF; + UNTIL done END REPEAT; + + CLOSE cur1; + CLOSE cur2; +END| +CREATE PROCEDURE test.p2() +BEGIN + INSERT INTO test.t1 VALUES (4,'MySQL'),(20,'ROCKS'),(11,'Texas'),(10,'kyle'); + INSERT INTO test.t2 VALUES (4),(2),(1),(3); + UPDATE test.t1 SET id=id+4 WHERE id=4; +END| +delimiter ;| + +CALL test.p2(); +SELECT * FROM test.t1 ORDER BY id; +SELECT * FROM test.t2 ORDER BY id2; + +sync_slave_with_master; +SELECT * FROM test.t1 ORDER BY id; +SELECT * FROM test.t2 ORDER BY id2; + +connection master; +CALL test.p1(); + +let $wait_condition= SELECT COUNT(*) = 4 FROM t3; +--source include/wait_condition.inc +save_master_pos; +SELECT * FROM test.t3 ORDER BY id3; + +sync_slave_with_master; +SELECT * FROM test.t3 ORDER BY id3; + +connection master; + +ALTER PROCEDURE test.p1 MODIFIES SQL DATA; +#show binlog events; + +# Cleanup + +connection master; +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test b/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test new file mode 100644 index 00000000..c575a105 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp006_InnoDB.test @@ -0,0 +1,12 @@ +################################# +# Wrapper for rpl_row_sp006.test# +################################# +######################################################## +# By JBM 2005-02-15 Wrapped to allow reuse of test code# +######################################################## +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=InnoDB; +-- source include/rpl_row_sp006.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test b/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test new file mode 100644 index 00000000..6eaafa8c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp007_innodb.test @@ -0,0 +1,3 @@ +-- source include/have_innodb.inc +let $engine_type=INNODB; +-- source include/rpl_row_sp007.test diff --git a/mysql-test/suite/rpl/t/rpl_row_sp008.test b/mysql-test/suite/rpl/t/rpl_row_sp008.test new file mode 100644 index 00000000..74a988ee --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp008.test @@ -0,0 +1,52 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/15/2005 # +# Update: 08/29/2005 Remove sleep # +############################################################################# +# TEST: Use SQL_CALC_FOUND_ROWS and insert results into a table inside a sp # +############################################################################# + + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP TABLE IF EXISTS test.t2; +--enable_warnings +# End of cleanup + + + +# Begin test section 1 +CREATE TABLE test.t1 (a INT,PRIMARY KEY(a)); +CREATE TABLE test.t2 (a INT,PRIMARY KEY(a)); +INSERT INTO test.t1 VALUES(1),(2); + +delimiter |; +CREATE PROCEDURE test.p1() +BEGIN + SELECT SQL_CALC_FOUND_ROWS * FROM test.t1 LIMIT 1; + INSERT INTO test.t2 VALUES(FOUND_ROWS()); +END| +delimiter ;| + +CALL test.p1(); +SELECT * FROM test.t2; + +sync_slave_with_master; +SELECT * FROM test.t2; + +# Cleanup + +connection master; +DROP PROCEDURE IF EXISTS test.p1; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp009.test b/mysql-test/suite/rpl/t/rpl_row_sp009.test new file mode 100644 index 00000000..83d743b8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp009.test @@ -0,0 +1,98 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +# Updated: 08/29/2005 removed sleeps and added master pos save and snyc # +############################################################################# +#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=12168 # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; + + +# Begin test section 1 +CREATE TABLE test.t1 (a INT, PRIMARY KEY(a)); +INSERT INTO test.t1 VALUES (1),(2),(3),(4); +CREATE TABLE test.t2 (a INT, PRIMARY KEY(a)); + +delimiter |; +CREATE PROCEDURE test.p1 (arg1 CHAR(1)) +BEGIN + DECLARE b, c INT; + IF arg1 = 'a' THEN + BEGIN + DECLARE cur1 CURSOR FOR SELECT A FROM test.t1 WHERE a % 2; + DECLARE continue handler for not found set b = 1; + SET b = 0; + OPEN cur1; + c1_repeat: REPEAT + FETCH cur1 INTO c; + IF (b = 1) THEN + LEAVE c1_repeat; + END IF; + + INSERT INTO test.t2 VALUES (c); + UNTIL b = 1 + END REPEAT; + CLOSE cur1; + END; + END IF; + IF arg1 = 'b' THEN + BEGIN + DECLARE cur2 CURSOR FOR SELECT a FROM test.t1 WHERE NOT a % 2; + DECLARE continue handler for not found set b = 1; + SET b = 0; + OPEN cur2; + c2_repeat: REPEAT + FETCH cur2 INTO c; + IF (b = 1) THEN + LEAVE c2_repeat; + END IF; + + INSERT INTO test.t2 VALUES (c); + UNTIL b = 1 + END REPEAT; + CLOSE cur2; + END; + END IF; +END| +delimiter ;| + +CALL test.p1('a'); +SELECT * FROM test.t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM test.t2 ORDER BY a; +connection master; +truncate test.t2; + +# this next call fails, but should not +call test.p1('b'); +select * from test.t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM test.t2 ORDER BY a; + +connection master; +truncate test.t2; +SELECT * FROM test.t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM test.t2 ORDER BY a; + +# Cleanup +connection master; +#show binlog events; +DROP PROCEDURE test.p1; +DROP TABLE test.t1; +DROP TABLE test.t2; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp010.test b/mysql-test/suite/rpl/t/rpl_row_sp010.test new file mode 100644 index 00000000..aad7edcd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp010.test @@ -0,0 +1,77 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +# Update: 08/29/2005 remove sleep added master pos save and sync # +############################################################################# +#TEST: Taken and modfied from http://bugs.mysql.com/bug.php?id=11126 # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; +DROP PROCEDURE IF EXISTS test.p4; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; + + +# Begin test section 1 +delimiter |; +CREATE PROCEDURE test.p1() +BEGIN + INSERT INTO test.t1 VALUES(2); +END| +CREATE PROCEDURE test.p2() +BEGIN + DROP TEMPORARY TABLE IF EXISTS test.t1; + CREATE TEMPORARY TABLE test.t1 (a int, PRIMARY KEY(a)); + INSERT INTO test.t1 VALUES(1); + CALL test.p1(); +END| +delimiter ;| +CALL test.p2(); +SELECT * FROM test.t1 ORDER BY a; + +sync_slave_with_master; +show tables; + +connection master; +delimiter |; +CREATE PROCEDURE test.p3() +BEGIN + INSERT INTO test.t2 VALUES(7); +END| +CREATE PROCEDURE test.p4() +BEGIN + DROP TABLE IF EXISTS test.t2; + CREATE TABLE test.t2 (a int, PRIMARY KEY(a)); + INSERT INTO test.t2 VALUES(6); + CALL test.p3(); +END| +delimiter ;| +CALL test.p4(); +SELECT * FROM test.t2 ORDER BY a; + +sync_slave_with_master; +SELECT * FROM test.t2 ORDER BY a; + +# Cleanup +connection master; +#show binlog events; +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; +DROP PROCEDURE IF EXISTS test.p4; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp011.test b/mysql-test/suite/rpl/t/rpl_row_sp011.test new file mode 100644 index 00000000..d2a323fa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp011.test @@ -0,0 +1,112 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +# Updated: 08/29/2005 turned on diff and commented out debug SQL statements# +############################################################################# +#TEST: SP to test alter table and nested SP calls # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; +DROP PROCEDURE IF EXISTS test.p4; +DROP PROCEDURE IF EXISTS test.p5; +DROP PROCEDURE IF EXISTS test.p6; +DROP PROCEDURE IF EXISTS test.p7; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; + + +# Begin test section 1 +CREATE TABLE test.t1 (a int, PRIMARY KEY(a)); +INSERT INTO test.t1 VALUES (1); + +delimiter |; +CREATE PROCEDURE test.p1() +BEGIN + ALTER TABLE test.t1 ADD COLUMN b CHAR(4) AFTER a; + UPDATE test.t1 SET b = 'rbr' WHERE a = 1; + CALL test.p2(); +END| +CREATE PROCEDURE test.p2() +BEGIN + ALTER TABLE test.t1 ADD COLUMN f FLOAT AFTER b; + UPDATE test.t1 SET f = RAND() WHERE a = 1; + CALL test.p3(); +END| +CREATE PROCEDURE test.p3() +BEGIN + ALTER TABLE test.t1 RENAME test.t2; + CALL test.p4(); +END| +CREATE PROCEDURE test.p4() +BEGIN + ALTER TABLE test.t2 ADD INDEX (f); + ALTER TABLE test.t2 CHANGE a a INT UNSIGNED NOT NULL AUTO_INCREMENT; + INSERT INTO test.t2 VALUES (NULL,'TEST',RAND()); + CALL test.p5(); +END| +CREATE PROCEDURE test.p5() +BEGIN + ALTER TABLE test.t2 ORDER BY f; + INSERT INTO test.t2 VALUES (NULL,'STM',RAND()); + CALL test.p6(); +END| +CREATE PROCEDURE test.p6() +BEGIN + ALTER TABLE test.t2 ADD COLUMN b2 CHAR(4) FIRST; + ALTER TABLE test.t2 ADD COLUMN to_drop BIT(8) AFTER b2; + INSERT INTO test.t2 VALUES ('new',1,NULL,'STM',RAND()); + CALL test.p7(); +END| +CREATE PROCEDURE test.p7() +BEGIN + ALTER TABLE test.t2 DROP COLUMN to_drop; + INSERT INTO test.t2 VALUES ('gone',NULL,'STM',RAND()); +END| +delimiter ;| +CALL test.p1(); + +#SELECT * FROM test.t2; +sync_slave_with_master; +#SELECT * FROM test.t2; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp011_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp011_slave.sql + +# Cleanup +connection master; +#show binlog events; +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; +DROP PROCEDURE IF EXISTS test.p4; +DROP PROCEDURE IF EXISTS test.p5; +DROP PROCEDURE IF EXISTS test.p6; +DROP PROCEDURE IF EXISTS test.p7; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +sync_slave_with_master; + +# Lets compare. Note: If they match test will pass, if they do not match +# the test will show that the diff statement failed and not reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching :-) Failed test +# Will leave dump files in $MYSQLTEST_VARDIR/tmp + +diff_files $MYSQLTEST_VARDIR/tmp/sp011_master.sql $MYSQLTEST_VARDIR/tmp/sp011_slave.sql; + +# If all is good, when can cleanup our dump files. +--remove_file $MYSQLTEST_VARDIR/tmp/sp011_master.sql +--remove_file $MYSQLTEST_VARDIR/tmp/sp011_slave.sql + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_sp012.test b/mysql-test/suite/rpl/t/rpl_row_sp012.test new file mode 100644 index 00000000..2b8549bf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_sp012.test @@ -0,0 +1,74 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/22/2005 # +# Update: 08/29/2005 Added save pos and sync # +############################################################################# +#TEST: SP to test security and current_user and user # +############################################################################# + + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/not_embedded.inc +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; + + +# Begin test section 1 +# Create user user1 with no particular access rights +create user user1@localhost; +grant usage on *.* to user1@localhost; +flush privileges; + +SELECT CURRENT_USER(); +SELECT USER(); +CREATE PROCEDURE test.p1 () SQL SECURITY INVOKER SELECT CURRENT_USER(), USER(); +CREATE PROCEDURE test.p2 () SQL SECURITY DEFINER CALL test.p1(); +CREATE PROCEDURE test.p3 () SQL SECURITY INVOKER CALL test.p1(); +GRANT EXECUTE ON PROCEDURE p1 TO user1@localhost; +GRANT EXECUTE ON PROCEDURE p2 TO user1@localhost; +GRANT EXECUTE ON PROCEDURE p3 TO user1@localhost; +set sql_mode=default; + +# Need to wait for the rights to be applied at the slave +sync_slave_with_master; + +connect (muser1,localhost,user1,,); +connection muser1; +SELECT CURRENT_USER(); +SELECT USER(); +CALL test.p3(); +CALL test.p2(); + +connect (suser1,127.0.0.1,user1,,test,$SLAVE_MYPORT,); + +connection master; +save_master_pos; +connection suser1; +sync_with_master; + +SELECT CURRENT_USER(); +SELECT USER(); +CALL test.p3(); +CALL test.p2(); + +# Cleanup +connection master; +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p3; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP USER user1@localhost; +sync_slave_with_master; + +# End of 5.0 test case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_spatial.test b/mysql-test/suite/rpl/t/rpl_row_spatial.test new file mode 100644 index 00000000..00c3dd7c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_spatial.test @@ -0,0 +1,17 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +CREATE TABLE t1 (g POINT NOT NULL, SPATIAL INDEX(g)); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 1)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(1 2)')); +INSERT INTO t1 VALUES (ST_GEOMFROMTEXT('Point(2 2)')); +DELETE FROM t1 where MBREqual(g, ST_GEOMFROMTEXT('Point(1 2)')); + +--sync_slave_with_master +select count(*) from t1; + +--connection master +DELETE FROM t1; +drop table t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test b/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test new file mode 100644 index 00000000..e1ecf702 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_tabledefs_2myisam.test @@ -0,0 +1,9 @@ + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +let $engine_type = 'MyISAM'; +-- source include/rpl_row_tabledefs.test + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test b/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test new file mode 100644 index 00000000..49abc84c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_tabledefs_3innodb.test @@ -0,0 +1,10 @@ + +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +let $engine_type = 'InnoDB'; +-- source include/rpl_row_tabledefs.test + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test new file mode 100644 index 00000000..d3a115e9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -0,0 +1,338 @@ +# +# BUG#42749: infinite loop writing to row based binlog - processlist shows +# "freeing items" +# +# +# WHY +# === +# +# This bug would make table map event to report data_written one +# byte less than what would actually be written in its body. This +# would cause one byte shorter event end_log_pos. The ultimate +# impact was that it would make fixing the position in +# MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. +# +# HOW +# === +# +# Checking that the patch fixes the problem is done as follows: +# +# i) one table with m_field_metadata sized at 290 +# ii) an insert is performed; +# iii) the logs are flushed; +# iv) mysqlbinlog is used to check if it succeeds. +# +# In step iv), before the bug was fixed, the test case would fail +# with mysqlbinlog reporting that it was unable to succeed in +# reading the event. + +-- source include/have_innodb.inc +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +-- disable_warnings +DROP TABLE IF EXISTS `t1`; +-- enable_warnings + +-- echo ### TABLE with field_metadata_size == 290 +CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(30) NOT NULL, + `c3` varchar(30) DEFAULT NULL, + `c4` varchar(30) DEFAULT NULL, + `c5` varchar(30) DEFAULT NULL, + `c6` varchar(30) DEFAULT NULL, + `c7` varchar(30) DEFAULT NULL, + `c8` varchar(30) DEFAULT NULL, + `c9` varchar(30) DEFAULT NULL, + `c10` varchar(30) DEFAULT NULL, + `c11` varchar(30) DEFAULT NULL, + `c12` varchar(30) DEFAULT NULL, + `c13` varchar(30) DEFAULT NULL, + `c14` varchar(30) DEFAULT NULL, + `c15` varchar(30) DEFAULT NULL, + `c16` varchar(30) DEFAULT NULL, + `c17` varchar(30) DEFAULT NULL, + `c18` varchar(30) DEFAULT NULL, + `c19` varchar(30) DEFAULT NULL, + `c20` varchar(30) DEFAULT NULL, + `c21` varchar(30) DEFAULT NULL, + `c22` varchar(30) DEFAULT NULL, + `c23` varchar(30) DEFAULT NULL, + `c24` varchar(30) DEFAULT NULL, + `c25` varchar(30) DEFAULT NULL, + `c26` varchar(30) DEFAULT NULL, + `c27` varchar(30) DEFAULT NULL, + `c28` varchar(30) DEFAULT NULL, + `c29` varchar(30) DEFAULT NULL, + `c30` varchar(30) DEFAULT NULL, + `c31` varchar(30) DEFAULT NULL, + `c32` varchar(30) DEFAULT NULL, + `c33` varchar(30) DEFAULT NULL, + `c34` varchar(30) DEFAULT NULL, + `c35` varchar(30) DEFAULT NULL, + `c36` varchar(30) DEFAULT NULL, + `c37` varchar(30) DEFAULT NULL, + `c38` varchar(30) DEFAULT NULL, + `c39` varchar(30) DEFAULT NULL, + `c40` varchar(30) DEFAULT NULL, + `c41` varchar(30) DEFAULT NULL, + `c42` varchar(30) DEFAULT NULL, + `c43` varchar(30) DEFAULT NULL, + `c44` varchar(30) DEFAULT NULL, + `c45` varchar(30) DEFAULT NULL, + `c46` varchar(30) DEFAULT NULL, + `c47` varchar(30) DEFAULT NULL, + `c48` varchar(30) DEFAULT NULL, + `c49` varchar(30) DEFAULT NULL, + `c50` varchar(30) DEFAULT NULL, + `c51` varchar(30) DEFAULT NULL, + `c52` varchar(30) DEFAULT NULL, + `c53` varchar(30) DEFAULT NULL, + `c54` varchar(30) DEFAULT NULL, + `c55` varchar(30) DEFAULT NULL, + `c56` varchar(30) DEFAULT NULL, + `c57` varchar(30) DEFAULT NULL, + `c58` varchar(30) DEFAULT NULL, + `c59` varchar(30) DEFAULT NULL, + `c60` varchar(30) DEFAULT NULL, + `c61` varchar(30) DEFAULT NULL, + `c62` varchar(30) DEFAULT NULL, + `c63` varchar(30) DEFAULT NULL, + `c64` varchar(30) DEFAULT NULL, + `c65` varchar(30) DEFAULT NULL, + `c66` varchar(30) DEFAULT NULL, + `c67` varchar(30) DEFAULT NULL, + `c68` varchar(30) DEFAULT NULL, + `c69` varchar(30) DEFAULT NULL, + `c70` varchar(30) DEFAULT NULL, + `c71` varchar(30) DEFAULT NULL, + `c72` varchar(30) DEFAULT NULL, + `c73` varchar(30) DEFAULT NULL, + `c74` varchar(30) DEFAULT NULL, + `c75` varchar(30) DEFAULT NULL, + `c76` varchar(30) DEFAULT NULL, + `c77` varchar(30) DEFAULT NULL, + `c78` varchar(30) DEFAULT NULL, + `c79` varchar(30) DEFAULT NULL, + `c80` varchar(30) DEFAULT NULL, + `c81` varchar(30) DEFAULT NULL, + `c82` varchar(30) DEFAULT NULL, + `c83` varchar(30) DEFAULT NULL, + `c84` varchar(30) DEFAULT NULL, + `c85` varchar(30) DEFAULT NULL, + `c86` varchar(30) DEFAULT NULL, + `c87` varchar(30) DEFAULT NULL, + `c88` varchar(30) DEFAULT NULL, + `c89` varchar(30) DEFAULT NULL, + `c90` varchar(30) DEFAULT NULL, + `c91` varchar(30) DEFAULT NULL, + `c92` varchar(30) DEFAULT NULL, + `c93` varchar(30) DEFAULT NULL, + `c94` varchar(30) DEFAULT NULL, + `c95` varchar(30) DEFAULT NULL, + `c96` varchar(30) DEFAULT NULL, + `c97` varchar(30) DEFAULT NULL, + `c98` varchar(30) DEFAULT NULL, + `c99` varchar(30) DEFAULT NULL, + `c100` varchar(30) DEFAULT NULL, + `c101` varchar(30) DEFAULT NULL, + `c102` varchar(30) DEFAULT NULL, + `c103` varchar(30) DEFAULT NULL, + `c104` varchar(30) DEFAULT NULL, + `c105` varchar(30) DEFAULT NULL, + `c106` varchar(30) DEFAULT NULL, + `c107` varchar(30) DEFAULT NULL, + `c108` varchar(30) DEFAULT NULL, + `c109` varchar(30) DEFAULT NULL, + `c110` varchar(30) DEFAULT NULL, + `c111` varchar(30) DEFAULT NULL, + `c112` varchar(30) DEFAULT NULL, + `c113` varchar(30) DEFAULT NULL, + `c114` varchar(30) DEFAULT NULL, + `c115` varchar(30) DEFAULT NULL, + `c116` varchar(30) DEFAULT NULL, + `c117` varchar(30) DEFAULT NULL, + `c118` varchar(30) DEFAULT NULL, + `c119` varchar(30) DEFAULT NULL, + `c120` varchar(30) DEFAULT NULL, + `c121` varchar(30) DEFAULT NULL, + `c122` varchar(30) DEFAULT NULL, + `c123` varchar(30) DEFAULT NULL, + `c124` varchar(30) DEFAULT NULL, + `c125` varchar(30) DEFAULT NULL, + `c126` varchar(30) DEFAULT NULL, + `c127` varchar(30) DEFAULT NULL, + `c128` varchar(30) DEFAULT NULL, + `c129` varchar(30) DEFAULT NULL, + `c130` varchar(30) DEFAULT NULL, + `c131` varchar(30) DEFAULT NULL, + `c132` varchar(30) DEFAULT NULL, + `c133` varchar(30) DEFAULT NULL, + `c134` varchar(30) DEFAULT NULL, + `c135` varchar(30) DEFAULT NULL, + `c136` varchar(30) DEFAULT NULL, + `c137` varchar(30) DEFAULT NULL, + `c138` varchar(30) DEFAULT NULL, + `c139` varchar(30) DEFAULT NULL, + `c140` varchar(30) DEFAULT NULL, + `c141` varchar(30) DEFAULT NULL, + `c142` varchar(30) DEFAULT NULL, + `c143` varchar(30) DEFAULT NULL, + `c144` varchar(30) DEFAULT NULL, + `c145` varchar(30) DEFAULT NULL, + `c146` varchar(30) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB; + +LOCK TABLES `t1` WRITE; +INSERT INTO `t1`(c2) VALUES ('1'); +FLUSH LOGS; + +-- sync_slave_with_master +-- connection master + +-- echo ### assertion: the slave replicated event successfully and tables match +-- let $diff_tables= master:t1, slave:t1 +-- source include/diff_tables.inc + +DROP TABLE `t1`; + +-- connection master +-- sync_slave_with_master +-- connection master + +-- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. + +-- let $MYSQLD_DATADIR= `SELECT @@datadir` +-- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog + +############################################################# +# BUG#50018: binlog corruption when table has many columns +# +# Same test from BUG#42749, but now we generate some SQL which +# creates and inserts into tables with metadata size from 249 +# to 258. +# +# The test works as follows: +# 1. SQL for several CREATE TABLE and INSERTS are generated +# into a file. +# 2. This file is then "sourced" +# 3. The slave is synchronized with the master +# 4. FLUSH LOGS on master +# 5. Compare tables on master and slave. +# 6. run mysqlbinlog on master's binary log +# +# Steps #5 and #6 assert that binary log is not corrupted +# in both cases: when slave is replaying events and when +# mysqlbinlog is used to read the binary log + +--source include/rpl_reset.inc +-- connection master + +# Create several tables with field_metadata_size ranging +# from 249 to 258 (so that we cover 251 and 255 range). +# This should exercise the switch between using 1 or 3 +# bytes to pack m_field_metadata_size. +# +# Each varchar field takes up to 2 metadata bytes, see: +# +# Field_varstring::save_field_metadata (field.cc) +# +# The float field takes 1 byte, see: +# +# Field_float::save_field_metadata (field.cc) +# + +-- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql +-- let B50018_FILE= $generated_sql + +-- echo ### action: generating several tables with different metadata +-- echo ### sizes (resorting to perl) +-- perl +my $file= $ENV{'B50018_FILE'}; +open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ; + +my $tables= ""; +my $ntables= 10; +my $base_ncols= 124; + +for my $i (1..$ntables) +{ + my $ncols= $base_ncols + $i; + my $metadata_size= $ncols_variable * 2 + 1; + + print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n"; + print FILE "CREATE TABLE t$i (\n"; + for my $n (1..$base_ncols) + { + print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n"; + } + + for my $n (1..$i) + { + print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0"; + if ($n < $i) + { + print FILE ",\n"; + } + } + + print FILE ") Engine=InnoDB;\n"; + + $tables.= " t$i WRITE"; + if ($i < $ntables) + { + $tables .=","; + } + + print FILE "LOCK TABLES t$i WRITE;\n"; + print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n"; + print FILE "UNLOCK TABLES;"; +} + +close(FILE); + +EOF + +## we don't need this in the result file +## however, for debugging purposes you +## may want to reactivate query logging +-- disable_query_log +-- source $generated_sql +-- enable_query_log + +-- sync_slave_with_master +-- connection master + +FLUSH LOGS; + +-- let $ntables=10 +while($ntables) +{ + -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables + -- let $diff_tables= master:t$ntables, slave:t$ntables + -- source include/diff_tables.inc + + -- connection master + -- disable_query_log + -- eval DROP TABLE t$ntables + -- enable_query_log + -- sync_slave_with_master + -- connection master + + -- dec $ntables +} + +-- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to +-- echo ### detect failure. Before the patch mysqlbinlog would find +-- echo ### a corrupted event, thence would fail. +-- let $MYSQLD_DATADIR= `SELECT @@datadir` +-- exec $MYSQL_BINLOG -v --hexdump $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog + +## clean up +## For debugging purposes you might want not to remove these +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- remove_file $generated_sql +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt b/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt new file mode 100644 index 00000000..83ed8522 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt-master.opt @@ -0,0 +1 @@ +--binlog-format=row diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt b/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt new file mode 100644 index 00000000..af3a2119 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt-slave.opt @@ -0,0 +1 @@ +--binlog-format=statement diff --git a/mysql-test/suite/rpl/t/rpl_row_to_stmt.test b/mysql-test/suite/rpl/t/rpl_row_to_stmt.test new file mode 100644 index 00000000..5ca583d8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_to_stmt.test @@ -0,0 +1,23 @@ +# +# check that master starterd with log-format=ROW replication can replicate to +# slave started with log-format=STATEMENT +# + +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +use test; + +create table t1 (a int primary key); +insert into t1 values (1),(2),(3),(4),(5); +update t1 set a=a*10; + +sync_slave_with_master; +use test; +select * from t1; +source include/show_binlog_events.inc; + +connection master; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_trig001.test b/mysql-test/suite/rpl/t/rpl_row_trig001.test new file mode 100644 index 00000000..39f2662b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trig001.test @@ -0,0 +1,116 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/09/2005 # +############################################################################# +# TEST: Use after insert and before inset triggers and stored procdures to # +# Update and insert data # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +-- disable_query_log +-- disable_result_log + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p2; +DROP PROCEDURE IF EXISTS test.p3; +--error 0,1360 +DROP TRIGGER test.t2_ai; +--error 0,1360 +DROP TRIGGER test.t3_bi_t2; +--error 0,1360 +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; + + +# test section 1, lets add a trigger to the mix. Taken from bug #12280 +let $message=<Begin test section 1 (Tiggers & SP)>; +--source include/show_msg.inc + +CREATE TABLE test.t1 (n MEDIUMINT NOT NULL, d DATETIME, PRIMARY KEY(n)); +CREATE TABLE test.t2 (n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n)); +CREATE TABLE test.t3 (n MEDIUMINT NOT NULL AUTO_INCREMENT, d DATETIME, PRIMARY KEY(n)); + +INSERT INTO test.t1 VALUES (1,NOW()); + +delimiter //; +CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW UPDATE test.t1 SET d=NOW() where n = 1// +CREATE PROCEDURE test.p3() +BEGIN + INSERT INTO test.t3 (d) VALUES (NOW()); +END// +CREATE TRIGGER test.t3_bi_t2 BEFORE INSERT ON test.t2 FOR EACH ROW CALL test.p3()// +CREATE PROCEDURE test.p2() +BEGIN + INSERT INTO test.t2 (f,d) VALUES (RAND(),NOW()); +END// +delimiter ;// + +# Make sure that all definition have propagated to the slave +sync_slave_with_master; + +connection master; +-- disable_query_log +-- disable_result_log +SET @wait_count = 1; +let $1=10; +while ($1) +{ + CALL test.p2(); + let $wait_condition= SELECT COUNT(*) = @wait_count FROM test.t3; + --source include/wait_condition.inc + --disable_query_log + SET @wait_count = @wait_count + 1; + dec $1; +} +-- enable_result_log +-- enable_query_log + +# Just a precaution to make sure all changes have made it over to the +# slave +connection master; +let $count = `select count(*) from t1`; +eval INSERT INTO test.t1 VALUES ($count+1, NOW()); +sync_slave_with_master; + +#show binlog events; +#select * from test.t2; +#select * from test.t3; +#connection slave; +#select * from test.t2; +#select * from test.t3; + +let $message=<End test section 2 (Tiggers & SP)>; +--source include/show_msg.inc + +# time to dump the databases and so we can see if they match + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trig001_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trig001_slave.sql + +# Cleanup +connection master; +DROP PROCEDURE test.p2; +DROP PROCEDURE test.p3; +DROP TRIGGER test.t2_ai; +DROP TRIGGER test.t3_bi_t2; +DROP TABLE test.t1; +DROP TABLE test.t2; +DROP TABLE test.t3; +sync_slave_with_master; + +# Lets compare. Note: If they match test will pass, if they do not match +# the test will show that the diff statement failed and not reject file +# will be created. You will need to go to the mysql-test dir and diff +# the files your self to see what is not matching :-) Failed tests +# will leave dump files in $MYSQLTEST_VARDIR/tmp + +diff_files $MYSQLTEST_VARDIR/tmp/trig001_master.sql $MYSQLTEST_VARDIR/tmp/trig001_slave.sql; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_trig002.test b/mysql-test/suite/rpl/t/rpl_row_trig002.test new file mode 100644 index 00000000..f04d1e6d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trig002.test @@ -0,0 +1,77 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/14/2005 # +# Updated: 08/29/2005 added save master pos and sync with master # +############################################################################# +# TEST: Taken and modified from BUG#12048 After Insert updates replication # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +#-- disable_query_log +#-- disable_result_log + +# Begin clean up test section +connection master; +--disable_warnings +--error 0,1360 +DROP TRIGGER test.t2_ai; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +--enable_warnings + +# test section 1, Taken from bug #12408 + +CREATE TABLE test.t2 (value CHAR(30),domain_id INT, mailaccount_id INT, program CHAR(30),keey CHAR(30),PRIMARY KEY(domain_id)); + +CREATE TABLE test.t3 (value CHAR(30),domain_id INT, mailaccount_id INT, program CHAR(30),keey CHAR(30),PRIMARY KEY(domain_id)); + +CREATE TABLE test.t1 (id INT,domain CHAR(30),PRIMARY KEY(id)); + +delimiter |; +CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW UPDATE test.t3 ms, test.t1 d SET ms.value='No' WHERE ms.domain_id = (SELECT max(id) FROM test.t1 WHERE domain='example.com') AND ms.mailaccount_id IS NULL AND ms.program='spamfilter' AND ms.keey='scan_incoming'| +delimiter ;| + +INSERT INTO test.t1 VALUES (1, 'example.com'),(2, 'mysql.com'),(3, 'earthmotherwear.com'), (4, 'yahoo.com'),(5, 'example.com'); + +SELECT * FROM test.t1 ORDER BY id; +#show binlog events; +sync_slave_with_master; +SELECT * FROM test.t1 ORDER BY id; +connection master; + +INSERT INTO test.t3 VALUES ('Yes', 5, NULL, 'spamfilter','scan_incoming'); +INSERT INTO test.t3 VALUES ('Yes', 1, NULL, 'spamfilter','scan_incoming'); +INSERT INTO test.t2 VALUES ('Yes', 1, NULL, 'spamfilter','scan_incoming'); + +select * from test.t2; +--sorted_result +select * from test.t3; +sync_slave_with_master; +select * from test.t2; +--sorted_result +select * from test.t3; +connection master; + +DELETE FROM test.t1 WHERE id = 1; + +SELECT * FROM test.t1 ORDER BY id; +connection master; +SELECT * FROM test.t1 ORDER BY id; +sync_slave_with_master; +SELECT * FROM test.t1 ORDER BY id; + +# Cleanup +connection master; +#show binlog events; +DROP TRIGGER test.t2_ai; +DROP TABLE test.t1; +DROP TABLE test.t2; +DROP TABLE test.t3; +sync_slave_with_master; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_trig003.test b/mysql-test/suite/rpl/t/rpl_row_trig003.test new file mode 100644 index 00000000..e332fc91 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trig003.test @@ -0,0 +1,155 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/16/2005 # +# Updated: 8/29/2005 Remove sleep calls add dump and diff # +############################################################################# +# TEST: This test includes all trigger types. BEFORE/AFTER INSERT, UPDATE & # +# DELETE. In addition, includes cursor, bit, varchar, flow control, # +# looping, ROUND(), NOW(), YEAR(), TIMESTAMP # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +#-- disable_query_log +#-- disable_result_log + +# Begin clean up test section +connection master; +--disable_warnings +--error 0,1360 +DROP TRIGGER test.t1_bi; +--error 0,1360 +DROP TRIGGER test.t2_ai; +--error 0,1360 +DROP TRIGGER test.t1_bu; +--error 0,1360 +DROP TRIGGER test.t2_au; +--error 0,1360 +DROP TRIGGER test.t1_bd; +--error 0,1360 +DROP TRIGGER test.t2_ad; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +--enable_warnings + +# test section 1 + +CREATE TABLE test.t1 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id)); +CREATE TABLE test.t2 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id)); +CREATE TABLE test.t3 (id MEDIUMINT NOT NULL AUTO_INCREMENT, b1 BIT(8), vc VARCHAR(255), bc CHAR(255), d DECIMAL(10,4) DEFAULT 0, f FLOAT DEFAULT 0, total BIGINT UNSIGNED, y YEAR, t TIMESTAMP,PRIMARY KEY(id)); + +# Note Most of these cause the slave to core or do not produce desired results. Currently commenting out the ones not working until they are fixed. + +delimiter |; +CREATE TRIGGER test.t1_bi BEFORE INSERT ON test.t1 FOR EACH ROW UPDATE test.t3 SET b1=1 and y=YEAR(NOW())| +CREATE TRIGGER test.t2_ai AFTER INSERT ON test.t2 FOR EACH ROW BEGIN + INSERT INTO test.t3 VALUES(NULL,0,'MySQL Replication team rocks!', 'Dark beer in prague is #1',12345.34,12.51,0,1965,NOW()); + UPDATE test.t3 SET f = ROUND(f); +END| +CREATE TRIGGER test.t1_bu BEFORE UPDATE on test.t1 FOR EACH ROW BEGIN + UPDATE test.t3 SET y = '2000'; + INSERT INTO test.t3 VALUES(NULL,1,'Testing MySQL databases before update ', 'Insert should work',621.43, 0105.21,0,1974,NOW()); +END| +CREATE TRIGGER test.t2_au AFTER UPDATE on test.t2 FOR EACH ROW BEGIN + DECLARE done INT DEFAULT 0; + DECLARE a DECIMAL(10,4); + DECLARE b FLOAT; + DECLARE num MEDIUMINT; + DECLARE cur1 CURSOR FOR SELECT t2.id, t2.d, t2.f FROM test.t2; + DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; + + OPEN cur1; + + REPEAT + FETCH cur1 INTO num, a, b; + IF NOT done THEN + UPDATE test.t3 SET total =(a*b) WHERE ID = num; + END IF; + UNTIL done END REPEAT; + CLOSE cur1; +END| +CREATE TRIGGER test.t1_bd BEFORE DELETE on test.t1 FOR EACH ROW BEGIN + DECLARE done INT DEFAULT 0; + DECLARE a BIT(8); + DECLARE b VARCHAR(255); + DECLARE c CHAR(255); + DECLARE d DECIMAL(10,4); + DECLARE e FLOAT; + DECLARE f BIGINT UNSIGNED; + DECLARE g YEAR; + DECLARE h TIMESTAMP; + DECLARE cur1 CURSOR FOR SELECT t1.b1, t1.vc, t1.bc, t1.d, t1.f, t1.total, t1.y, t1.t FROM test.t1; + DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; + + OPEN cur1; + + REPEAT + FETCH cur1 INTO a, b, c, d, e, f, g, h; + IF NOT done THEN + INSERT INTO test.t3 VALUES(NULL, a, b, c, d, e, f, g, h); + END IF; + UNTIL done END REPEAT; + CLOSE cur1; +END| +CREATE TRIGGER test.t2_ad AFTER DELETE ON test.t2 FOR EACH ROW + DELETE FROM test.t1| +delimiter ;| + +INSERT INTO test.t1 VALUES(NULL,1,'Testing MySQL databases is a cool ', 'Must make it bug free for the customer',654321.4321,15.21,0,1965,NOW()); +INSERT INTO test.t2 VALUES(NULL,0,'Testing MySQL databases is a cool ', 'MySQL Customers ROCK!',654321.4321,1.24521,0,YEAR(NOW()),NOW()); + +UPDATE test.t1 SET b1 = 0 WHERE b1 = 1; + +INSERT INTO test.t2 VALUES(NULL,1,'This is an after update test.', 'If this works, total will not be zero on the master or slave',1.4321,5.221,0,YEAR(NOW()),NOW()); +UPDATE test.t2 SET b1 = 0 WHERE b1 = 1; + +INSERT INTO test.t1 VALUES(NULL,1,'add some more test data test.', 'and hope for the best', 3.321,5.221,0,YEAR(NOW()),NOW()); + +# To make sure BUG#14698 is gone, we sleep before calling trigger +# (with the bug in, that caused differences in TIMESTAMP columns). +# We just need to let the machine's clock advance, it's not +# to do synchronization. + +let $wait_condition= SELECT SUM(f)= ROUND(SUM(f)) FROM t3; +--source include/wait_condition.inc + +DELETE FROM test.t1 WHERE id = 1; + +DELETE FROM test.t2 WHERE id = 1; + +sync_slave_with_master; +connection master; + +# time to dump the databases and so we can see if they match + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trg003_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/trg003_slave.sql + +# cleanup +--disable_warnings +--error 0,1360 +DROP TRIGGER test.t1_bi; +--error 0,1360 +DROP TRIGGER test.t2_ai; +--error 0,1360 +DROP TRIGGER test.t1_bu; +--error 0,1360 +DROP TRIGGER test.t2_au; +--error 0,1360 +DROP TRIGGER test.t1_bd; +--error 0,1360 +DROP TRIGGER test.t2_ad; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +--enable_warnings + +sync_slave_with_master; + +diff_files $MYSQLTEST_VARDIR/tmp/trg003_master.sql $MYSQLTEST_VARDIR/tmp/trg003_slave.sql; + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_trig004.test b/mysql-test/suite/rpl/t/rpl_row_trig004.test new file mode 100644 index 00000000..0cbdea33 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trig004.test @@ -0,0 +1,15 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Oct/18/2005 # +############################################################################# +# TEST: Use before insert triggers and has the second insert fail # +############################################################################# + +# Includes +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc +let $engine_type=INNODB; +-- source include/rpl_trig004.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_triggers.test b/mysql-test/suite/rpl/t/rpl_row_triggers.test new file mode 100644 index 00000000..68002dbe --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_triggers.test @@ -0,0 +1,442 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +-- echo # Test of row replication with triggers on the slave side + +connection master; +CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb; +SELECT * FROM t1; + +sync_slave_with_master; + +connection slave; +SET @old_slave_exec_mode= @@global.slave_exec_mode; +SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr; +SET @@global.slave_exec_mode= IDEMPOTENT; +SET @@global.slave_run_triggers_for_rbr= YES; +SELECT * FROM t1; +create table t2 (id char(2) primary key, cnt int, o char(1), n char(1)); +insert into t2 values + ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '), + ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '), + ('i0', 0, ' ', ' '),('i1', 0, ' ', ' '); +create trigger t1_cnt_b before update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0'; +create trigger t1_cnt_db before delete on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd0'; +create trigger t1_cnt_ib before insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0'; +create trigger t1_cnt_a after update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1'; +create trigger t1_cnt_da after delete on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1'; +create trigger t1_cnt_ia after insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1'; +SELECT * FROM t2 order by id; + +connection master; +--echo # INSERT triggers test +insert into t1 values ('a','b'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +--echo # UPDATE triggers test +update t1 set C1= 'd'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; +--echo # DELETE triggers test +delete from t1 where C1='d'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +--echo # INSERT triggers causing DELETE + INSERT (on unique key conflict) +insert into t1 values ('0','1'); + +SELECT * FROM t2 order by id; + +connection master; + +insert into t1 values ('0','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + + +--echo # INSERT triggers which cause also DELETE test +--echo # (insert duplicate row in table referenced by foreign key) +insert into t1 values ('1','1'); + +connection master; + +CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb; + +insert into t1 values ('1','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +drop table t3,t1; + +sync_slave_with_master; + +connection slave; +SET @@global.slave_exec_mode= @old_slave_exec_mode; +SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr; +drop table t2; + +--connection master + +CREATE TABLE t1 (i INT) ENGINE=InnoDB; +CREATE TABLE t2 (i INT) ENGINE=InnoDB; + +--sync_slave_with_master + +SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr; +SET GLOBAL slave_run_triggers_for_rbr=YES; + +CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW + INSERT INTO t2 VALUES (new.i); + +--connection master + +BEGIN; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +COMMIT; + +--sync_slave_with_master +select * from t2; +SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr; + +--connection master +drop tables t2,t1; + +--sync_slave_with_master + +-- echo # Triggers on slave do not work if master has some + +connection master; +CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb; +SELECT * FROM t1; + +create trigger t1_dummy before delete on t1 for each row + set @dummy= 1; + +sync_slave_with_master; + +connection slave; +SET @old_slave_exec_mode= @@global.slave_exec_mode; +SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr; +SET @@global.slave_exec_mode= IDEMPOTENT; +SET @@global.slave_run_triggers_for_rbr= YES; +SELECT * FROM t1; +create table t2 (id char(2) primary key, cnt int, o char(1), n char(1)); +insert into t2 values + ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '), + ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '), + ('i0', 0, ' ', ' '),('i1', 0, ' ', ' '); +create trigger t1_cnt_b before update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0'; +create trigger t1_cnt_ib before insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0'; +create trigger t1_cnt_a after update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1'; +create trigger t1_cnt_da after delete on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1'; +create trigger t1_cnt_ia after insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1'; +SELECT * FROM t2 order by id; + +connection master; +--echo # INSERT triggers test +insert into t1 values ('a','b'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +--echo # UPDATE triggers test +update t1 set C1= 'd'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; +--echo # DELETE triggers test +delete from t1 where C1='d'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +--echo # INSERT triggers which cause also UPDATE test (insert duplicate row) +insert into t1 values ('0','1'); + +SELECT * FROM t2 order by id; + +connection master; + +insert into t1 values ('0','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + + +--echo # INSERT triggers which cause also DELETE test +--echo # (insert duplicate row in table referenced by foreign key) +insert into t1 values ('1','1'); + +connection master; + +CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb; + +insert into t1 values ('1','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +drop table t3,t1; + +sync_slave_with_master; + +connection slave; +SET @@global.slave_exec_mode= @old_slave_exec_mode; +SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr; +drop table t2; + +--echo # +--echo # MDEV-5513: Trigger is applied to the rows after first one +--echo # + +--connection master + +create table t1 (a int, b int); +create table tlog (a int); + +set sql_log_bin=0; +create trigger tr1 after insert on t1 for each row insert into tlog values (1); +set sql_log_bin=1; + +sync_slave_with_master; +--connection slave + +set @slave_run_triggers_for_rbr.saved = @@slave_run_triggers_for_rbr; +set global slave_run_triggers_for_rbr=1; +create trigger tr2 before insert on t1 for each row set new.b = new.a; + +--connection master + +insert into t1 values (1,10),(2,20),(3,30); + +--sync_slave_with_master + +select * from t1; + +# Cleanup + +set global slave_run_triggers_for_rbr = @slave_run_triggers_for_rbr.saved; + +--connection master + +drop table t1, tlog; + +sync_slave_with_master; + + +--echo # +--echo # MDEV-8411 Assertion `is_stat_field || !table || (!table->write_set || +--echo # bitmap_is_set(table->write_set, field_index) || +--echo # bitmap_is_set(table->vcol_set, field_index))' +--echo # failed in Field_timestamp::store_TIME_with_warning +--echo # +--echo # +--echo # Create table on master, replicate it on slave. +--echo # +--connection master +set @binlog_row_image.saved = @@binlog_row_image; +set binlog_row_image = MINIMAL; +create table t1 (pk int primary key, f int); + +--sync_slave_with_master +--echo # +--echo # Create a trigger on the slave. +--echo # +create trigger tr before update on t1 for each row set new.f = 1000; +set @old_slave_run_triggers_for_rbr = @@global.slave_run_triggers_for_rbr; +set global slave_run_triggers_for_rbr = YES; + +--connection master +--echo # +--echo # Update the table to have the trigger fire on the slave., +--echo # +insert into t1 values (1,1),(2,2); +update t1 set pk=pk+10; +select * from t1; + +--sync_slave_with_master +--echo # +--echo # Check to see if slave has the table updated. +--echo # +select * from t1; + +--echo # +--echo # Cleanup +--echo # + +set global slave_run_triggers_for_rbr = @old_slave_run_triggers_for_rbr; + +--connection master +set binlog_row_image = @binlog_row_image.saved; +drop table t1; + +--sync_slave_with_master + +--echo # +--echo # enterprise 10.4 tests start +--echo # + +--echo # +--echo # MENT-607 : Make slave_run_triggers_for_rbr enforce triggers to run +--echo # on slave, even when there are triggers on the master +--echo # + +--echo # Triggers on slave WILL work (with ENFORCE) if master has some + +connection master; +CREATE TABLE t1 (C1 CHAR(1) primary key, C2 CHAR(1)) engine=innodb; +SELECT * FROM t1; + +create trigger t1_dummy before delete on t1 for each row + set @dummy= 1; + +sync_slave_with_master; + +connection slave; +SET @old_slave_exec_mode= @@global.slave_exec_mode; +SET @old_slave_run_triggers_for_rbr= @@global.slave_run_triggers_for_rbr; +SET @@global.slave_exec_mode= IDEMPOTENT; +SET @@global.slave_run_triggers_for_rbr= ENFORCE; +SELECT * FROM t1; +create table t2 (id char(2) primary key, cnt int, o char(1), n char(1)); +insert into t2 values + ('u0', 0, ' ', ' '),('u1', 0, ' ', ' '), + ('d0', 0, ' ', ' '),('d1', 0, ' ', ' '), + ('i0', 0, ' ', ' '),('i1', 0, ' ', ' '); +create trigger t1_cnt_b before update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u0'; +create trigger t1_cnt_ib before insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i0'; +create trigger t1_cnt_a after update on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=new.C1 where id = 'u1'; +create trigger t1_cnt_da after delete on t1 for each row + update t2 set cnt=cnt+1, o=old.C1, n=' ' where id = 'd1'; +create trigger t1_cnt_ia after insert on t1 for each row + update t2 set cnt=cnt+1, n=new.C1, o=' ' where id = 'i1'; +SELECT * FROM t2 order by id; + +connection master; +--echo # INSERT triggers test +insert into t1 values ('a','b'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +--echo # UPDATE triggers test +update t1 set C1= 'd'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; +--echo # DELETE triggers test +delete from t1 where C1='d'; + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +--echo # INSERT triggers which cause also UPDATE test (insert duplicate row) +insert into t1 values ('0','1'); + +SELECT * FROM t2 order by id; + +connection master; + +insert into t1 values ('0','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + + +--echo # INSERT triggers which cause also DELETE test +--echo # (insert duplicate row in table referenced by foreign key) +insert into t1 values ('1','1'); + +connection master; + +CREATE TABLE t3 (C1 CHAR(1) primary key, FOREIGN KEY (C1) REFERENCES t1(C1) ) engine=innodb; + +insert into t1 values ('1','1'); + +sync_slave_with_master; + +connection slave; +SELECT * FROM t2 order by id; + +connection master; + +drop table t3,t1; + +sync_slave_with_master; + +connection slave; +SET @@global.slave_exec_mode= @old_slave_exec_mode; +SET @@global.slave_run_triggers_for_rbr= @old_slave_run_triggers_for_rbr; +drop table t2; + +--echo # +--echo # enterprise 10.4 tests end +--echo # + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test new file mode 100644 index 00000000..a8d7f77d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_trunc_temp.test @@ -0,0 +1,35 @@ +# +# Bug#48350 truncate temporary table crashes replication +# +# All statements operating on temporary tables should not be binlogged in RBR. +# However, before fix of bug#48350, 'TRUNCATE ...' statement on a temporary +# table was binlogged in RBR. +# + +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +#This statement is not binlogged in RBR. +CREATE TEMPORARY TABLE t1(c1 INTEGER); +CREATE TABLE t2(c1 INTEGER); +sync_slave_with_master; + +CREATE TABLE t1(c1 INTEGER); +INSERT INTO t1 VALUES(1), (2); +INSERT INTO t2 VALUES(1), (2); +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +TRUNCATE t1; +TRUNCATE t2; +sync_slave_with_master; +# t1 will have nothing, if 'TRUNCATE t1' has been replicate from master to +# slave. +SELECT * FROM t1; +SELECT * FROM t2; + +DROP TABLE t1; +connection master; +DROP TABLE t2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test b/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test new file mode 100644 index 00000000..2442f869 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_type_conv_err_msg.test @@ -0,0 +1,356 @@ +# ==== Purpose ==== +# +# Test verifies that when slave side type conversion fails in row based +# replication, more informative error message is displayed. It also verifies +# that in the case of blob fields appropriate type name is displayed in error +# message. +# +# ==== Implementation ==== +# +# Steps: +# Test case1: +# 1. Create a table on master with VARCHAR filed and charset +# 'utf8mb3'. +# 2. Create a table on slave with VARCHAR field and charset +# 'utf8mb4'. +# 3. Insert a tuple on master. +# 4. Verify that slave provides more informative error message with +# respect to difference in charsets. +# Test case2: Repeat same steps as above for CHAR field +# Test case3: +# 1. Create a table on master with LONGBLOB field. +# 2. Create a table on slave with TINYBLOB field. +# 3. Insert a tuple on master. +# 4. Verify that error message displayed on slave clearly states type +# conversion failure from 'longblob' to 'tinyblob'. +# 5. Also verify that error message doesn't show additional details +# of charset when not required. +# Test Case4: Verifies varbinary to binary type conversion failure specific +# error message. +# Test Case5: Verifies binary to varbinary type conversion failure specific +# error message. +# Test Case6: Verifies binary to binary type conversion failure specific +# error message. +# Test Case7: Verifies char to blob type conversion failure specific +# error message. +# Test Case8: Verifies char to text type conversion failure specific +# error message. +# ==== References ==== +# +# MDEV-19925: Column ... cannot be converted from type 'varchar(20)' to type +# 'varchar(20)' +# + +--source include/have_binlog_format_row.inc +# Inorder to grep a specific error pattern in error log a fresh error log +# needs to be generated. +--source include/force_restart.inc +--source include/master-slave.inc + +--echo #################################################################### +--echo # Test Case1: Improved error message with charset information +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb3'); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb4'); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'varchar(3)' to type 'varchar(1)' +# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'varchar(3 octets)' to type 'varchar(4 octets) character set utf8mb4' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'varchar\(3 octets\)\' to type \'varchar\(4 octets\) character set utf8mb4\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case2: Improved error message with charset information for CHAR +--echo # type +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb3'); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb4'); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'char(0)' to type 'char(1)' +# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'char(3 octets)' to type 'char(4 octets) character set utf8mb4)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'char\(3 octets\)\' to type \'char\(4 octets\) character set utf8mb4\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case3: For BLOB type fileds, when type conversion failed on +--echo # slave, the errormessage had incorrect type names. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 LONGBLOB); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 TINYBLOB); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type 'tinyblob' +# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'longblob' to type 'tinyblob' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'longblob\' to type \'tinyblob\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case4: Verifies varbinary to binary type conversion failure +--echo # specific error message. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 VARBINARY(10)); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 BINARY(10)); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'varbinary(10)' to type 'binary(10)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'varbinary\(10\)\' to type \'binary\(10\)\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case5: Verifies binary to varbinary type conversion failure +--echo # specific error message. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 BINARY(10)); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 VARBINARY(10)); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(10)' to type 'varbinary(10)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'binary\(10\)\' to type \'varbinary\(10\)\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case6: Verifies binary to binary type conversion failure +--echo # specific error message. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 BINARY(1)); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 BINARY(10)); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'binary\(1\)\' to type \'binary\(10\)\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case7: Verifies char to blob type conversion failure +--echo # specific error message. BLOB field on slave has no +--echo # associated character set hence the master side field +--echo # is also considered as binary. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 CHAR(1)); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 BLOB); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'binary\(1\)\' to type \'blob\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo #################################################################### +--echo # Test Case8: Verifies char to text type conversion failure +--echo # specific error message. +--echo #################################################################### +--connection master +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 CHAR(1)); +SET SQL_LOG_BIN=1; + +--connection slave +CREATE TABLE t1 (c1 TEXT); + +--connection master +INSERT INTO t1 VALUES ('a'); + +--connection slave +--let $slave_sql_errno= 1677 +--source include/wait_for_slave_sql_error.inc + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} + +# Expected Error : Column 0 of table 'test.t1' cannot be converted from type 'binary(1)' to type 'binary(10)' +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=\'char\(1 octets\)\' to type \'text\' +--source include/search_pattern_in_file.inc + +--connection master +DROP TABLE t1; +--connection slave +DROP TABLE t1; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test new file mode 100644 index 00000000..31eea3a2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test @@ -0,0 +1,36 @@ +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +# +# Bug #30244: row_count/found_rows does not replicate well +# + +connection master; + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT); + +INSERT INTO t1 SELECT 1; + +connection master1; +INSERT INTO t1 VALUES (2),(3),(4),(5),(6); + +connection master; +INSERT INTO t2 SELECT 1, ROW_COUNT(); + +INSERT INTO t1 VALUES (2),(3),(4); +INSERT INTO t2 SELECT 2, ROW_COUNT(); + +#must return 1 and 3 +SELECT b FROM t2 ORDER BY a; + +sync_slave_with_master; + +#must return 1 and 3 +SELECT b FROM t2 ORDER BY a; + +connection master; +DROP TABLE t1, t2; +sync_slave_with_master; +connection master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_until.test b/mysql-test/suite/rpl/t/rpl_row_until.test new file mode 100644 index 00000000..478c2206 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_until.test @@ -0,0 +1,150 @@ +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +############################################################################## +# The test is dependent on binlog positions. The test is divided into two +# sections. The first section checks START SLAVE UNTIL MASTER_LOG_FILE = +# 'log_name', MASTER_LOG_POS = log_pos followed by a couple of failure +# scenarios. The second section checks START SLAVE UNTIL RELAY_LOG_FILE = +# 'log_name', RELAY_LOG_POS = log_pos. +############################################################################## + +# Create some events on master +connection master; +CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4); +# Save master log position for query DROP TABLE t1 +let $master_pos_drop_t1= query_get_value(SHOW MASTER STATUS, Position, 1); +DROP TABLE t1; +# Save master log position for query DROP TABLE t1 +save_master_pos; +#let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 10); +let $master_log_file= query_get_value(SHOW BINLOG EVENTS, Log_name, 10); + +# Save master log position for query CREATE TABLE t2 +let $master_pos_create_t2= query_get_value(SHOW MASTER STATUS, Position, 1); +CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +#show binlog events; + +INSERT INTO t2 VALUES (1),(2); +# Save master log position for query INSERT INTO t2 VALUES (1),(2); +let $master_pos_insert1_t2= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t2 VALUES (3),(4); +DROP TABLE t2; +# Save master log position for query DROP TABLE t2; +let $master_pos_drop_t2= query_get_value(SHOW MASTER STATUS, Position, 1); +sync_slave_with_master; +#show binlog events; + +--source include/stop_slave.inc +# Reset slave. +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval CHANGE MASTER TO MASTER_USER='root', MASTER_CONNECT_RETRY=1, MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT; + +# Try to replicate all queries until drop of t1 + +connection slave; +--replace_result $master_pos_drop_t1 master_pos_drop_t1 +eval START SLAVE UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos_drop_t1; +--source include/wait_for_slave_sql_to_stop.inc + +# Here table should be still not deleted +SELECT * FROM t1; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_pos_drop_t1 +--source include/check_slave_param.inc + +# This should fail right after start +START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291; +--source include/wait_for_slave_sql_to_stop.inc +# again this table should be still not deleted +SELECT * FROM t1; + +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_pos_drop_t1 +--source include/check_slave_param.inc + +# clean up +START SLAVE; +--source include/wait_for_slave_to_start.inc +connection master; +sync_slave_with_master; +--source include/stop_slave.inc + +# This should stop immediately as we are already there +--replace_result $master_pos_create_t2 master_pos_create_t2 +eval START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos_create_t2; +let $slave_param= Until_Log_Pos; +let $slave_param_value= $master_pos_create_t2; +--source include/wait_for_slave_param.inc +--source include/wait_for_slave_sql_to_stop.inc +# here the sql slave thread should be stopped +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_pos_drop_t2 +--source include/check_slave_param.inc + +#testing various error conditions +--replace_result 561 MASTER_LOG_POS +--error 1277 +START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561; +--replace_result 561 MASTER_LOG_POS 12 RELAY_LOG_POS +--error 1277 +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12; +--error 1277 +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001'; +--error 1277 +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009'; +--replace_result 561 MASTER_LOG_POS +--error 1277 +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; +--replace_result 740 MASTER_LOG_POS +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; + +--source include/stop_slave.inc +RESET SLAVE; +--source include/start_slave.inc + +############################################################################## +# The second section - checks START SLAVE UNTIL RELAY_LOG_FILE =# 'log_name', +# RELAY_LOG_POS = log_pos. This section of the test does the following: +# 1) At master, create a table and inserts a value. Let slave replicate this. +# 2) Stop slave sql thread. +# 3) Insert some more values at master. Note that io thread copies this insert +# 4) Use start slave until to start the sql thread and check if it +# stops at the correct position. +############################################################################## + +--source include/rpl_reset.inc + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); + +--sync_slave_with_master +--source include/stop_slave_sql.inc + +--connection master +INSERT INTO t1 VALUES (2); +--let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +INSERT INTO t1 VALUES (3); + +--source include/sync_slave_io_with_master.inc + +--let $relay_log_file= query_get_value(SHOW SLAVE STATUS, Relay_Log_File,1) +--source include/get_relay_log_pos.inc + +--replace_result $relay_log_pos relay_log_pos +--eval start slave until relay_log_file='$relay_log_file', relay_log_pos=$relay_log_pos +--source include/wait_for_slave_sql_to_stop.inc + +--let $assert_cond= COUNT(*) = 2 FROM t1 +--let $assert_text= table t1 should have two rows. +--source include/assert.inc + +#cleanup +--source include/start_slave.inc +--connection master +DROP TABLE t1; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_utf16.test b/mysql-test/suite/rpl/t/rpl_row_utf16.test new file mode 100644 index 00000000..d5dcdc42 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_utf16.test @@ -0,0 +1,26 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_utf16.inc +-- source include/master-slave.inc + +# +# BUG#51716: Char column with utf16 character set gives wrong padding on slave +# + +CREATE TABLE t1(c1 CHAR(10) CHARACTER SET utf16 DEFAULT 'ola'); +INSERT INTO t1 VALUES ('abc'); # explicit value is inserted and encoded correctly +INSERT INTO t1 VALUES (); # default value is inserted and encoded correctly + +--query_vertical SELECT c1, hex(c1) from t1 + +-- sync_slave_with_master + +--query_vertical SELECT c1, hex(c1) FROM t1 + +# assertion: tables don't differ +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc + +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_utf32.test b/mysql-test/suite/rpl/t/rpl_row_utf32.test new file mode 100644 index 00000000..c82cd4e5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_utf32.test @@ -0,0 +1,45 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_utf32.inc +-- source include/master-slave.inc + +# +# BUG#51787 Assertion `(n % 4) == 0' on slave upon INSERT into a table with UTF32 +# + +SET SQL_LOG_BIN=0; +CREATE TABLE t1 (c1 char(255) DEFAULT NULL, KEY c1 (c1)) DEFAULT CHARSET=utf32; +SET SQL_LOG_BIN=1; + +-- connection slave + +SET @saved_slave_type_conversions= @@global.slave_type_conversions; + +# +# Force test to cover conversion execution path in the +# slave, which also makes use of sql_type method, thence +# can ultimately trigger the assertion. +# +-- source include/stop_slave.inc +SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY'; +-- source include/start_slave.inc + +SET SQL_LOG_BIN=0; +CREATE TABLE t1 ( c1 varchar(255) DEFAULT NULL, KEY c1 (c1)) DEFAULT CHARSET=utf32; +SET SQL_LOG_BIN=1; + +-- connection master + +INSERT INTO t1(c1) VALUES ('insert into t1'); +DROP TABLE t1; + +--sync_slave_with_master + +# assertion: the slave woul hit an/several assertions: +# before and during slave conversion procedure +# Now that is fixed, it wont. + +SET GLOBAL SLAVE_TYPE_CONVERSIONS= @saved_slave_type_conversions; +-- source include/stop_slave.inc +-- source include/start_slave.inc +-- connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test b/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test new file mode 100644 index 00000000..84ee1497 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_vcol_crash.test @@ -0,0 +1,425 @@ +# ==== Purpose ==== +# +# Test verifies that, slave doesn't report any assert on UPDATE or DELETE of +# row which tries to update the virtual columns with associated KEYs. +# +# Test scenarios are listed below. +# 1) KEY on a virtual column with ON DELETE CASCADE +# 2) Verify "ON DELETE CASCADE" for parent->child->child scenario +# 3) KEY on a virtual column with ON UPDATE CASCADE +# 4) Define triggers on master, their results should be replicated +# as part of row events and they should be applied on slave with +# the default slave_run_triggers_for_rbr=NO +# 5) Define triggers + Foreign Keys on master, their results should be +# replicated as part of row events and master and slave should be in sync. +# 6) Triggers are present only on slave and 'slave_run_triggers_for_rbr=NO' +# 7) Triggers are present only on slave and 'slave_run_triggers_for_rbr=YES' +# 8) Triggers and Foreign Keys are present only on slave and +# 'slave_run_triggers_for_rbr=NO' +# 9) Triggers are Foreign Keys are present only on slave and +# 'slave_run_triggers_for_rbr=YES' +# +# ==== References ==== +# +# MDEV-23033: All slaves crash once in ~24 hours and loop restart with signal 11 +# + +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + + +--echo # +--echo # Test case 1: KEY on a virtual column with ON DELETE CASCADE +--echo # +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); + +CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, + t1_id INT NOT NULL, + v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id), + CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; + +INSERT INTO t2 VALUES (90,1,NULL); +INSERT INTO t2 VALUES (91,2,default); + +# Following query results in an assert on slave +DELETE FROM t1 WHERE id=1; +--sync_slave_with_master + +--echo # +--echo # Verify data consistency on slave +--echo # +--let $diff_tables= master:test.t1, slave:test.t1 +--source include/diff_tables.inc +--let $diff_tables= master:test.t2, slave:test.t2 +--source include/diff_tables.inc + +--connection master +DROP TABLE t2,t1; +--sync_slave_with_master + +--echo # +--echo # Test case 2: Verify "ON DELETE CASCADE" for parent->child->child scenario +--echo # Parent table: users +--echo # Child tables: matchmaking_groups, matchmaking_group_users +--echo # Parent table: matchmaking_groups +--echo # Child tables: matchmaking_group_users, matchmaking_group_maps +--echo # +--echo # Deleting a row from parent table should be reflected in +--echo # child tables. +--echo # matchmaking_groups->matchmaking_group_users->matchmaking_group_maps +--echo # users->matchmaking_group_users->matchmaking_group_maps +--echo # + +--connection master +CREATE TABLE users (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(32) NOT NULL DEFAULT '' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE matchmaking_groups ( + id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + host_user_id INT UNSIGNED NOT NULL UNIQUE, + v_col INT AS (host_user_id+1) VIRTUAL, KEY (v_col), + CONSTRAINT FOREIGN KEY (host_user_id) REFERENCES users (id) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE matchmaking_group_users ( + matchmaking_group_id BIGINT UNSIGNED NOT NULL, + user_id INT UNSIGNED NOT NULL, + v_col1 int as (user_id+1) virtual, KEY (v_col1), + PRIMARY KEY (matchmaking_group_id,user_id), + UNIQUE KEY user_id (user_id), + CONSTRAINT FOREIGN KEY (matchmaking_group_id) + REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT FOREIGN KEY (user_id) + REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE matchmaking_group_maps ( + matchmaking_group_id BIGINT UNSIGNED NOT NULL, + map_id TINYINT UNSIGNED NOT NULL, + v_col2 INT AS (map_id+1) VIRTUAL, KEY (v_col2), + PRIMARY KEY (matchmaking_group_id,map_id), + CONSTRAINT FOREIGN KEY (matchmaking_group_id) + REFERENCES matchmaking_groups (id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +--sync_slave_with_master + +--connection master +INSERT INTO users VALUES (NULL,'foo'),(NULL,'bar'); +INSERT INTO matchmaking_groups VALUES (10,1,default),(11,2,default); +INSERT INTO matchmaking_group_users VALUES (10,1,default),(11,2,default); +INSERT INTO matchmaking_group_maps VALUES (10,55,default),(11,66,default); + +DELETE FROM matchmaking_groups WHERE id = 10; +--sync_slave_with_master + +--echo # +--echo # No rows should be returned as ON DELETE CASCASE should have removed +--echo # corresponding rows from child tables. There should not any mismatch +--echo # of 'id' field between parent->child. +--echo # +SELECT * FROM matchmaking_group_users WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups); +SELECT * FROM matchmaking_group_maps WHERE matchmaking_group_id NOT IN (SELECT id FROM matchmaking_groups); + +--echo # +--echo # Rows with id=11 should be present +--echo # +SELECT * FROM matchmaking_group_users; +SELECT * FROM matchmaking_group_maps; + +--connection master +DELETE FROM users WHERE id = 2; +--sync_slave_with_master + +--echo # +--echo # No rows should be present in both the child tables +--echo # +SELECT * FROM matchmaking_group_users; +SELECT * FROM matchmaking_group_maps; + +--connection master +DROP TABLE matchmaking_group_maps, matchmaking_group_users, matchmaking_groups, users; +--sync_slave_with_master + +--echo # +--echo # Test case 3: KEY on a virtual column with ON UPDATE CASCADE +--echo # + +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 80); + +CREATE TABLE t2 (a INT KEY, b INT, + v_col int as (b+1) virtual, KEY (v_col), + CONSTRAINT b FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO t2 VALUES (51, 1, default); +--sync_slave_with_master + +--connection master +UPDATE t1 SET a = 50 WHERE a = 1; + +--echo # +--echo # Master: Verify that ON UPDATE CASCADE works fine +--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51) +--echo # +SELECT * FROM t2 WHERE b=50; +--sync_slave_with_master + +--echo # +--echo # Slave: Verify that ON UPDATE CASCADE works fine +--echo # old_row: (51, 1, 2) ON UPDATE New_row: (51, 50, 51) +--echo # +SELECT * FROM t2 WHERE b=50; + +--connection master +DROP TABLE t2, t1; +--sync_slave_with_master + +--echo # +--echo # Test case 4: Define triggers on master, their results should be +--echo # replicated as part of row events and they should be +--echo # applied on slave with the default +--echo # slave_run_triggers_for_rbr=NO +--echo # + +# In row-based replication, the binary log contains row changes. It will have +# both the changes made by the statement itself, and the changes made by the +# triggers that were invoked by the statement. Slave server(s) do not need to +# run triggers for row changes they are applying. Hence verify that this +# property remains the same and data should be available as if trigger was +# executed. Please note by default slave_run_triggers_for_rbr=NO. + +--connection master +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (count INT NOT NULL) ENGINE=InnoDB; +CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (1); +INSERT INTO t1 VALUES (2),(3); +--sync_slave_with_master + +SHOW GLOBAL VARIABLES LIKE 'slave_run_triggers_for_rbr'; +--echo # +--echo # As two rows are inserted in table 't1', two rows should get inserted +--echo # into table 't2' as part of trigger. +--echo # +--let $assert_cond= COUNT(*) = 2 FROM t2 +--let $assert_text= Table t2 should have two rows. +--source include/assert.inc + +--connection master +DROP TABLE t1,t2; +--sync_slave_with_master + +--echo # +--echo # Test case 5: Define triggers + Foreign Keys on master, their results +--echo # should be replicated as part of row events and master +--echo # and slave should be in sync. +--echo # +--connection master +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (t1_id INT NOT NULL, + v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id), + CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB; +CREATE TRIGGER trg AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t3 VALUES (1); + +INSERT INTO t1 VALUES (2),(3); +INSERT INTO t2 VALUES (2, default), (3, default); +--sync_slave_with_master + +--echo # +--echo # As two rows are inserted in table 't1', two rows should get inserted +--echo # into table 't3' as part of trigger. +--echo # +--let $assert_cond= COUNT(*) = 2 FROM t3 +--let $assert_text= Table t3 should have two rows. +--source include/assert.inc + +--echo # +--echo # Verify ON DELETE CASCASE correctness +--echo # +--connection master +DELETE FROM t1 WHERE id=2; +--sync_slave_with_master + +--connection master +--let $diff_tables= master:test.t1, slave:test.t1 +--source include/diff_tables.inc +--let $diff_tables= master:test.t2, slave:test.t2 +--source include/diff_tables.inc +--let $diff_tables= master:test.t3, slave:test.t3 +--source include/diff_tables.inc + +DROP TABLE t3,t2,t1; +--sync_slave_with_master + +# +# Test case: Triggers only on slave +# +--write_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc PROCEDURE + if ($slave_run_triggers_for_rbr == '') { + --die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr + } + +--connection slave +SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr; +--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr; +SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%'; + +--connection master +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (t1_id INT NOT NULL, + v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), + KEY (t1_id), CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB; +--sync_slave_with_master + +CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1); + +--connection master +INSERT INTO t1 VALUES (2),(3); +INSERT INTO t2 VALUES (2, default), (3, default); +--sync_slave_with_master + +if ($slave_run_triggers_for_rbr == 'NO') { +--echo # +--echo # Count must be 0 +--echo # +--let $assert_cond= COUNT(*) = 0 FROM t3 +--let $assert_text= Table t3 should have zero rows. +--source include/assert.inc +} +if ($slave_run_triggers_for_rbr == 'YES') { +--echo # +--echo # Count must be 2 +--echo # +--let $assert_cond= COUNT(*) = 2 FROM t3 +--let $assert_text= Table t3 should have two rows. +--source include/assert.inc +} + +--connection master +DELETE FROM t1 WHERE id=2; +--sync_slave_with_master +SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr; + +--echo # +--echo # Verify t1, t2 are consistent on slave. +--echo # +--let $diff_tables= master:test.t1, slave:test.t1 +--source include/diff_tables.inc +--let $diff_tables= master:test.t2, slave:test.t2 +--source include/diff_tables.inc + +--connection master +DROP TABLE t3,t2,t1; +--sync_slave_with_master +#END OF +PROCEDURE + +--echo # +--echo # Test case 6: Triggers are present only on slave and +--echo # 'slave_run_triggers_for_rbr=NO' +--echo # +--let $slave_run_triggers_for_rbr=NO +--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc + +--echo # +--echo # Test case 7: Triggers are present only on slave and +--echo # 'slave_run_triggers_for_rbr=YES' +--echo # +--let $slave_run_triggers_for_rbr=YES +--source $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc +--remove_file $MYSQLTEST_VARDIR/tmp/trig_on_slave.inc + +# +# Test case: Trigger and Foreign Key are present only on slave +# +--write_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc PROCEDURE + if ($slave_run_triggers_for_rbr == '') { + --die !!!ERROR IN TEST: you must set $slave_run_triggers_for_rbr + } + +--connection slave +SET @save_slave_run_triggers_for_rbr= @@GLOBAL.slave_run_triggers_for_rbr; +--eval SET GLOBAL slave_run_triggers_for_rbr= $slave_run_triggers_for_rbr; +SHOW GLOBAL VARIABLES LIKE '%slave_run_triggers_for_rbr%'; + +--connection master +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +SET sql_log_bin=0; +CREATE TABLE t2 (t1_id INT NOT NULL,v_col INT AS (t1_id+1) VIRTUAL) ENGINE=INNODB; +SET sql_log_bin=1; +CREATE TABLE t3 (count INT NOT NULL) ENGINE=InnoDB; +--sync_slave_with_master + +# Have foreign key and trigger on slave. +CREATE TABLE t2 (t1_id INT NOT NULL, + v_col INT AS (t1_id+1) VIRTUAL, KEY (v_col), KEY (t1_id), + CONSTRAINT a FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE +) ENGINE=InnoDB; +CREATE TRIGGER trg AFTER INSERT ON t2 FOR EACH ROW INSERT INTO t3 VALUES (1); + +--connection master +INSERT INTO t1 VALUES (2),(3); +INSERT INTO t2 VALUES (2, default), (3, default); +--sync_slave_with_master + +if ($slave_run_triggers_for_rbr == 'NO') { +--echo # +--echo # Count must be 0 +--echo # +--let $assert_cond= COUNT(*) = 0 FROM t3 +--let $assert_text= Table t3 should have zero rows. +--source include/assert.inc +} +if ($slave_run_triggers_for_rbr == 'YES') { +--echo # +--echo # Count must be 2 +--echo # +--let $assert_cond= COUNT(*) = 2 FROM t3 +--let $assert_text= Table t3 should have two rows. +--source include/assert.inc +} + +--connection master +DELETE FROM t1 WHERE id=2; +--echo # t1: Should have one row +SELECT * FROM t1; +--echo # t2: Should have two rows +SELECT * FROM t2; +--sync_slave_with_master +--echo # t1: Should have one row +SELECT * FROM t1; +--echo # t2: Should have one row on slave due to ON DELETE CASCASE +SELECT * FROM t2; +SET GLOBAL slave_run_triggers_for_rbr= @save_slave_run_triggers_for_rbr; + +--connection master +DROP TABLE t3,t2,t1; +--sync_slave_with_master +#END OF +PROCEDURE + +--echo # +--echo # Test case 8: Triggers and Foreign Keys are present only on slave and +--echo # 'slave_run_triggers_for_rbr=NO' +--echo # +--let $slave_run_triggers_for_rbr=NO +--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc + +--echo # +--echo # Test case 9: Triggers are Foreign Keys are present only on slave and +--echo # 'slave_run_triggers_for_rbr=YES' +--echo # +--let $slave_run_triggers_for_rbr=YES +--source $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc +--remove_file $MYSQLTEST_VARDIR/tmp/trig_fk_on_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_view01.test b/mysql-test/suite/rpl/t/rpl_row_view01.test new file mode 100644 index 00000000..449196ae --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_view01.test @@ -0,0 +1,85 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/19/2005 # +# Updated: 08/29/2005 Remove sleeps # +############################################################################# +#TEST: row based replication of views # +############################################################################# +# Includes +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +# Begin clean up test section +connection master; +--disable_warnings +create database if not exists mysqltest1; +DROP VIEW IF EXISTS mysqltest1.v1; +DROP VIEW IF EXISTS mysqltest1.v2; +DROP VIEW IF EXISTS mysqltest1.v3; +DROP VIEW IF EXISTS mysqltest1.v4; +DROP TABLE IF EXISTS mysqltest1.t3; +DROP TABLE IF EXISTS mysqltest1.t1; +DROP TABLE IF EXISTS mysqltest1.t2; +DROP TABLE IF EXISTS mysqltest1.t4; + +# Begin test section 1 +CREATE TABLE mysqltest1.t1 (a INT, c CHAR(6),PRIMARY KEY(a)); +CREATE TABLE mysqltest1.t2 (a INT, c CHAR(6),PRIMARY KEY(a)); +CREATE TABLE mysqltest1.t3 (a INT, c CHAR(6), c2 CHAR(6), PRIMARY KEY(a)); +CREATE TABLE mysqltest1.t4 (a INT, qty INT, price INT,PRIMARY KEY(a)); +CREATE TABLE mysqltest1.t5 (qty INT, price INT, total INT, PRIMARY KEY(qty)); +INSERT INTO mysqltest1.t1 VALUES (1,'Thank'),(2,'it'),(3,'Friday'); +INSERT INTO mysqltest1.t2 VALUES (1,'GOD'),(2,'is'),(3,'TGIF'); +INSERT INTO mysqltest1.t4 VALUES(1, 3, 50),(2, 18, 3),(4, 4, 4); + + +CREATE VIEW mysqltest1.v2 AS SELECT qty, price, qty*price AS value FROM mysqltest1.t4 ORDER BY qty; +CREATE VIEW mysqltest1.v1 AS SELECT t1.a, t1.c, t2.c as c2 FROM mysqltest1.t1 as t1, mysqltest1.t2 AS t2 WHERE mysqltest1.t1.a = mysqltest1.t2.a ORDER BY a; +CREATE VIEW mysqltest1.v3 AS SELECT * FROM mysqltest1.t1; +CREATE VIEW mysqltest1.v4 AS SELECT * FROM mysqltest1.v3 WHERE a > 1 WITH LOCAL CHECK OPTION; + + +SELECT * FROM mysqltest1.v2; +SELECT * FROM mysqltest1.v1; + +--sync_slave_with_master + +SELECT * FROM mysqltest1.v2; +SELECT * FROM mysqltest1.v1; +connection master; + +INSERT INTO mysqltest1.t5 SELECT * FROM mysqltest1.v2; +INSERT INTO mysqltest1.t3 SELECT * FROM mysqltest1.v1; + +SELECT * FROM mysqltest1.t5 ORDER BY qty; +SELECT * FROM mysqltest1.t3 ORDER BY a; +sync_slave_with_master; +SELECT * FROM mysqltest1.t5 ORDER BY qty; +SELECT * FROM mysqltest1.t3 ORDER BY a; +connection master; + +INSERT INTO mysqltest1.v4 VALUES (4,'TEST'); + +SELECT * FROM mysqltest1.t1 ORDER BY a; +SELECT * FROM mysqltest1.v4 ORDER BY a; +sync_slave_with_master; +SELECT * FROM mysqltest1.t1 ORDER BY a; +SELECT * FROM mysqltest1.v4 ORDER BY a; + +connection master; + +# lets cleanup +DROP VIEW IF EXISTS mysqltest1.v1; +DROP VIEW IF EXISTS mysqltest1.v2; +DROP VIEW IF EXISTS mysqltest1.v3; +DROP VIEW IF EXISTS mysqltest1.v4; +DROP TABLE IF EXISTS mysqltest1.t3; +DROP TABLE IF EXISTS mysqltest1.t1; +DROP TABLE IF EXISTS mysqltest1.t2; +DROP TABLE IF EXISTS mysqltest1.t4; +DROP DATABASE mysqltest1; +sync_slave_with_master; + +# End of 5.1 test case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_virt.test b/mysql-test/suite/rpl/t/rpl_row_virt.test new file mode 100644 index 00000000..e79869cd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_virt.test @@ -0,0 +1,27 @@ +--source include/have_binlog_format_row.inc +--source include/master-slave.inc +--source include/have_innodb.inc +connection master; + +create table t1 ( + id int auto_increment, + data varchar(32), + virt tinyint as (1), + primary key (id), + key virt (virt) +) engine=innodb default charset=utf8mb4; + +insert into t1 (data) values ('broken'); + +update t1 set data='more broken'; + +--sync_slave_with_master + +select * from t1; + +--connection master +drop table t1; + +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_wide_table.test b/mysql-test/suite/rpl/t/rpl_row_wide_table.test new file mode 100644 index 00000000..01473f99 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_wide_table.test @@ -0,0 +1,340 @@ +################################################################## +# rpl_row_wide_table +# +# This test verifies that the table with number of attributes more +# than 250 is replicated. +# Related bugs: +# Bug #42977 RBR logs for rows with more than 250 column results +# in corrupt binlog +################################################################## + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +--disable_warnings +DROP TABLE IF EXISTS t300; +--enable_warnings + +connection master; + +create table t300 ( +f1 int, +f2 int, +f3 int, +f4 int, +f5 int, +f6 int, +f7 int, +f8 int, +f9 int, +f10 int, +f11 int, +f12 int, +f13 int, +f14 int, +f15 int, +f16 int, +f17 int, +f18 int, +f19 int, +f20 int, +f21 int, +f22 int, +f23 int, +f24 int, +f25 int, +f26 int, +f27 int, +f28 int, +f29 int, +f30 int, +f31 int, +f32 int, +f33 int, +f34 int, +f35 int, +f36 int, +f37 int, +f38 int, +f39 int, +f40 int, +f41 int, +f42 int, +f43 int, +f44 int, +f45 int, +f46 int, +f47 int, +f48 int, +f49 int, +f50 int, +f51 int, +f52 int, +f53 int, +f54 int, +f55 int, +f56 int, +f57 int, +f58 int, +f59 int, +f60 int, +f61 int, +f62 int, +f63 int, +f64 int, +f65 int, +f66 int, +f67 int, +f68 int, +f69 int, +f70 int, +f71 int, +f72 int, +f73 int, +f74 int, +f75 int, +f76 int, +f77 int, +f78 int, +f79 int, +f80 int, +f81 int, +f82 int, +f83 int, +f84 int, +f85 int, +f86 int, +f87 int, +f88 int, +f89 int, +f90 int, +f91 int, +f92 int, +f93 int, +f94 int, +f95 int, +f96 int, +f97 int, +f98 int, +f99 int, +f100 int, +f101 int, +f102 int, +f103 int, +f104 int, +f105 int, +f106 int, +f107 int, +f108 int, +f109 int, +f110 int, +f111 int, +f112 int, +f113 int, +f114 int, +f115 int, +f116 int, +f117 int, +f118 int, +f119 int, +f120 int, +f121 int, +f122 int, +f123 int, +f124 int, +f125 int, +f126 int, +f127 int, +f128 int, +f129 int, +f130 int, +f131 int, +f132 int, +f133 int, +f134 int, +f135 int, +f136 int, +f137 int, +f138 int, +f139 int, +f140 int, +f141 int, +f142 int, +f143 int, +f144 int, +f145 int, +f146 int, +f147 int, +f148 int, +f149 int, +f150 int, +f151 int, +f152 int, +f153 int, +f154 int, +f155 int, +f156 int, +f157 int, +f158 int, +f159 int, +f160 int, +f161 int, +f162 int, +f163 int, +f164 int, +f165 int, +f166 int, +f167 int, +f168 int, +f169 int, +f170 int, +f171 int, +f172 int, +f173 int, +f174 int, +f175 int, +f176 int, +f177 int, +f178 int, +f179 int, +f180 int, +f181 int, +f182 int, +f183 int, +f184 int, +f185 int, +f186 int, +f187 int, +f188 int, +f189 int, +f190 int, +f191 int, +f192 int, +f193 int, +f194 int, +f195 int, +f196 int, +f197 int, +f198 int, +f199 int, +f200 int, +f201 int, +f202 int, +f203 int, +f204 int, +f205 int, +f206 int, +f207 int, +f208 int, +f209 int, +f210 int, +f211 int, +f212 int, +f213 int, +f214 int, +f215 int, +f216 int, +f217 int, +f218 int, +f219 int, +f220 int, +f221 int, +f222 int, +f223 int, +f224 int, +f225 int, +f226 int, +f227 int, +f228 int, +f229 int, +f230 int, +f231 int, +f232 int, +f233 int, +f234 int, +f235 int, +f236 int, +f237 int, +f238 int, +f239 int, +f240 int, +f241 int, +f242 int, +f243 int, +f244 int, +f245 int, +f246 int, +f247 int, +f248 int, +f249 int, +f250 int, +f251 int, +f252 int, +f253 int, +f254 int, +f255 int, +f256 int, +f257 int, +f258 int, +f259 int, +f260 int, +f261 int, +f262 int, +f263 int, +f264 int, +f265 int, +f266 int, +f267 int, +f268 int, +f269 int, +f270 int, +f271 int, +f272 int, +f273 int, +f274 int, +f275 int, +f276 int, +f277 int, +f278 int, +f279 int, +f280 int, +f281 int, +f282 int, +f283 int, +f284 int, +f285 int, +f286 int, +f287 int, +f288 int, +f289 int, +f290 int, +f291 int, +f292 int, +f293 int, +f294 int, +f295 int, +f296 int, +f297 int, +f298 int, +f299 int, +f300 int, + primary key (f1)); + +insert into t300 set f1= 1; + +sync_slave_with_master; + +# +# prove that slave processed the create as well as the insert +# +eval select f300 from t300; +select count(*) as one from t300; + +--echo *** Cleanup *** +connection master; +DROP TABLE t300; +sync_slave_with_master; + +# END of Test Case + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_savepoint.test b/mysql-test/suite/rpl/t/rpl_savepoint.test new file mode 100644 index 00000000..31af6151 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_savepoint.test @@ -0,0 +1,43 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +--echo # +--echo # Bug#50124 Rpl failure on DROP table with concurrent txn/non-txn +--echo # DML flow and SAVEPOINT +--echo # + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS tt, nt; +--enable_warnings + +CREATE TABLE tt (i INT) ENGINE = InnoDB; +CREATE TABLE nt (i INT) ENGINE = MyISAM; +FLUSH LOGS; +START TRANSACTION; +INSERT INTO nt VALUES (1); +SAVEPOINT insert_statement; +INSERT INTO tt VALUES (1); + +connection master1; +--echo # Sending: +--send DROP TABLE tt + +connection master; +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND info = "DROP TABLE tt"; +--source include/wait_condition.inc +ROLLBACK TO SAVEPOINT insert_statement; +COMMIT; + +connection master1; +--echo # Reaping: DROP TABLE tt +--reap +FLUSH LOGS; + +connection master; +DROP TABLE nt; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync.test new file mode 100644 index 00000000..5c17bcb2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync.test @@ -0,0 +1 @@ +--source include/rpl_semi_sync.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test new file mode 100644 index 00000000..2d91d2e4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync.test @@ -0,0 +1,4 @@ +--source include/have_binlog_format_statement.inc +set global rpl_semi_sync_master_wait_point=AFTER_SYNC; +source rpl_semi_sync.test; +set global rpl_semi_sync_master_wait_point=default; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test new file mode 100644 index 00000000..47af6c34 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_after_sync_row.test @@ -0,0 +1,4 @@ +--source include/have_binlog_format_row.inc +set global rpl_semi_sync_master_wait_point=AFTER_SYNC; +source rpl_semi_sync.test; +set global rpl_semi_sync_master_wait_point=default; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt new file mode 100644 index 00000000..4cfb5d53 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event-master.opt @@ -0,0 +1 @@ +--max-connections=40 diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test new file mode 100644 index 00000000..4d96fd69 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test @@ -0,0 +1,90 @@ +source include/not_embedded.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +let $engine_type= InnoDB; + +# Suppress warnings that might be generated during the test +connection master; +call mtr.add_suppression("Timeout waiting for reply of binlog"); +call mtr.add_suppression("Semi-sync master .* waiting for slave reply"); +call mtr.add_suppression("Read semi-sync reply"); +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); +call mtr.add_suppression("mysqld: Got an error reading communication packets"); + +connection slave; +call mtr.add_suppression("Master server does not support semi-sync"); +call mtr.add_suppression("Semi-sync slave .* reply"); +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); + +connection master; +set global rpl_semi_sync_master_enabled = 1; + +connection slave; +source include/stop_slave.inc; +set global rpl_semi_sync_slave_enabled = 1; + +source include/start_slave.inc; + +connection master; +SET GLOBAL event_scheduler = ON; + +replace_result $engine_type ENGINE_TYPE; +eval CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=$engine_type; +INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a'); +--disable_warnings +INSERT INTO t1 SELECT i+5, f FROM t1; +INSERT INTO t1 SELECT i+10, f FROM t1; +--enable_warnings +CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND +DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID())); +CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND +DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev2_',CONNECTION_ID())); + +connection slave; +STOP SLAVE IO_THREAD; + +connection master; +let $run = 20; +while ($run) +{ + connect (m$run,localhost,root,,); + connection m$run; + send; + eval UPDATE t1 SET f = CONCAT('up_',CONNECTION_ID()) WHERE i = $run; + connection master; + dec $run; +} + +connection master; +SET GLOBAL event_scheduler = OFF; + +let $run = 20; +while ($run) +{ + connection m$run; + reap; + disconnect m$run; + dec $run; +} + +# +# Clean up +# +connection slave; +source include/stop_slave.inc; +set global rpl_semi_sync_slave_enabled = 0; + +connection master; +set global rpl_semi_sync_master_enabled = 0; + +connection slave; +source include/start_slave.inc; + +connection master; + +DROP EVENT ev1; +DROP EVENT ev2; +DROP TABLE t1; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt new file mode 100644 index 00000000..4cfb5d53 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync-master.opt @@ -0,0 +1 @@ +--max-connections=40 diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test new file mode 100644 index 00000000..527900fd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event_after_sync.test @@ -0,0 +1,3 @@ +set global rpl_semi_sync_master_wait_point=AFTER_SYNC; +source rpl_semi_sync_event.test; +set global rpl_semi_sync_master_wait_point=default; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test new file mode 100644 index 00000000..96f7e805 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test @@ -0,0 +1,74 @@ +source include/not_embedded.inc; +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +# +# Semisync initialization +# +--connection master +RESET MASTER; +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--connection slave +source include/stop_slave.inc; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +# Prove fixes to +# MDEV-19376 Assert (!m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name...) +# +# +# Run few queries to replicate/execute on slave. +# Stop the slave applier. +# Replicate/not-executed few more. +# Restart the slave. +# +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a = 1; +--source include/save_master_gtid.inc +--let $resume_gtid = $master_pos +FLUSH LOGS; +INSERT INTO t1 SET a = 2; + +--sync_slave_with_master +--connection slave +--source include/stop_slave_sql.inc + +--connection master +INSERT INTO t1 SET a = 3; + +# the sync connection is 'slave' by default +--source include/sync_slave_io_with_master.inc +--connection slave +--source include/stop_slave_io.inc + +--connection master +RESET MASTER; +--eval SET @@global.gtid_binlog_state = '$resume_gtid' + +# The resume gtid is set up to point to the very first binlog file +--connection slave +CHANGE MASTER TO MASTER_USE_GTID = slave_pos; +--eval SET @@global.gtid_slave_pos = '$resume_gtid' +# Yet the slave io first submits the last received binlog file name:pos. +--source include/start_slave.inc + +# Here goes the cracker. +--connection master +INSERT INTO t1 SET a = 4; + +# +# Clean up +# +--connection master +DROP TABLE t1; +--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master + +--sync_slave_with_master +source include/stop_slave.inc; +--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave +source include/start_slave.inc; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test new file mode 100644 index 00000000..2224f78d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test @@ -0,0 +1,60 @@ +# MDEV-16812 Semisync slave io thread segfaults at STOP-SLAVE handling +# +# The test verifies that the semisync-enabled slave io thread +# finishes off as specified in particular trying to connect even to a shut down +# master for a semisync firewell routine. + +source include/not_embedded.inc; +source include/have_debug.inc; +source include/master-slave.inc; + +--connection master + +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled ` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--connection slave +source include/stop_slave.inc; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled ` +SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; + +--sync_slave_with_master + +connection master; +--echo # Shutdown master +--let $rpl_server_number=1 +source include/rpl_stop_server.inc; + +--connection slave +--source include/stop_slave.inc + +#connection master; +--echo # Restart master +--let $rpl_server_number=1 +source include/rpl_start_server.inc; + +# +# Clean up +# +--connection slave +--source include/stop_slave.inc +--source include/start_slave.inc + +--connection master +SET @@GLOBAL.debug_dbug=""; +--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master + +--connection master +DROP TABLE t1; + +--sync_slave_with_master +source include/stop_slave.inc; +--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test b/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test new file mode 100644 index 00000000..587e1290 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_skip_repl.test @@ -0,0 +1,66 @@ +# MDEV-14721 Big transaction events get lost on semisync master when +# replicate_events_marked_for_skip=FILTER_ON_MASTER +# +# When events of a big transaction are binlogged offsetting over 2GB from +# the beginning of the log the semisync master's dump thread +# lost such events. +# The test verifies the fixes' correctness simulating the 2GB offset. + +source include/not_embedded.inc; +source include/have_innodb.inc; +source include/have_debug.inc; +source include/master-slave.inc; + +--connection master +# Suppress warnings that might be generated during the test +call mtr.add_suppression("Timeout waiting for reply of binlog"); + +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled` +--let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +SET @@GLOBAL.rpl_semi_sync_master_timeout=100; + +--connection slave +--let $sav_skip_marked_slave=`SELECT @@GLOBAL.replicate_events_marked_for_skip` +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` +source include/stop_slave.inc; +SET @@GLOBAL.replicate_events_marked_for_skip=FILTER_ON_MASTER; +SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +--connection master +CREATE TABLE t1 (a INT) ENGINE=innodb; + +# Make the following events as if they offset over 2GB from the beginning of binlog +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="d,dbug_master_binlog_over_2GB"; +SET @@SESSION.skip_replication=1; +INSERT INTO t1 SET a=1; +SET @@SESSION.skip_replication=0; +INSERT INTO t1 SET a=0; +SET @@GLOBAL.debug_dbug=""; + +# The current binlog is inconsistent so let's rotate it away +# to clean up simulation results. +FLUSH LOGS; + +--sync_slave_with_master + +# +# Clean up +# +--connection master +SET @@GLOBAL.debug_dbug = @saved_dbug; +--eval SET @@GLOBAL.rpl_semi_sync_master_timeout = $sav_timeout_master +--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = $sav_enabled_master + +--connection master +DROP TABLE t1; + +--sync_slave_with_master +source include/stop_slave.inc; +--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_slave +--eval SET @@GLOBAL.replicate_events_marked_for_skip = $sav_skip_marked_slave + +source include/start_slave.inc; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt new file mode 100644 index 00000000..a1b687d6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol-slave.opt @@ -0,0 +1 @@ +--slave_compressed_protocol diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test new file mode 100644 index 00000000..bc05bec2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_compressed_protocol.test @@ -0,0 +1,55 @@ +################################################################################ +# Bug#26027024 SLAVE_COMPRESSED_PROTOCOL DOESN'T WORK WITH SEMI-SYNC +# REPLICATION IN MYSQL-5.7 +# +# Steps to reproduce: +# 1) Set slave_compressed_protocol ON on Slave. +# 2) Do some sample work on Master +# 3) After the work is synced on Slave, check that there is no error +# (Read semi-sync reply magic number error) on Slave. +# 4) Cleanup +################################################################################ +# Test is independent of Binlog format. One of the three formats is enough +# for testing. Choosing 'Row' format. +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled ` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--connection slave +source include/stop_slave.inc; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled ` +SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1; +source include/start_slave.inc; + +--connection master +# Do some sample work on Master with slave_compressed_protocol ON. +# (slave_compressed_protocol is set to ON in -slave.opt file of this test.) +CREATE TABLE t1 (i INT); +DROP TABLE t1; + +# Make sure sync is done, so that next 'assert' step can be executed without +# any issues. +--source include/rpl_sync.inc + +# Without the fix, the test would have generated few +# errors in the error log. With the fix, test will +# pass without any errors in the error log. +--let $assert_text= Check that there is no 'Read semi-sync reply magic number error' in error log. +--let $assert_select=Read semi-sync reply magic number error +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_count= 0 +--let $assert_only_after = CURRENT_TEST:rpl.rpl_semi_sync_slave_compressed_protocol.test +--source include/assert_grep.inc + +--connection master +--evalp SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master + +--connection slave +source include/stop_slave.inc; +--evalp SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave +source include/start_slave.inc; + +# Cleanup +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test new file mode 100644 index 00000000..f0eb474f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_reply_fail.test @@ -0,0 +1,87 @@ +# ==== Purpose ==== +# +# Test verifies that slave IO thread doesn't report an error, when slave fails +# to send an acknowledgment to master with semi sync replication in use. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Have semi synchronous replication in use. +# 1 - Enable a debug simulation point which simulates network flush failure +# at the time of slave reply operation. +# 2 - Do some operation on master and wait for it to be replicated. Master +# will timeout waiting for reply from slave. +# 3 - Check the slave error log for appropriate error message regarding +# net_flush operation failure. +# 4 - Remove the debug simulation and do some more DML operations on master +# and wait for them to be replicated. +# 5 - Slave will be able to replicate and data is consistent on both master +# and slave. Semi sync will be automatically turned on. +# +# ==== References ==== +# +# MDEV-20217: Semi_sync: Last_IO_Error: Fatal error: Failed to run +# 'after_queue_event' hook +# +--source include/have_debug.inc +--source include/master-slave.inc + +--connection slave +--source include/stop_slave.inc + +--connection master +call mtr.add_suppression("Timeout waiting for reply of binlog*"); +--let $sav_timeout_master=`SELECT @@GLOBAL.rpl_semi_sync_master_timeout` +set global rpl_semi_sync_master_enabled = ON; +SET @@GLOBAL.rpl_semi_sync_master_timeout=100; +create table t1 (i int); + +--connection slave +set global rpl_semi_sync_slave_enabled = ON; +CALL mtr.add_suppression("Semi-sync slave net_flush*"); +SET @save_debug= @@global.debug; +SET GLOBAL debug_dbug="+d,semislave_failed_net_flush"; +--source include/start_slave.inc + +--connection master +--sync_slave_with_master + +# Check error log for correct messages. +let $log_error_= `SELECT @@GLOBAL.log_error`; +if(!$log_error_) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} +--echo "Assert that the net_fulsh() reply failed is present in slave error log. +--let SEARCH_FILE=$log_error_ +--let SEARCH_PATTERN=Semi-sync slave net_flush\(\) reply failed +--source include/search_pattern_in_file.inc + +--echo "Assert that Slave IO thread is up and running." +SHOW STATUS LIKE 'Slave_running'; +let $status= query_get_value("show slave status", Slave_IO_Running, 1); +echo Slave_IO_Running= $status; + +--echo "Clear the network failure simulation." +SET GLOBAL debug_dbug= @save_debug; + +--connection master +insert into t1 values (10); +--sync_slave_with_master + +--connection slave +--echo # Compare the tables on master and slave. +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + +--connection master +drop table t1; +--sync_slave_with_master +set global rpl_semi_sync_slave_enabled = OFF; + +--connection master +set global rpl_semi_sync_master_enabled = OFF; +--eval SET @@GLOBAL.rpl_semi_sync_master_timeout = $sav_timeout_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt new file mode 100644 index 00000000..d84ebab5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave-master.opt @@ -0,0 +1 @@ +--rpl_semi_sync_master_enabled=0 --rpl_semi_sync_master_wait_no_slave=0 diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test new file mode 100644 index 00000000..fecd0e25 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_no_slave.test @@ -0,0 +1,14 @@ +# The test verifies master crash of MDEV-18096 when the server starts with +# rpl_semi_sync_master_enabled = OFF rpl_semi_sync_master_wait_no_slave = OFF + +--source include/master-slave.inc +--source include/have_binlog_format_mixed.inc + +--connection master +CREATE TABLE t1 (a INT); +INSERT INTO t1 SET a=1; +DROP TABLE t1; + +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt new file mode 100644 index 00000000..e49ae455 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.opt @@ -0,0 +1 @@ +--log_bin diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test new file mode 100644 index 00000000..dcff4030 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test @@ -0,0 +1,253 @@ +source include/not_embedded.inc; +source include/have_innodb.inc; + +# +# This test the rpl_semi_sync_master_wait_point functionality +# and illustrates the differences between the two values AFTER_COMMIT and +# AFTER_SYNC +# + +--echo # +--echo # Preparation +--echo # + +CREATE TABLE t1 (i INT NOT NULL, PRIMARY KEY (i)) ENGINE=InnoDB; +RESET MASTER; + +let $save_timeout = `select @@global.rpl_semi_sync_master_timeout`; +let $save_wait_no_slave = `select @@global.rpl_semi_sync_master_wait_no_slave`; +let $save_wait_point = `select @@global.rpl_semi_sync_master_wait_point`; + +SET @@global.rpl_semi_sync_master_timeout = 60000; +SET @@global.rpl_semi_sync_master_wait_no_slave = 1; + +--echo # It's okay to see "Killed" but we should not see "Timeout" in the log. +call mtr.add_suppression("Killed waiting for reply of binlog"); +call mtr.add_suppression("Run function 'after_commit' in plugin 'rpl_semi_sync_master' failed"); +call mtr.add_suppression("Run function 'after_sync' in plugin 'rpl_semi_sync_master' failed"); + +--echo # +--echo # Test wait point = AFTER_COMMIT +--echo # +SET @@global.rpl_semi_sync_master_wait_point = AFTER_COMMIT; + +--echo # Make another connection to INSERT from. +connect (other,localhost,root,,); +connection other; +let $other_connection_id = `SELECT CONNECTION_ID()`; + +connection default; + +--disable_query_log +eval SET @other_connection_id = $other_connection_id; +--enable_query_log + +SET GLOBAL rpl_semi_sync_master_enabled = 1; + +--echo # Go ahead and send the INSERT; it should block. +connection other; +send INSERT INTO t1 (i) VALUES (1); + +connection default; + +let $wait_condition = + SELECT COUNT(*) > 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id + AND state = "Waiting for semi-sync ACK from slave"; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be waiting. +SELECT state AS should_be_waiting +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The insert should be visible to other threads +SELECT * FROM t1 ORDER BY 1; + +--echo # Kill the waiting thread; it should die immediately. +KILL @other_connection_id; + +--echo # Collect the error from the INSERT thread; it should be disconnected. +connection other; +--error 2013,ER_CONNECTION_KILLED +reap; + +connection default; + +--echo # Wait for INSERT thread to actually disappear (KILL closes connection +--echo # before thread actually finishes its processing). +let $wait_condition = + SELECT COUNT(*) = 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be gone. +SELECT state AS should_be_empty_set +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The insert is still there +SELECT * FROM t1 ORDER BY 1; + +connection default; +disconnect other; + +--echo # Make another connection to INSERT from. +connect (other,localhost,root,,); +connection other; +let $other_connection_id = `SELECT CONNECTION_ID()`; +connection default; +--disable_query_log +eval SET @other_connection_id = $other_connection_id; +--enable_query_log + +--echo # Go ahead and send the INSERT; it should block. +connection other; +send INSERT INTO t1 (i) VALUES (2); + +connection default; + +let $wait_condition = + SELECT COUNT(*) > 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id + AND state = "Waiting for semi-sync ACK from slave"; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be waiting. +SELECT state AS should_be_waiting +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The insert should be visible to other threads +SELECT * FROM t1 ORDER BY 1; + +--echo # Now restart server +--source include/restart_mysqld.inc +--echo # Done restarting server + +--echo # Reset setting that were lost in restart +SET @@global.rpl_semi_sync_master_timeout = 60000; +SET @@global.rpl_semi_sync_master_wait_no_slave = 1; + +--echo # Check that row is still there +SELECT * FROM t1 ORDER BY 1; + +disconnect other; + +--echo # +--echo # Test wait point = AFTER_SYNC +--echo # +SET @@global.rpl_semi_sync_master_wait_point = AFTER_SYNC; + +--echo # Make another connection to INSERT from. +connect (other,localhost,root,,); +connection other; +let $other_connection_id = `SELECT CONNECTION_ID()`; + +connection default; + +--disable_query_log +eval SET @other_connection_id = $other_connection_id; +--enable_query_log + +SET GLOBAL rpl_semi_sync_master_enabled = 1; + +--echo # Go ahead and send the INSERT; it should block. +connection other; +send INSERT INTO t1 (i) VALUES (3); + +connection default; + +let $wait_condition = + SELECT COUNT(*) > 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id + AND state = "Waiting for semi-sync ACK from slave"; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be waiting. +SELECT state AS should_be_waiting +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The insert should NOT be visible to other threads +SELECT * FROM t1 ORDER BY 1; + +--echo # Kill the waiting thread; it should die immediately. +KILL @other_connection_id; + +--echo # Collect the error from the INSERT thread; it should be disconnected. +connection other; +--error 2013,ER_CONNECTION_KILLED +reap; + +connection default; + +--echo # Wait for INSERT thread to actually disappear (KILL closes connection +--echo # before thread actually finishes its processing). +let $wait_condition = + SELECT COUNT(*) = 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be gone. +SELECT state AS should_be_empty_set +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The row inserted is there +SELECT * FROM t1 ORDER BY 1; + +connection default; +disconnect other; + +--echo # Make another connection to INSERT from. +connect (other,localhost,root,,); +connection other; +let $other_connection_id = `SELECT CONNECTION_ID()`; +connection default; +--disable_query_log +eval SET @other_connection_id = $other_connection_id; +--enable_query_log + +--echo # Go ahead and send the INSERT; it should block. +connection other; +send INSERT INTO t1 (i) VALUES (4); + +connection default; + +let $wait_condition = + SELECT COUNT(*) > 0 AS should_be_true + FROM information_schema.processlist + WHERE id = @other_connection_id + AND state = "Waiting for semi-sync ACK from slave"; +--source include/wait_condition.inc + +--echo # The INSERT thread should now be waiting. +SELECT state AS should_be_waiting +FROM information_schema.processlist WHERE id = @other_connection_id; + +--echo # The insert should NOT be visible to other threads +SELECT * FROM t1 ORDER BY 1; + +--echo # Now restart server +--source include/restart_mysqld.inc +--echo # Done restarting server + +--echo # Reset setting that were lost in restart +SET @@global.rpl_semi_sync_master_timeout = 60000; +SET @@global.rpl_semi_sync_master_wait_no_slave = 1; + +--echo # But the row inserted is there +SELECT * FROM t1 ORDER BY 1; + +disconnect other; + +--echo # +--echo # Cleanup +--echo # +SET GLOBAL rpl_semi_sync_master_enabled = 0; +DROP TABLE t1; + +eval SET @@global.rpl_semi_sync_master_timeout = $save_timeout; +eval SET @@global.rpl_semi_sync_master_wait_no_slave = $save_wait_no_slave; +eval SET @@global.rpl_semi_sync_master_wait_point = $save_wait_point; diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt new file mode 100644 index 00000000..2672d4ff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-master.opt @@ -0,0 +1 @@ +--binlog_format=row diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt new file mode 100644 index 00000000..2672d4ff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues-slave.opt @@ -0,0 +1 @@ +--binlog_format=row diff --git a/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test new file mode 100644 index 00000000..f67c6e2a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semisync_ali_issues.test @@ -0,0 +1,425 @@ +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/master-slave.inc + +CALL mtr.add_suppression("Failed to start semi-sync ACK receiver thread.*"); +CALL mtr.add_suppression("Failed to register slave to semi-sync ACK receiver thread.*"); +CALL mtr.add_suppression("Failed to stop ack receiver thread on pthread_join.*"); +CALL mtr.add_suppression("Got an error reading communication packets:*"); +CALL mtr.add_suppression("Timeout waiting for reply of binlog*"); +CALL mtr.add_suppression("slave_read_sync_header*"); +CALL mtr.add_suppression("Missing magic number for semi-sync*"); +CALL mtr.add_suppression("Got timeout reading communication packets*"); +CALL mtr.add_suppression("Failed to call*"); +CALL mtr.add_suppression("Execution failed on master*"); +CALL mtr.add_suppression("Failed on request_dump()*"); +CALL mtr.add_suppression("Semi-sync master failed on*"); +CALL mtr.add_suppression("Master command COM_BINLOG_DUMP failed*"); +CALL mtr.add_suppression("on master failed*"); +CALL mtr.add_suppression("Master server does not support semi-sync*"); +CALL mtr.add_suppression("Semi-sync slave net_flush*"); +CALL mtr.add_suppression("Failed to flush master info*"); +CALL mtr.add_suppression("Request to stop slave SQL Thread received while apply*"); + +connection master; +echo [ enable semi-sync on master ]; +set global rpl_semi_sync_master_enabled = 1; +show variables like 'rpl_semi_sync_master_enabled'; + +connection slave; +echo [ enable semi-sync on slave ]; +stop slave; +set global rpl_semi_sync_slave_enabled = 1; +start slave; +let $status_var= rpl_semi_sync_slave_status; +let $status_var_value= ON; +source include/wait_for_status_var.inc; +show status like 'rpl_semi_sync_slave%'; + + +connection master; +CREATE TABLE t1(a INT) ENGINE=InnoDB; +sync_slave_with_master; + +connection master; +connect(con1,localhost,root,,); +connect(con2,localhost,root,,); +connect(con3,localhost,root,,); + +show status like 'Rpl_semi_sync_master_clients'; +show status like "rpl_semi_sync_master_yes_tx"; + +--echo ######################################### +--echo # Test rpl_semi_sync_master_wait_point # +--echo ######################################### +--echo # Test after_sync and after_commit first. + +--echo #Test after_sync +connection con1; +# Let's set a very large timeout value for testing purpose. +SET GLOBAL rpl_semi_sync_master_timeout = 1000000; +SET GLOBAL rpl_semi_sync_master_wait_point= 'AFTER_SYNC'; +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL after_sync_done WAIT_FOR end"; +--send INSERT into t1 values (1); + +connection con2; +SET DEBUG_SYNC= "now WAIT_FOR after_sync_done"; + +sync_slave_with_master; +--echo #slave can see record (1) after sync slave with master +select * from t1; + +connection con2; +--echo #con2 shouldn't see record (1) +select * from t1; +SET DEBUG_SYNC= "now SIGNAL end"; + +connection con1; +reap; + +connection con1; +select * from t1; +truncate table t1; + +sync_slave_with_master; + +# Test more threads in one semisync queue +connection con1; +SET DEBUG_SYNC= 'reset'; +SET DEBUG_SYNC= "commit_before_get_LOCK_log SIGNAL before_fetch_done WAIT_FOR more_queue"; +#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR more_queue"; +--send INSERT into t1 VALUES (1); + +connection con2; +SET DEBUG_SYNC= "now WAIT_FOR before_fetch_done"; +SET DEBUG_SYNC= "after_semisync_queue SIGNAL more_queue"; +INSERT INTO t1 VALUES (2); + +connection con1; +reap; + +# Test more threads in one semisync queue, but disable semisync before +# waiting. +connection con1; +SET DEBUG_SYNC= 'reset'; +SET DEBUG_SYNC= "commit_before_get_LOCK_log SIGNAL before_fetch_done WAIT_FOR disable_semisync"; +#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR more_queue"; +#SET DEBUG_SYNC= "before_semisync_fetch SIGNAL before_fetch_done WAIT_FOR disable_semisync"; +--send INSERT into t1 VALUES (3); + +connection con2; +SET DEBUG_SYNC= "now WAIT_FOR before_fetch_done"; +SET GLOBAL rpl_semi_sync_master_enabled= 0; +SET DEBUG_SYNC= "now SIGNAL disable_semisync"; + +connection con1; +reap; +SET GLOBAL rpl_semi_sync_master_enabled = 1; +show status like 'Rpl_semi_sync_master_clients'; + +--echo #Test after_commit +connection con1; +SET GLOBAL rpl_semi_sync_master_wait_point= 'AFTER_COMMIT'; +SET DEBUG_SYNC= "after_group_after_commit SIGNAL after_commit_done WAIT_FOR end"; +--send INSERT into t1 values (4); + +connection con2; +SET DEBUG_SYNC= "now WAIT_FOR after_commit_done"; + +sync_slave_with_master; +select * from t1; + +connection con2; +select * from t1; +SET DEBUG_SYNC= "now SIGNAL end"; + +connection con1; +reap; + +connection con1; +select * from t1; +truncate table t1; + +--echo ####################################################### +--echo # Test some other options in order to cover the patch # +--echo ####################################################### +connection slave; +--echo # Test rpl_semi_sync_slave_trace_level +SET GLOBAL rpl_semi_sync_slave_trace_level= 1; +SET GLOBAL rpl_semi_sync_slave_trace_level= 16; +SET GLOBAL rpl_semi_sync_slave_trace_level= 64; +SET GLOBAL rpl_semi_sync_slave_trace_level= 128; +SET GLOBAL rpl_semi_sync_slave_trace_level= 32; +connection master; +--echo # Test rpl_semi_sync_master_trace_level +SET GLOBAL rpl_semi_sync_master_trace_level= 1; +SET GLOBAL rpl_semi_sync_master_trace_level= 16; +SET GLOBAL rpl_semi_sync_master_trace_level= 64; +SET GLOBAL rpl_semi_sync_master_trace_level= 128; +SET GLOBAL rpl_semi_sync_master_trace_level= 32; +--echo # Test rpl_semi_sync_master_timeout +SET GLOBAL rpl_semi_sync_master_timeout= 1000; +SET GLOBAL rpl_semi_sync_master_timeout= 10000; +SET GLOBAL rpl_semi_sync_master_timeout = 1000000; + +--echo # Test rpl_semi_sync_slave_kill_conn_timeout +SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 10; +SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 20; +SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 60; +SET GLOBAL rpl_semi_sync_slave_kill_conn_timeout= 5; + +--echo ############################################ +--echo # Test rpl_semi_sync_master_wait_no_slave # +--echo ############################################ +SET GLOBAL rpl_semi_sync_master_wait_no_slave = 1; +connection slave; +STOP SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_stop.inc + +connection con1; +SET GLOBAL rpl_semi_sync_master_timeout = 1000; +--send INSERT INTO t1 values (1); + +connection con1; +reap; +echo # Rpl_semi_sync_master_no_tx should be non-zero +SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx'; + +# test rpl_semi_sync_master_wait_no_slave = 0 +connection slave; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +connection con1; +INSERT INTO t1 values (2); +sync_slave_with_master; +connection con1; +let $status_var= Rpl_semi_sync_master_clients; +let $status_var_value= 1; +source include/wait_for_status_var.inc; +let $status_var= Rpl_semi_sync_master_status; +let $status_var_value= ON; +source include/wait_for_status_var.inc; +show status like 'Rpl_semi_sync_master_clients'; +show status like 'Rpl_semi_sync_master_status'; + +connection slave; +STOP SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_stop.inc + +connection con1; +SET GLOBAL rpl_semi_sync_master_wait_no_slave= 0; +SET GLOBAL rpl_semi_sync_master_timeout= 1000000000; +INSERT INTO t1 values (3); +show status like 'Rpl_semi_sync_master_clients'; +show status like 'Rpl_semi_sync_master_status'; + + +connection slave; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +connection con1; +--let $status_var= Rpl_semi_sync_master_status +--let $status_var_value=ON +--source include/wait_for_status_var.inc + +SET GLOBAL rpl_semi_sync_master_timeout= 10000000; +SET GLOBAL rpl_semi_sync_master_wait_no_slave= 1; +INSERT INTO t1 values (4); +sync_slave_with_master; + +connection con1; +show status like 'Rpl_semi_sync_master_status'; +show status like 'Rpl_semi_sync_master_clients'; + +--echo ########################################## +--echo # Test rpl_semi_sync_slave_delay_master # +--echo ########################################## + +connection slave; +SET GLOBAL rpl_semi_sync_slave_delay_master= 1; +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +connection con1; +INSERT INTO t1 values (3); +--source include/sync_slave_io_with_master.inc + +connection con1; +show status like 'Rpl_semi_sync_master_clients'; +show status like 'Rpl_semi_sync_master_status'; + +sync_slave_with_master; + +connection slave; +select * from t1 order by a; +connection con1; +select * from t1 order by a; + +connection slave; +SET GLOBAL rpl_semi_sync_slave_delay_master = 0; +STOP SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_stop.inc +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +--echo ########################################################## +--echo # Test rpl_semi_sync_master_enabled and new ACK thread # +--echo ######################################################### +connection con1; +SET GLOBAL rpl_semi_sync_master_enabled = 0; + +let $status_var= Rpl_semi_sync_master_clients; +let $status_var_value= 1; +source include/wait_for_status_var.inc; +show status like 'Rpl_semi_sync_master_clients'; + +INSERT INTO t1 VALUES (1); +SET GLOBAL rpl_semi_sync_master_enabled = 1; +INSERT INTO t1 VALUES (2); +show status like 'Rpl_semi_sync_master_clients'; + +--echo # Test failure of select error . +SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error'; +# It can still receive ACK from semi-sync slave +INSERT INTO t1 VALUES(3); +sync_slave_with_master; + +connection con1; +--echo # Test failure of pthread_create +SET GLOBAL rpl_semi_sync_master_enabled = 0; +SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure'; +SET GLOBAL rpl_semi_sync_master_enabled= ON; + +--let $wait_condition= SELECT @@global.rpl_semi_sync_master_enabled = 0 +--source include/wait_condition.inc + +# Todo: implement the thread join failure simulation +--echo # Test failure of pthread_join +#SET GLOBAL DEBUG = 'd,rpl_semisync_simulate_thread_join_failure'; +#SET GLOBAL rpl_semi_sync_master_enabled= ON; +# +#--let $wait_condition= SELECT @@global.rpl_semi_sync_master_enabled = 0 +#--source include/wait_condition.inc +SET GLOBAL rpl_semi_sync_master_enabled= OFF; + +--echo # +--echo # Failure on registering semisync slave +--echo # +SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure'; +SET GLOBAL rpl_semi_sync_master_enabled= ON; + +connection slave; +STOP SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_stop.inc +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +connection con1; +#--echo # Should be Zero. +# Todo: implement the add_slave_failure simulation. Meanwhile +# the status will be 1. +# show status like 'Rpl_semi_sync_master_clients'; +SET GLOBAL debug=''; + +--let $status_var= Rpl_semi_sync_master_clients +--let $status_var_value= 1 +--let $status_type= GLOBAL +--source include/wait_for_status_var.inc + +connection slave; +--disable_warnings +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc +--enable_warnings + +connection con1; +sync_slave_with_master; + +show status like 'Rpl_semi_sync_master_clients'; + +--echo ################################################################## +--echo # Test fixing of BUG#70669 # +--echo #SLAVE CAN'T CONTINUE REPLICATION AFTER MASTER'S CRASH RECOVERY # +--echo ################################################################# +connection con1; +SET GLOBAL sync_binlog = 1; +CREATE TABLE t2 (c1 INT); +sync_slave_with_master; + +connection con1; +# Block the session before its events are synced to disk +#SET DEBUG_SYNC = 'before_sync_binlog_file SIGNAL before_sync_done WAIT_FOR continue'; +send INSERT INTO t2 values (1); + +connection slave; +--let $table= t2 +--let $count= 1 +--source include/wait_until_rows_count.inc + +connection con2; +#SET DEBUG_SYNC= "now WAIT_FOR before_sync_done"; +#SET DEBUG_SYNC = "now SIGNAL continue"; + +connection con1; +reap; + +sync_slave_with_master; +show tables like 't2'; +select * from t2; + +connection con1; +#SET DEBUG_SYNC= "before_update_pos SIGNAL leader_ready WAIT_FOR follower_ready"; +send INSERT INTO t2 VALUES (2); + +connection con2; +#SET DEBUG_SYNC= "now WAIT_FOR leader_ready"; +#SET DEBUG_SYNC= "after_sync_queue SIGNAL follower_ready"; +send INSERT INTO t2 VALUES (3); + +connection con1; +reap; +connection con2; +reap; + +connection con1; +#SET DEBUG_SYNC = 'before_sync_binlog_file SIGNAL before_sync_done WAIT_FOR continue'; +SET GLOBAL sync_binlog = 0; + +# Todo: fix this simulation and implement the intended sync protocol. +# As a workaround the DROP sender explicitly okays +# which naturally increments the binlog position. +#send DROP TABLE t2; +DROP TABLE t2; + +connection con2; +#SET DEBUG_SYNC= "now WAIT_FOR before_sync_done"; + +sync_slave_with_master; + +# t2 should be dropped +show tables like 't2'; + +connection con2; +#SET DEBUG_SYNC = "now SIGNAL continue"; + +# This block is commented out on purpose. See the todo/workaround above. +#connection con1; +#reap; + + +--echo #cleanup +connection master; +SET DEBUG_SYNC= 'reset'; +disconnect con1; +disconnect con2; +disconnect con3; +SET GLOBAL rpl_semi_sync_master_timeout= 10000; +SET GLOBAL rpl_semi_sync_master_enabled = 0; +DROP TABLE t1; +connection slave; +SET GLOBAL rpl_semi_sync_slave_enabled = 0; +stop slave;start slave; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_server_id1.test b/mysql-test/suite/rpl/t/rpl_server_id1.test new file mode 100644 index 00000000..90198a4a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_server_id1.test @@ -0,0 +1,22 @@ +# This test checks that the slave I/O thread refuses to start if slave +# and master have the same server id (because this is a useless setup, +# and otherwise SHOW SLAVE STATUS shows progress but all queries are +# ignored, which has caught our customers), unless +# --replicate-same-server-id. + +--let $rpl_topology= 2->2 +--let $rpl_skip_start_slave= 1 +--source include/rpl_init.inc + +--connection server_2 +START SLAVE; +# 1593 = ER_SLAVE_FATAL_ERROR +--let $slave_io_errno= 1593 +--let $show_slave_io_error= 1 +--source include/wait_for_slave_io_error.inc + +--source include/stop_slave_sql.inc +RESET SLAVE; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt b/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt new file mode 100644 index 00000000..30288952 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_server_id2-slave.opt @@ -0,0 +1 @@ +--disable-log-slave-updates --replicate-same-server-id diff --git a/mysql-test/suite/rpl/t/rpl_server_id2.test b/mysql-test/suite/rpl/t/rpl_server_id2.test new file mode 100644 index 00000000..6a8493ca --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_server_id2.test @@ -0,0 +1,67 @@ +# This test checks that a slave DOES execute queries originating +# from itself, if running with --replicate-same-server-id. + +source include/master-slave.inc; +connection slave; +create table t1 (n int); +reset master; +# replicate ourselves +stop slave; +--source include/wait_for_slave_to_stop.inc +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval change master to master_port=$SLAVE_MYPORT; +start slave; +--source include/wait_for_slave_to_start.inc +insert into t1 values (1); +save_master_pos; +sync_with_master; +select * from t1; # check that indeed 2 were inserted +# We stop the slave before cleaning up otherwise we'll get +# 'drop table t1' executed twice, so an error in the slave.err +# (not critical). +stop slave; +--source include/wait_for_slave_to_stop.inc +drop table t1; + + +# +# Bug#38934 slave slave until does not work with --replicate-same-server-id +# +# Verifying that slave performs all events until the master_log_pos +# in presense of --replicate-same-server-id the slave is started with. + +connection master; +reset master; + +# setting the until position to correspond to the last position of +# create table which will make the event executed and the slave sql +# thread stopped right after that. + +create table t1(n int); +let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +dec $until_pos; +create table t2(n int); + +connection slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_port=$MASTER_MYPORT; +--replace_result $until_pos UNTIL_POS +eval start slave until master_log_file='master-bin.000001', master_log_pos=$until_pos; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc + +--echo *** checking until position execution: must be only t1 in the list *** +show tables; + +# cleanup + +connection slave; +start slave sql_thread; + +connection master; +drop table t1; +drop table t2; +sync_slave_with_master; + +# End of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt b/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt new file mode 100644 index 00000000..30288952 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_server_id_ignore-slave.opt @@ -0,0 +1 @@ +--disable-log-slave-updates --replicate-same-server-id diff --git a/mysql-test/suite/rpl/t/rpl_server_id_ignore.test b/mysql-test/suite/rpl/t/rpl_server_id_ignore.test new file mode 100644 index 00000000..537978f1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_server_id_ignore.test @@ -0,0 +1,116 @@ +# This test checks that the slave rejects events originating +# by a server from the list of ignored originators (bug#27808 etc) +# +# phases of tests: +# +# 0. master_id new line in show slave status +# 1. syntax related: +# a. error reporting if options clash; +# b. overriding the old IGNORE_SERVER_IDS setup by the following +# CHANGE MASTER ... IGNORE_SERVER_IDS= (list); +# c. the old setup preserving by CHANGE MASTER w/o IGNORE_SERVER_IDS +# d. resetting the ignored server ids with the empty list arg to +# IGNORE_SERVER_IDS=() +# e. RESET SLAVE preserves the list +# 2. run time related: +# a. observing no processing events from a master listed in IGNORE_SERVER_IDS +# b. nullifying the list and resuming of taking binlog from the very beginning with +# executing events this time + +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +connection slave; + +# a new line for master_id +let $master_id= query_get_value(SHOW SLAVE STATUS, Master_Server_Id, 1); +echo master_id: $master_id; + +stop slave; +--echo *** --replicate-same-server-id and change master option can clash *** +--error ER_SLAVE_IGNORE_SERVER_IDS +change master to IGNORE_SERVER_IDS= (2, 1); +--echo *** must be empty due to the error *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); +echo ignore server id list: $ignore_list; + +change master to IGNORE_SERVER_IDS= (10, 100); +--echo *** must be 10, 100 *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); +echo ignore server id list: $ignore_list; +reset slave; +--echo *** must be empty due to reset slave *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); +echo ignore server id list: $ignore_list; +change master to IGNORE_SERVER_IDS= (10, 100); +--echo *** CHANGE MASTER with IGNORE_SERVER_IDS option overrides (does not increment) the previous setup *** +change master to IGNORE_SERVER_IDS= (5, 1, 4, 3, 1); +--echo *** must be 1, 3, 4, 5 due to overriding policy *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); +echo ignore server id list: $ignore_list; +--echo *** ignore master (server 1) queries for a while *** +start slave; + +connection master; + +#connection slave; +sync_slave_with_master; +let $slave_relay_pos0= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1); + +connection master; +create table t1 (n int); +let $master_binlog_end= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; +let $slave_param= Exec_Master_Log_Pos; +let $slave_param_value= $master_binlog_end; +source include/wait_for_slave_param.inc; +--echo *** must be empty as the event is to be filtered out *** +show tables; +--echo *** allowing events from master *** +let $slave_relay_pos1= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1); +# +# checking stability of relay log pos +# +if (`select $slave_relay_pos1 - $slave_relay_pos0`) +{ + --echo Error: relay log position changed: $slave_relay_pos0, $slave_relay_pos1 + query_vertical show slave status; +} + +stop slave; +source include/wait_for_slave_to_stop.inc; +reset slave; +change master to IGNORE_SERVER_IDS= (10, 100); +--echo *** the list must remain (10, 100) after reset slave *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); + +change master to IGNORE_SERVER_IDS= (); +--echo *** must be empty due to IGNORE_SERVER_IDS empty list *** +let $ignore_list= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Server_Ids, 1); +echo ignore server id list: $ignore_list; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1', master_port=$MASTER_MYPORT, master_user='root'; +start slave; + +connection master; + +#connection slave; +sync_slave_with_master; +--echo *** must have caught create table *** +show tables; + +# cleanup +connection master; +drop table t1; +#connection slave +sync_slave_with_master; + +--echo end of the tests + + + + + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_session_var.test b/mysql-test/suite/rpl/t/rpl_session_var.test new file mode 100644 index 00000000..cf3faa65 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_session_var.test @@ -0,0 +1,61 @@ +# Replication of session variables. +# FOREIGN_KEY_CHECKS is tested in rpl_insert_id.test + +source include/master-slave.inc; + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +drop table if exists t1; +create table t1(a varchar(100),b int); +set @@session.sql_mode=pipes_as_concat; +insert into t1 values('My'||'SQL', 1); +set @@session.sql_mode=default; +insert into t1 values('1'||'2', 2); +select * from t1 where b<3 order by a; +sync_slave_with_master; +select * from t1 where b<3 order by a; +connection master; +# if the slave does the next sync_with_master fine, then it means it accepts the +# two lines of ANSI syntax below, which is what we want to check. +set @@session.sql_mode=ignore_space; +insert into t1 values(password ('MySQL'), 3); +set @@session.sql_mode=ansi_quotes; +create table "t2" ("a" int); +drop table t1, t2; +set @@session.sql_mode=default; +create table t1(a int auto_increment primary key); +create table t2(b int, a int); +set @@session.sql_auto_is_null=1; +insert into t1 values(null); +insert into t2 select 1,a from t1 where a is null; +set @@session.sql_auto_is_null=0; +insert into t1 values(null); +insert into t2 select 2,a from t1 where a is null; +select * from t2 order by b; +sync_slave_with_master; +select * from t2 order by b; +connection master; +drop table t1,t2; +sync_slave_with_master; + +# +# Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. +# + +connection master; +CREATE TABLE t1 ( + `id` int(11) NOT NULL auto_increment, + `data` varchar(100), + PRIMARY KEY (`id`) + ) ENGINE=MyISAM; +--disable_warnings +INSERT INTO t1(data) VALUES(SESSION_USER()); +--enable_warnings +sync_slave_with_master; +SELECT length(data) < 100 FROM t1; +connection master; +drop table t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_set_charset.test b/mysql-test/suite/rpl/t/rpl_set_charset.test new file mode 100644 index 00000000..72b89a13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_charset.test @@ -0,0 +1,30 @@ +source include/master-slave.inc; +--disable_warnings +drop database if exists mysqltest1; +# 4.1 bases its conversion on the db's charset, +# while 4.0 uses the part of "SET CHARACTER SET" after "_". +# So for 4.1 we add a clause to CREATE DATABASE. +create database mysqltest1 /*!40100 character set latin2 */; +use mysqltest1; +drop table if exists t1; +--enable_warnings +create table t1 (a varchar(255) character set latin2, b varchar(4)); +SET CHARACTER SET cp1250_latin2; +INSERT INTO t1 VALUES ('ŠŒŽ','80'); +INSERT INTO t1 VALUES ('šœžŸ','90'); +INSERT INTO t1 VALUES ('£¥ª¯','A0'); +INSERT INTO t1 VALUES ('³¹º¼¾¿','B0'); +INSERT INTO t1 VALUES ('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ','C0'); +INSERT INTO t1 VALUES ('ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß','D0'); +INSERT INTO t1 VALUES ('àáâãäåæçèéêëìíîï','E0'); +INSERT INTO t1 VALUES ('ðñòóôõö÷øùúûüýþÿ','F0'); +select hex(a),b from t1 order by b; +sync_slave_with_master; +use mysqltest1; +select hex(a),b from t1 order by b; +connection master; +drop database mysqltest1; +sync_slave_with_master; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_set_null_innodb.test b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test new file mode 100644 index 00000000..84f7adb3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_null_innodb.test @@ -0,0 +1,7 @@ +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +-- let $engine= InnoDB +-- source include/rpl_set_null.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_set_null_myisam.test b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test new file mode 100644 index 00000000..db1bd4b7 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_null_myisam.test @@ -0,0 +1,6 @@ +-- source include/have_binlog_format_mixed_or_row.inc +-- source include/master-slave.inc + +-- let $engine= MyISAM +-- source include/rpl_set_null.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_set_statement.test b/mysql-test/suite/rpl/t/rpl_set_statement.test new file mode 100644 index 00000000..5bc54e44 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_statement.test @@ -0,0 +1,61 @@ +--source include/master-slave.inc +--source include/have_binlog_format_statement.inc +set sql_mode=""; +connection slave; +set sql_mode=""; +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +call mtr.add_suppression("Unsafe statement written to the binary log*"); +CREATE TABLE t1 (a bigint unsigned not null); +CREATE TABLE t2 (a char(255) not null); + +--echo +--echo There are the following types of variables: +--echo 1) variables that are NOT replicated correctly when using STATEMENT mode; +--echo + +--let $rpl_ssvt_var_name=max_join_size +--let $rpl_ssvt_var_value=2 +--let $rpl_ssvt_table=t1 +--source suite/rpl/include/rpl_set_statement.inc + +--echo +--echo 2) variables thar ARE replicated correctly +--echo They must be replicated correctly with "SET STATEMENT" too. +--echo +--let $rpl_ssvt_var_name=auto_increment_increment +--let $rpl_ssvt_var_value=10 +--let $rpl_ssvt_table=t1 +--source suite/rpl/include/rpl_set_statement.inc + +--echo +--echo 3) sql_mode which is replicated correctly exept NO_DIR_IN_CREATE value; +--echo +--let $rpl_ssvt_var_name=sql_mode +--let $rpl_ssvt_var_value='ERROR_FOR_DIVISION_BY_ZERO' +--let $rpl_ssvt_table=t2 +--source suite/rpl/include/rpl_set_statement.inc +--let $rpl_ssvt_var_name=sql_mode +--let $rpl_ssvt_var_value='NO_DIR_IN_CREATE' +--let $rpl_ssvt_table=t2 +--source suite/rpl/include/rpl_set_statement.inc + +--echo +--echo 4) variables that are not replicated at all: +--echo default_storage_engine, storage_engine, max_heap_table_size +--echo +--let $rpl_ssvt_var_name=max_heap_table_size +--let $rpl_ssvt_var_value=16384 +--let $rpl_ssvt_table=t1 +--source suite/rpl/include/rpl_set_statement.inc + +connection master; +DROP TABLE t1; +DROP TABLE t2; +sync_slave_with_master; +source include/stop_slave.inc; diff --git a/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test new file mode 100644 index 00000000..106cb454 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_set_statement_default_master.test @@ -0,0 +1,34 @@ +--source include/master-slave.inc + +--connection slave + +--source include/stop_slave.inc +RESET SLAVE ALL; + +--echo # Does not work for CHANGE MASTER: +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval SET STATEMENT default_master_connection = 'm1' FOR + CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root'; + + +--echo # +--echo # The first field, Connection_name, should say 'm1'... +--echo # +--let $status_items= Connection_name +--source include/show_all_slaves_status.inc +#query_vertical SHOW ALL SLAVES STATUS; + + +RESET SLAVE ALL; + +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval CHANGE MASTER 'm1' TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root'; +SET STATEMENT default_master_connection = 'm1' FOR START SLAVE; + +set default_master_connection = 'm1'; +stop slave; +--source include/wait_for_slave_to_stop.inc +reset slave all; +set default_master_connection = ''; +--disconnect slave +--connection default diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf new file mode 100644 index 00000000..288f0132 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.cnf @@ -0,0 +1,20 @@ +!include ../my.cnf + +[mysqld.1] +server_id=1 + +[mysqld.2] +server_id=2 +report-host= +report-user= + +[mysqld.3] +server_id=3 +report-host=slave2 +slave-net-timeout=5 + +[ENV] +SLAVE_MYPORT2= @mysqld.3.port +SLAVE_MYSOCK2= @mysqld.3.socket + + diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test new file mode 100644 index 00000000..84c5c215 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test @@ -0,0 +1,52 @@ +############################################################################### +# Bug#13963 SHOW SLAVE HOSTS is unreliable +# +# Slaves only appear in the output of SHOW SLAVE HOSTS when report-host option +# is set. If an expected slave does not appear in the list, nobody knows +# whether the slave does not connect or has started without the "report-host" +# option. +# +# Remove the "Rpl_recovery_rank" column from SHOW SLAVE HOSTS, It is not +# implemented. +####################################################################### +source include/master-slave.inc; +connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT2,); + +connection slave2; +RESET SLAVE; +--replace_result $MASTER_MYPORT MASTER_PORT +--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root' +START SLAVE IO_THREAD; +source include/wait_for_slave_io_to_start.inc; + +connection master; +let $show_statement= SHOW SLAVE HOSTS; +let $field= Server_id; +# 3 is server_id of slave2. +let $condition= ='3'; +source include/wait_show_condition.inc; +# Make sure that the other slave also had time to register. Otherwise we get +# occasional spurious failures where server_id=2 is missing from SHOW SLAVE +# HOSTS, when that slave is much slower to register due to thread scheduling. +let $condition= ='2'; +source include/wait_show_condition.inc; +--replace_column 3 'SLAVE_PORT' +--replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT +SHOW SLAVE HOSTS; + +connection slave2; +--source include/stop_slave_io.inc + +connection master; +let $show_statement= SHOW SLAVE HOSTS; +let $field= Server_id; +# 3 is server_id of slave2. +let $condition= <> '3'; +# All rows of 'SHOW SLAVE HOSTS' are not equal to 3. It mean that master has +# knew the leave of slave2 and has unregistered it. +let $wait_for_all= 1; +source include/wait_show_condition.inc; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW SLAVE HOSTS; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_running.test b/mysql-test/suite/rpl/t/rpl_show_slave_running.test new file mode 100644 index 00000000..cb4a8819 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_show_slave_running.test @@ -0,0 +1,83 @@ +# +# Bug #30703 SHOW STATUS LIKE 'Slave_running' is not compatible with `SHOW SLAVE STATUS' +# The test verifies that SHOW STATUS LIKE 'Slave_running' displays ON +# if and only if `SHOW SLAVE STATUS' displays YES for Slave_IO_Running and Slave_SQL_Running +# +source include/have_debug.inc; +source include/have_debug_sync.inc; +source include/master-slave.inc; + +connection slave; + +SET DEBUG_SYNC= 'RESET'; +source include/stop_slave.inc; +SET @saved_dbug = @@GLOBAL.debug_dbug; +set global debug_dbug= 'd,dbug.before_get_running_status_yes'; # to block due-started IO + +# Test 1. Slave is stopped + +--echo Slave_running, Slave_IO_Running, Slave_SQL_Running, must be OFF, NO, NO in three following queries + +SHOW STATUS LIKE 'Slave_running'; +let $status= query_get_value("show slave status", Slave_IO_Running, 1); +echo Slave_IO_Running= $status; +let $status= query_get_value("show slave status", Slave_SQL_Running, 1); +echo Slave_SQL_Running= $status; + +# Test 2. The slave IO thread is started but not yet got connected to master +# and SQL thread is not started + +start slave io_thread; + +# +# Notice a difference between versions in showing p.2: +# 5.1 has two OFF,ON IO-thread state running state whereas later versions +# have three: OFF,Connecting,ON. +# Hence, 5.1 must display OFF NO NO where as 5.1+ OFF Connecting NO +# +--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF Connecting NO in three following queries + +SHOW STATUS LIKE 'Slave_running'; +let $status= query_get_value("show slave status", Slave_IO_Running, 1); +echo Slave_IO_Running= $status; +let $status= query_get_value("show slave status", Slave_SQL_Running, 1); +echo Slave_SQL_Running= $status; + +# Test 3. The slave IO thread is started and got connected to master +# and SQL thread is still not started + +SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running'; # unblock IO thread now +let $slave_param= Slave_IO_Running; +let $slave_param_value= YES; +source include/wait_for_slave_param.inc; + +--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF YES NO in three following queries + +SHOW STATUS LIKE 'Slave_running'; +let $status= query_get_value("show slave status", Slave_IO_Running, 1); +echo Slave_IO_Running= $status; +let $status= query_get_value("show slave status", Slave_SQL_Running, 1); +echo Slave_SQL_Running= $status; + +# Test 4. The slave IO thread is started and got connected to master +# and SQL thread is started + +start slave sql_thread; +source include/wait_for_slave_sql_to_start.inc; + +--echo Slave_running, Slave_IO_Running, Slave_SQL_Running must be ON, YES, YES in three following queries + +SHOW STATUS LIKE 'Slave_running'; +let $status= query_get_value("show slave status", Slave_IO_Running, 1); +echo Slave_IO_Running= $status; +let $status= query_get_value("show slave status", Slave_SQL_Running, 1); +echo Slave_SQL_Running= $status; + +# cleanup + +connection slave; + +SET @@GLOBAL.debug_dbug = @saved_dbug; +SET DEBUG_SYNC= 'RESET'; +--echo End of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf new file mode 100644 index 00000000..8ff9df03 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.cnf @@ -0,0 +1,16 @@ +!include ../my.cnf + +[mysqld.1] +log_warnings=3 +[mysqld.2] + +[mysqld.3] + +[mysqld.4] + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test new file mode 100644 index 00000000..2c63df30 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_semisync_slaves.test @@ -0,0 +1,46 @@ +# +# MDEV-18450 "Slow" shutdown to wait for slaves that are to be fed +# with everything in the master binlog before shutdown completes. +# +# This is a semisync version of basic tests. +--source include/have_innodb.inc +--source include/have_debug.inc +--let $rpl_topology=1->2, 1->3, 1->4 +--source include/rpl_init.inc + +--connection server_1 +call mtr.add_suppression("Timeout waiting for reply of binlog"); +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled` +SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; + +--let slaves= 3 +--let i= 2 +while (`SELECT $i <= $slaves`) +{ + --connection server_$i + --let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` + set global rpl_semi_sync_slave_enabled = 1; + + source include/stop_slave.inc; + source include/start_slave.inc; + set global rpl_semi_sync_slave_enabled = 1; + + --inc $i +} + +--source include/rpl_shutdown_wait_slaves.inc +--let i= 2 +while (`SELECT $i <= $slaves`) +{ + --connection server_$i + source include/stop_slave.inc; + source include/start_slave.inc; + --eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_slave; + + --inc $i +} + +--connection server_1 +--eval SET @@GLOBAL.rpl_semi_sync_master_enabled = $sav_enabled_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf new file mode 100644 index 00000000..8ff9df03 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.cnf @@ -0,0 +1,16 @@ +!include ../my.cnf + +[mysqld.1] +log_warnings=3 +[mysqld.2] + +[mysqld.3] + +[mysqld.4] + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket + +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test new file mode 100644 index 00000000..97363206 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_shutdown_wait_slaves.test @@ -0,0 +1,11 @@ +# +# MDEV-18450 "Slow" shutdown to wait for slaves that are to be fed +# with everything in the master binlog before shutdown completes. +# +--source include/have_innodb.inc +--source include/have_debug.inc +--let $rpl_topology=1->2, 1->3, 1->4 +--source include/rpl_init.inc + +--source include/rpl_shutdown_wait_slaves.inc +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt b/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt new file mode 100644 index 00000000..208da1fa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_error-slave.opt @@ -0,0 +1 @@ +--slave-skip-errors=1062 diff --git a/mysql-test/suite/rpl/t/rpl_skip_error.test b/mysql-test/suite/rpl/t/rpl_skip_error.test new file mode 100644 index 00000000..d3ef834e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_error.test @@ -0,0 +1,175 @@ +# ==== Purpose ==== +# +# Verify that --slave-skip-errors works correctly. The error messages +# specified by --slave-skip-errors on slave should be ignored. If +# such errors occur, they should not be reported and not cause the +# slave to stop. +# +# ==== Method ==== +# +# We run the slave with --slave-skip-errors=1062 (the code for +# duplicate key). Then we have two set of tests. In the first +# set, we insert value 1 in a table on the slave, and then, on +# master, we insert value 1 in the table. In the second set, we +# insert several values on the master, disable the binlog and +# delete one of the values and re-enable the binlog. Right after, +# we perform an update on the set of values in order to generate +# a duplicate key on the slave. The errors should be ignored on +# the slave. +# +# ==== Related bugs ==== +# +# BUG#28839: Errors in strict mode silently stop SQL thread if --slave-skip-errors exists +# bug in this test: BUG#30594: rpl.rpl_skip_error is nondeterministic: +# BUG#39393: slave-skip-errors does not work when using ROW based replication + +source include/have_innodb.inc; +source include/master-slave.inc; + +--connection slave +let $initial_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1); + +connection master; +--echo ==== Test Without sql_mode=strict_trans_tables ==== + +create table t1 (n int not null primary key); + +sync_slave_with_master; +insert into t1 values (1); + +connection master; +# Here we expect (ignored) error, since 1 is already in slave table +insert into t1 values (1); +# These should work fine +insert into t1 values (2),(3); + +sync_slave_with_master; +select * from t1 order by n; + +--echo ==== Test With sql_mode=strict_trans_tables ==== +insert into t1 values (7),(8); +connection master; +set sql_mode=strict_trans_tables; +insert into t1 values (7), (8), (9); +sync_slave_with_master; +select * from t1 order by n; +source include/check_slave_is_running.inc; + +--echo ==== Clean Up ==== +connection master; +drop table t1; +sync_slave_with_master; +# End of 4.1 tests + +# +# #28839 Errors in strict mode silently stop SQL thread if --slave-skip-errors exists +# +connection master; +create table t1(a int primary key); +insert into t1 values (1),(2); +SET SQL_LOG_BIN=0; +delete from t1; +SET SQL_LOG_BIN=1; +set sql_mode=strict_trans_tables; +insert into t1 values (1), (2), (3); + +sync_slave_with_master; +select * from t1; +source include/check_slave_is_running.inc; + + +--echo ==== Clean Up ==== + +connection master; +drop table t1; +sync_slave_with_master; +# End of 5.0 tests + +# +# BUG#39393: slave-skip-errors does not work when using ROW based replication +# +--echo ==== Using Innodb ==== + +connection master; + +SET SQL_LOG_BIN=0; +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; +SET SQL_LOG_BIN=1; + +connection slave; + +call mtr.add_suppression("Slave SQL.*Could not execute .*te_rows event on table test.t.; Duplicate entry.* error.* 1062"); + +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; + +connection master; + +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t1 VALUES(2, 1); +INSERT INTO t1 VALUES(3, 1); +INSERT INTO t1 VALUES(4, 1); + +SET SQL_LOG_BIN=0; +DELETE FROM t1 WHERE id = 4; +SET SQL_LOG_BIN=1; +UPDATE t1 SET id= id + 3, data = 2; + +sync_slave_with_master; + +let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +echo $error; + +--echo **** We cannot execute a select as there are differences in the +--echo **** behavior between STMT and RBR. + +--echo ==== Using MyIsam ==== + +connection master; + +SET SQL_LOG_BIN=0; +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; +SET SQL_LOG_BIN=1; + +connection slave; + +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; +let $current_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1); +--let $delta_skipped_error= `select $current_skipped_error - $initial_skipped_error from dual` +--echo # Slave_skipped_errros = $delta_skipped_error +connection master; + +INSERT INTO t2 VALUES(1, 1); +INSERT INTO t2 VALUES(2, 1); +INSERT INTO t2 VALUES(3, 1); +INSERT INTO t2 VALUES(5, 1); + +SET SQL_LOG_BIN=0; +DELETE FROM t2 WHERE id = 5; +SET SQL_LOG_BIN=1; +UPDATE t2 SET id= id + 3, data = 2; + +sync_slave_with_master; + +let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +echo $error; + +let $current_skipped_error= query_get_value(show global status like "Slave_skipped_errors", Value, 1); +--let $delta_skipped_error= `select $current_skipped_error - $initial_skipped_error from dual` +--echo # Slave_skipped_errros = $delta_skipped_error + +--echo **** We cannot execute a select as there are differences in the +--echo **** behavior between STMT and RBR. + +--echo ==== Clean Up ==== + +connection master; + +DROP TABLE t1; +DROP TABLE t2; + +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt b/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt new file mode 100644 index 00000000..912801de --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_incident-master.opt @@ -0,0 +1 @@ +--loose-debug=+d,incident_database_resync_on_replace diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt b/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt new file mode 100644 index 00000000..a223f2e0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_incident-slave.opt @@ -0,0 +1 @@ +--slave-skip-errors=1590 diff --git a/mysql-test/suite/rpl/t/rpl_skip_incident.test b/mysql-test/suite/rpl/t/rpl_skip_incident.test new file mode 100644 index 00000000..704854ae --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_incident.test @@ -0,0 +1,42 @@ +--source include/have_debug.inc +--source include/master-slave.inc + +connection master; +SET GLOBAL BINLOG_CHECKSUM=NONE; +connection slave; +SET GLOBAL BINLOG_CHECKSUM=NONE; +connection master; + +--echo **** On Master **** +CREATE TABLE t1 (a INT); + +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1; + +# This will generate an incident log event and store it in the binary +# log before the replace statement. +REPLACE INTO t1 VALUES (4); + +--sync_slave_with_master + +# Now, we should have inserted the row into the table and the slave +# should be running. We should also have rotated to a new binary log. + +SELECT * FROM t1; +source include/check_slave_is_running.inc; + +connection master; + +--echo Should have two binary logs here +--source include/show_binary_logs.inc +DROP TABLE t1; +--sync_slave_with_master + + +connection master; +SET GLOBAL BINLOG_CHECKSUM=default; +connection slave; +SET GLOBAL BINLOG_CHECKSUM=default; +connection master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_skip_replication.test b/mysql-test/suite/rpl/t/rpl_skip_replication.test new file mode 100644 index 00000000..66fdbb89 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_skip_replication.test @@ -0,0 +1 @@ +--source include/rpl_skip_replication.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test new file mode 100644 index 00000000..324821a3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_alias_replica.test @@ -0,0 +1,102 @@ +# ==== Purpose ==== +# +# Test verifies that SQL statements which use keyword 'REPLICA' a synonym for +# 'SLAVE' work as expected. +# +# ==== Implementation ==== +# +# List of commands being verified are +# On Master: SHOW REPLICA HOSTS +# : Privilege "REPLICA" +# +# On Slave: START REPLICA +# START REPLICA UNTIL +# STOP REPLICA +# SHOW REPLICA STATUS +# RESET REPLICA ALL +# REPLICA_POS +# +# ==== References ==== +# +# MDEV-20601: Make REPLICA a synonym for SLAVE in SQL statements +# + +--source include/have_innodb.inc +--source include/master-slave.inc + +--echo "Command: STOP SLAVE --> STOP REPLICA" +--connection slave +STOP REPLICA; +--source include/wait_for_slave_io_to_stop.inc +--source include/wait_for_slave_sql_to_stop.inc + +--connection master +CREATE USER 'repl_user'; +--echo "Privilege: SLAVE --> REPLICA" +GRANT REPLICATION REPLICA on *.* TO repl_user; +FLUSH PRIVILEGES; + +--connection slave +--echo "SHOW SLAVE STATUS --> SHOW REPLICA STATUS" +--let $master_user= query_get_value(SHOW REPLICA STATUS, Master_User, 1) +CHANGE MASTER TO MASTER_USER= 'repl_user'; +--echo "Command: START SLAVE --> START REPLICA" +START REPLICA; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master + +--connection master +--echo "Command: SHOW SLAVE HOSTS --> SHOW REPLICA HOSTS" +let $show_statement= SHOW REPLICA HOSTS; +let $field= Server_id; +# Slave's server_id 2 +let $condition= ='2'; +source include/wait_show_condition.inc; +DROP USER 'repl_user'; +--sync_slave_with_master + +--echo "Command: SHOW SLAVE IO/SQL THREAD --> SHOW REPLICA IO/SQL THREAD" +STOP REPLICA IO_THREAD; +STOP REPLICA SQL_THREAD; +--source include/wait_for_slave_io_to_stop.inc +--source include/wait_for_slave_sql_to_stop.inc +--echo "Command: RESET SLAVE ALL --> RESET REPLICA ALL" +RESET REPLICA ALL; + +--connection master +RESET MASTER; +CREATE TABLE t(f INT) ENGINE=INNODB; +INSERT INTO t VALUES (10); +let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +DROP TABLE t; + +--connection slave +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1',MASTER_PORT=$MASTER_MYPORT,MASTER_USER='$master_user'; +--echo "Command: START SLAVE UNTIL --> START REPLICA UNTIL" +--replace_result $master_log_file MASTER_LOG_FILE $master_pos MASTER_POS +--eval START REPLICA UNTIL MASTER_LOG_FILE='$master_log_file', MASTER_LOG_POS=$master_pos +--source include/wait_for_slave_sql_to_stop.inc +--source include/stop_slave_io.inc + +SELECT * FROM t; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_pos +--source include/check_slave_param.inc + +--replace_result $MASTER_MYPORT MASTER_PORT +--echo "MASTER_USE_GTID=SLAVE_POS --> MASTER_USE_GTID=REPLICA_POS" +--replace_result $MASTER_MYPORT MASTER_PORT +--eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, MASTER_USE_GTID=REPLICA_POS +--source include/start_slave.inc + +--connection master +CREATE TABLE t2 (f INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t2 VALUES (10); +DROP TABLE t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test new file mode 100644 index 00000000..5b08b2cd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_grp_exec.test @@ -0,0 +1,186 @@ +############################################################# +# Author: Serge Kozlov <skozlov@mysql.com> +# Date: 03/21/2008 +# Purpose: +# WL#3734 Test: slave group execution +# Testing slave group execution: stop in middle of the group +# (of events) should be immpossible on slave. +# Group of events means set of statements between BEGIN/COMMIT +# for transactional engines or a statement for +# non-transactional engines that fires triggers and +# affects to another tables. +# Implementation of slave stop in middle of the group: +# Delete the table on slave before start of the group +# on master where this table is participant of the group. +# So sql thread will failed inside of the group. +# Expected results: +# 1. For non-transactional engines w/o PK slave should trying +# to complete executing of the group. +# 2. For non-transactional engines slave should stop on +# start position of the group. +############################################################# +--source include/have_innodb.inc +--source include/master-slave.inc +--echo + +# Create tables and data +--echo *** Preparing data *** +--connection master +CREATE TABLE t1 (a INT NOT NULL, b VARCHAR(10)) ENGINE=MyISAM; +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; + +DELIMITER |; +CREATE TRIGGER tr1 BEFORE UPDATE ON t1 + FOR EACH ROW BEGIN + UPDATE t2 SET b='YY' WHERE a=NEW.a; + END| +CREATE TRIGGER tr2 AFTER UPDATE ON t1 + FOR EACH ROW BEGIN + UPDATE t3 SET b='ZZ' WHERE a=NEW.a; + END| +DELIMITER ;| +--echo + +# Test non-transactional group with MyISAM tables w/o PK. +# Data for t1,t2 should be replicated for SBR even t3 +# doesn't exist on slave +--echo *** Test non-transactional group w/o PK *** + +--connection master +INSERT INTO t3 VALUES(1, 'AA'); +INSERT INTO t2 VALUES(1, 'AA'); +INSERT INTO t1 VALUES(1, 'AA'); +--sync_slave_with_master + +RENAME TABLE t3 TO t3_bak; + +--connection master +UPDATE t1 SET b = 'XX' WHERE a = 1; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--connection slave +# 1146 = ER_NO_SUCH_TABLE +call mtr.add_suppression("Slave SQL.*Table .test.t3. doesn.t exist.* error.* 1146"); +call mtr.add_suppression("At line *"); +--let $slave_sql_errno= 1146 +--source include/wait_for_slave_sql_error.inc +SHOW TABLES LIKE 't%'; +if (`SELECT @@BINLOG_FORMAT = 'ROW'`) { +--replace_regex /AA/AA_for_row_or_XX_for_stmt_mixed/ + SELECT * FROM t1 ORDER BY a; +--replace_regex /AA/AA_for_row_or_YY_for_stmt_mixed/ + SELECT * FROM t2 ORDER BY a; +} +if (!`SELECT @@BINLOG_FORMAT = 'ROW'`) { +--replace_regex /XX/AA_for_row_or_XX_for_stmt_mixed/ + SELECT * FROM t1 ORDER BY a; +--replace_regex /YY/AA_for_row_or_YY_for_stmt_mixed/ + SELECT * FROM t2 ORDER BY a; +} + +--source include/stop_slave_io.inc +RENAME TABLE t3_bak TO t3; +--source include/start_slave.inc + +--connection master +TRUNCATE t1; +TRUNCATE t2; +TRUNCATE t3; +--sync_slave_with_master +--echo + + +# Test non-transactional group with MyISAM tables and PK. +# No data replicated because update based on PK +--echo *** Test non-transactional group w/ PK *** + +--connection master +ALTER TABLE t1 ADD PRIMARY KEY (a); +ALTER TABLE t2 ADD PRIMARY KEY (a); +ALTER TABLE t3 ADD PRIMARY KEY (a); + +--sync_slave_with_master +RENAME TABLE t3 TO t3_bak; + +--connection master +INSERT INTO t3 VALUES(2, 'B'); +INSERT INTO t2 VALUES(2, 'B'); +INSERT INTO t1 VALUES(2, 'B'); +UPDATE t1 SET b = 'X' WHERE a = 2; + +--connection slave +# 1146 = ER_NO_SUCH_TABLE +--let $slave_sql_errno= 1146 +--source include/wait_for_slave_sql_error.inc + +--connection master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--connection slave +SHOW TABLES LIKE 't%'; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--source include/stop_slave_io.inc +RENAME TABLE t3_bak TO t3; +--source include/start_slave.inc + +--connection master +TRUNCATE t1; +TRUNCATE t2; +TRUNCATE t3; +--sync_slave_with_master +--echo + + +# Test transactional group with InnoDB tables with PK +# No data replicated if errors happens inside transaction +--echo *** Test transactional group w/ PK *** + +--connection master +ALTER TABLE t1 ENGINE=InnoDB; +ALTER TABLE t2 ENGINE=InnoDB; +ALTER TABLE t3 ENGINE=InnoDB; + +--sync_slave_with_master +RENAME TABLE t3 TO t3_bak; + +--connection master +BEGIN; +INSERT INTO t1 VALUES (3, 'C'), (4, 'D'); +INSERT INTO t2 VALUES (3, 'C'), (4, 'D'); +INSERT INTO t3 VALUES (3, 'C'), (4, 'D'); +COMMIT; + +--connection slave +# 1146 = ER_NO_SUCH_TABLE +--let $slave_sql_errno= 1146 +--source include/wait_for_slave_sql_error.inc + +--connection master +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--connection slave +SHOW TABLES LIKE 't%'; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +source include/stop_slave_io.inc; +RENAME TABLE t3_bak TO t3; +source include/start_slave.inc; + +# Clean up +--echo *** Clean up *** +--connection master +DROP TABLE t1,t2,t3; +--sync_slave_with_master + +# End of 5.1 test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test b/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test new file mode 100644 index 00000000..5099d7ee --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_invalid_external_user.test @@ -0,0 +1,42 @@ +# ==== Purpose ==== +# +# Test verifies that when applier thread tries to access 'variable_name' of +# INFORMATION_SCHEMA.SESSION_VARIABLES table through triggers it successfully +# retrieves all the session variables. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Create two tables t1 and t2. +# 1 - Create a trigger such that it reads the names of all session variables +# from INFORMATION_SCHEMA.SESSION_VARIABLES table and populates one of the +# tables. +# 2 - Do a DML on master and wait for it to be replicated and ensure that +# slave is in sync with master and it is up and running. +# +# ==== References ==== +# +# MDEV-14784: Slave crashes in show_status_array upon running a trigger with +# select from I_S + +--source include/master-slave.inc +--source include/have_binlog_format_mixed.inc +--enable_connect_log +CREATE USER test_user@localhost; +SET PASSWORD FOR test_user@localhost = password('PWD'); +GRANT ALL ON *.* TO test_user@localhost WITH GRANT OPTION; +connect(conn_test,localhost,test_user,PWD,test,$MASTER_MYPORT,$MASTER_MYSOCK); + +--connection conn_test +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 VARCHAR(64)); +CREATE TRIGGER tr_before BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 SELECT variable_name FROM INFORMATION_SCHEMA.SESSION_VARIABLES; +CREATE DEFINER='root'@'localhost' TRIGGER tr_after AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 SELECT variable_name FROM INFORMATION_SCHEMA.SESSION_VARIABLES; + +INSERT INTO t1 VALUES (1); +--disable_connect_log +# Cleanup +--connection master +DROP USER 'test_user'@'localhost'; +DROP TABLE t1, t2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_in.test b/mysql-test/suite/rpl/t/rpl_slave_load_in.test new file mode 100644 index 00000000..80a27479 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_in.test @@ -0,0 +1,49 @@ +########################################################################## +# This test verifies if a slave is able to process a "LOAD DATA INFILE" +# event while the "--secure-file-priv" option is set. +# +# The test is divided in two steps: +# 1 - Creates tables and populates them through "LOAD DATA INFILE". +# 2 - Compares the master and slave. +########################################################################## +--source include/have_innodb.inc +--source include/master-slave.inc + +########################################################################## +# Loading data +########################################################################## +connection master; + +create table t1(a int not null auto_increment, b int, primary key(a)); +create table t2(a int not null auto_increment, b int, primary key(a)) engine=innodb; + +load data infile '../../std_data/rpl_loaddata.dat' into table t1; + +start transaction; + insert into t2(b) values (1); + insert into t2(b) values (2); + load data infile '../../std_data/rpl_loaddata.dat' into table t2; + load data infile '../../std_data/rpl_loaddata.dat' into table t2; +commit; + +########################################################################## +# Checking Consistency +########################################################################## +sync_slave_with_master; + +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; + +let $diff_tables= master:t2, slave:t2; +source include/diff_tables.inc; + +########################################################################## +# Clean up +########################################################################## +connection master; + +drop table t1; +drop table t2; + +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test new file mode 100644 index 00000000..10051408 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test @@ -0,0 +1,80 @@ +# ==== Purpose ==== +# +# This test verifies if the slave fails gracefully when the temporary +# file used to load data is removed while it is about to be used. +# Similar errors are caught if the temporary directory is removed. +# +# ==== Implementation ==== +# +# Steps: +# 0 - Set debug variable remove_slave_load_file_before_write. This +# causes the slave to remove the file. +# 1 - Creates a table and populates it through "LOAD DATA INFILE". +# 2 - Catches error. +# +# ==== References ==== +# +# BUG#42861: Assigning invalid directories to --slave-load-tmpdir crashes the slave +# BUG#11872422: rpl_slave_load_remove_tmpfile fails sporadically in pb2 + +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/not_embedded.inc +--source include/not_var_link.inc +--source include/master-slave.inc + +########################################################################## +# Loading data +########################################################################## + +connection slave; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@global.debug_dbug= '+d,remove_slave_load_file_before_write'; + +connection master; + +create table t1(a int not null auto_increment, b int, primary key(a)) engine=innodb; + +start transaction; + insert into t1(b) values (1); + insert into t1(b) values (2); + load data infile '../../std_data/rpl_loaddata.dat' into table t1; +commit; + +########################################################################## +# Catch Error +########################################################################## +connection slave; + +# windows and linux different error numbers here: +# Windows: +# - Last_Errno 29 (File not found) +# Unix like OS: +# - Last_Errno 13 (Can't stat file) +--let $slave_sql_errno= 29, 13 +--source include/wait_for_slave_sql_error.inc + +########################################################################## +# Clean up +########################################################################## +connection master; + +drop table t1; + +--source include/sync_slave_io_with_master.inc +--source include/stop_slave_io.inc +RESET SLAVE; + +drop table t1; + +call mtr.add_suppression("Slave: Can't get stat of .*"); +call mtr.add_suppression("Slave SQL: Error .Can.t get stat of.* error.* 13"); +call mtr.add_suppression("Slave: File.* not found.*"); +call mtr.add_suppression("Slave SQL: Error .File.* not found.* error.* 29"); +--let $rpl_only_running_threads= 1 + +SET @@GLOBAL.debug_dbug = @saved_dbug; + +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt new file mode 100644 index 00000000..c4f91e97 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist-slave.opt @@ -0,0 +1 @@ +--slave-load-tmpdir=../../../error diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test new file mode 100644 index 00000000..16dcd8ec --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test @@ -0,0 +1,22 @@ +########################################################################## +# This test verifies if the start slave fails gracefuly when an +# invalid directory is used to set --slave-load-tmpdir. +########################################################################## +--source include/have_log_bin.inc +--source include/not_embedded.inc + +--let $rpl_skip_start_slave= 1 +--source include/master-slave.inc + +--connection slave +START SLAVE; +call mtr.add_suppression("Slave SQL.*Unable to use slave.s temporary directory"); +# 12 = EE_CANT_MKDIR +--let $slave_sql_errno= 12 +source include/wait_for_slave_sql_error.inc; + +--source include/stop_slave_io.inc +RESET SLAVE; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf new file mode 100644 index 00000000..1e7cdee5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.cnf @@ -0,0 +1,19 @@ +!include suite/rpl/rpl_1slave_base.cnf +!include include/default_client.cnf + +[mysqld.1] +log-slave-updates +gtid-domain-id=1 + +[mysqld.2] +log-slave-updates +gtid-domain-id=2 + +[mysqld.3] +log-slave-updates +gtid-domain-id=3 +slave_parallel_threads=2 + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test new file mode 100644 index 00000000..6f73de98 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_shutdown_mdev20821.test @@ -0,0 +1,171 @@ +# MDEV-20821 parallel slave server shutdown hang +# +# Test the bug condition of a parallel slave server shutdown +# hang when the parallel workers were idle. +# The bug reported scenario is extented to cover the multi-sources case as well as +# checking is done for both the idle and busy workers cases. +# +# MDEV-25336 Parallel replication causes failed assert while restarting +# Since this test case involves slave restart this will help in testing +# Mdev-25336 too. + +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +--let $rpl_topology= 1->3 +--source include/rpl_init.inc + +# +# A. idle workers. +# +--connection server_3 +set default_master_connection = ''; +--source include/start_slave.inc + +set default_master_connection = 'm2'; +--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2 +eval change master to master_host='127.0.0.1', master_port=$SERVER_MYPORT_2, master_user='root', master_use_gtid=slave_pos; +--source include/start_slave.inc + +select @@global.slave_parallel_workers as two; + +# At this point worker threads have no assignement. +# Shutdown must not hang. +# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0' +--connection server_3 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +wait +EOF +--send SHUTDOWN +--reap +--source include/wait_until_disconnected.inc + +--connection server_3 +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +restart +EOF + +# No hang is *proved* to occur when this point is reached. +--connection server_3 +--enable_reconnect +--source include/wait_until_connected_again.inc + +# +# B. resting workers after some busy time +# +--connection server_1 +create table t1 (i int primary key) engine=Innodb; + +--connection server_2 +create table t2 (i int primary key) engine=Innodb; + +--connection server_3 +set default_master_connection = ''; +--source include/start_slave.inc + +set default_master_connection = 'm2'; +--source include/start_slave.inc + +--connection server_2 +insert into t2 values (1); +--save_master_pos + +--connection server_3 +--sync_with_master 0,'m2' + +--connection server_1 +insert into t1 values (1); +--save_master_pos + +--connection server_3 +--sync_with_master 0,'' + +# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0' +# At this point worker threads have no assignement. +# Shutdown must not hang. + +--connection server_3 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +wait +EOF +--send SHUTDOWN +--reap +--source include/wait_until_disconnected.inc + +--connection server_3 +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +restart +EOF + +# No hang is *proved* to occur when this point is reached. +--connection server_3 +--enable_reconnect +--source include/wait_until_connected_again.inc + +# +# C. busy workers +# +--connection server_3 +set default_master_connection = ''; +--source include/start_slave.inc + +set default_master_connection = 'm2'; +--source include/start_slave.inc + +--connect (conn_block_server3, 127.0.0.1, root,, test, $SERVER_MYPORT_3,) +begin; + insert into t1 values (2); + insert into t2 values (2); + +--connection server_1 +insert into t1 values (2); +--connection server_2 +insert into t2 values (2); + + +# In 10.2/10.3 there should not be any assert failure `prev != 0 && next != 0' +# At this point there's a good chance the worker threads are busy. +# SHUTDOWN must proceed without any delay as above. +--connection server_3 +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +wait +EOF +--send SHUTDOWN +--reap +--source include/wait_until_disconnected.inc + +--connection server_3 +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.3.expect +restart +EOF + +# No hang is *proved* to occur when this point is reached. +--connection server_3 +--enable_reconnect +--source include/wait_until_connected_again.inc + + +# Cleanup + +--connection server_3 +set default_master_connection = ''; +--source include/start_slave.inc + +set default_master_connection = 'm2'; +--source include/start_slave.inc + +--connection server_1 +drop table t1; + +--connection server_2 +drop table t2; +--save_master_pos + +# (!) The following block is critical to avoid check-mysqld_3.reject by mtr: +--connection server_3 +--sync_with_master 0,'m2' +set default_master_connection = 'm2'; +--source include/stop_slave.inc +RESET SLAVE ALL; +set default_master_connection = ''; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_skip.test b/mysql-test/suite/rpl/t/rpl_slave_skip.test new file mode 100644 index 00000000..2ec80758 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_skip.test @@ -0,0 +1,293 @@ +# Every statement in this test is either executing under ROW or +# STATEMENT format, which requires the slave thread to be able to apply +# both statement and row events. Hence, we only need to execute this +# test for MIXED mode. +source include/have_binlog_format_mixed.inc; + +source include/have_innodb.inc; +source include/master-slave.inc; + +connection slave; +source include/have_innodb.inc; +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc + +connection master; +SET SESSION BINLOG_FORMAT=ROW; + +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE TABLE t2 (c INT, d INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1),(2,4),(3,9); +INSERT INTO t2 VALUES (1,1),(2,8),(3,27); +let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +UPDATE t1,t2 SET b = d, d = b * 2 WHERE a = c; +source include/show_binlog_events.inc; + +# These tables should be changed +SELECT * FROM t1; +SELECT * FROM t2; +save_master_pos; +connection slave; + +# Stop when reaching the the first table map event. +--replace_result $master_log_pos MASTER_LOG_POS +eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_log_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_param= Exec_Master_Log_Pos; +let $slave_param_value= $master_log_pos; +source include/check_slave_param.inc; +source include/check_slave_no_error.inc; + +# Now we skip *one* table map event. If the execution starts right +# after that table map event, *one* of the involved tables will be +# changed. +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +--source include/wait_for_slave_to_start.inc +sync_with_master; + +# These values should be what was inserted, not what was +# updated. Since we are skipping the first table map of the group +# representing the UPDATE statement above, we should skip the entire +# group and not start executing at the first table map. +SELECT * FROM t1; +SELECT * FROM t2; + +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +RESET SLAVE; +connection master; +RESET MASTER; + +SET SESSION BINLOG_FORMAT=STATEMENT; +SET @foo = 12; +let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +INSERT INTO t1 VALUES(@foo, 2*@foo); +save_master_pos; +source include/show_binlog_events.inc; + +connection slave; +--replace_result $master_log_pos MASTER_LOG_POS +eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_log_pos; +source include/wait_for_slave_sql_to_stop.inc; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +--source include/wait_for_slave_to_start.inc +sync_with_master; + +connection master; +DROP TABLE t1, t2; +sync_slave_with_master; + +# +# More tests for BUG#28618 +# +# Case 1. +# ROW binlog format and non-transactional tables. +# Create the group of events via triggers and try to skip +# some items of that group. +# + +connection master; +SET SESSION BINLOG_FORMAT=ROW; +SET AUTOCOMMIT=0; + +CREATE TABLE t1 (a INT, b VARCHAR(20)) ENGINE=myisam; +CREATE TABLE t2 (a INT, b VARCHAR(20)) ENGINE=myisam; +CREATE TABLE t3 (a INT, b VARCHAR(20)) ENGINE=myisam; + +INSERT INTO t1 VALUES (1,'master/slave'); +INSERT INTO t2 VALUES (1,'master/slave'); +INSERT INTO t3 VALUES (1,'master/slave'); + +DELIMITER |; + +CREATE TRIGGER tr1 AFTER UPDATE on t1 FOR EACH ROW +BEGIN + INSERT INTO t2 VALUES (NEW.a,NEW.b); + DELETE FROM t2 WHERE a < NEW.a; +END| + +CREATE TRIGGER tr2 AFTER INSERT on t2 FOR EACH ROW +BEGIN + UPDATE t3 SET a =2, b = 'master only'; +END| + +DELIMITER ;| + +sync_slave_with_master; +source include/stop_slave.inc; + +connection master; +UPDATE t1 SET a = 2, b = 'master only' WHERE a = 1; +DROP TRIGGER tr1; +DROP TRIGGER tr2; +INSERT INTO t1 VALUES (3,'master/slave'); +INSERT INTO t2 VALUES (3,'master/slave'); +INSERT INTO t3 VALUES (3,'master/slave'); +COMMIT; + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +save_master_pos; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +source include/start_slave.inc; +sync_with_master; + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +connection master; +DROP TABLE t1, t2, t3; +sync_slave_with_master; + +--echo **** Case 2: Row binlog format and transactional tables **** + +# Create the transaction and try to skip some +# queries from one. + +connection master; +CREATE TABLE t4 (a INT, b VARCHAR(20)) ENGINE=innodb; +CREATE TABLE t5 (a INT, b VARCHAR(20)) ENGINE=innodb; +CREATE TABLE t6 (a INT, b VARCHAR(20)) ENGINE=innodb; + +sync_slave_with_master; +source include/stop_slave.inc; + +connection master; +BEGIN; +INSERT INTO t4 VALUES (2, 'master only'); +INSERT INTO t5 VALUES (2, 'master only'); +INSERT INTO t6 VALUES (2, 'master only'); +COMMIT; + +BEGIN; +INSERT INTO t4 VALUES (3, 'master/slave'); +INSERT INTO t5 VALUES (3, 'master/slave'); +INSERT INTO t6 VALUES (3, 'master/slave'); +COMMIT; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +save_master_pos; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +source include/start_slave.inc; +sync_with_master; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +# Test skipping two groups + +connection slave; +source include/stop_slave.inc; + +connection master; +BEGIN; +INSERT INTO t4 VALUES (6, 'master only'); +INSERT INTO t5 VALUES (6, 'master only'); +INSERT INTO t6 VALUES (6, 'master only'); +COMMIT; + +BEGIN; +INSERT INTO t4 VALUES (7, 'master only'); +INSERT INTO t5 VALUES (7, 'master only'); +INSERT INTO t6 VALUES (7, 'master only'); +COMMIT; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +save_master_pos; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=12; +source include/start_slave.inc; +sync_with_master; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +# +# And the same, but with autocommit = 0 +# +connection slave; +source include/stop_slave.inc; + +connection master; +SET AUTOCOMMIT=0; + +INSERT INTO t4 VALUES (4, 'master only'); +INSERT INTO t5 VALUES (4, 'master only'); +INSERT INTO t6 VALUES (4, 'master only'); +COMMIT; + +INSERT INTO t4 VALUES (5, 'master/slave'); +INSERT INTO t5 VALUES (5, 'master/slave'); +INSERT INTO t6 VALUES (5, 'master/slave'); +COMMIT; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +save_master_pos; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +source include/start_slave.inc; +sync_with_master; + +SELECT * FROM t4 ORDER BY a; +SELECT * FROM t5 ORDER BY a; +SELECT * FROM t6 ORDER BY a; + +connection master; +DROP TABLE t4, t5, t6; +sync_slave_with_master; + +--echo **** Case 3: Statement logging format and LOAD DATA with non-transactional table **** + +# LOAD DATA creates two events in binary log for statement binlog format. +# Try to skip the first. + +connection master; +CREATE TABLE t10 (a INT, b VARCHAR(20)) ENGINE=myisam; + +sync_slave_with_master; +source include/stop_slave.inc; + +connection master; +SET SESSION BINLOG_FORMAT=STATEMENT; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/std_data/rpl_bug28618.dat' INTO TABLE t10 FIELDS TERMINATED BY '|'; + +SELECT * FROM t10 ORDER BY a; + +save_master_pos; + +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +source include/start_slave.inc; +sync_with_master; + +SELECT * FROM t10 ORDER BY a; + +connection master; +DROP TABLE t10; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slave_status.test b/mysql-test/suite/rpl/t/rpl_slave_status.test new file mode 100644 index 00000000..63e37216 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_status.test @@ -0,0 +1,81 @@ +# ==== Purpose ==== +# +# Verify that a slave without replication privileges has +# Slave_IO_Running = No +# Check that relay_log_status doesn't change by CHANGE MASTER +# ==== Method ==== +# +# We do the following steps: +# - Create a new replication user on master +# - Connect to slave and start replication as this user. +# - Verify that slave can replicate well, by creating a table and +# inserting a row into it. +# - Delete the user from the master. +# - Stop and start the slave (this should fail). +# - Check the Slave_IO_Running column of SHOW SLAVE STATUS. +# +# ==== Related bugs ==== +# +# BUG#10780: slave can't connect to master - IO and SQL threads running + +--source include/master-slave.inc + +--echo ==== Create new replication user ==== +connection master; +GRANT REPLICATION SLAVE ON *.* TO rpl@127.0.0.1 IDENTIFIED BY 'rpl'; + +sync_slave_with_master; +source include/stop_slave.inc; + +# Test that relay_log_purge doesn't change because of CHANGE MASTER +set @save_relay_log_purge=@@global.relay_log_purge; +set @@global.relay_log_purge=0; +CHANGE MASTER TO master_user='rpl', master_password='rpl'; +select @@global.relay_log_purge; +set @@global.relay_log_purge=1; +CHANGE MASTER TO master_user='rpl', master_password='rpl'; +select @@global.relay_log_purge; +set @@global.relay_log_purge=@save_relay_log_purge; + +CHANGE MASTER TO master_user='rpl', master_password='rpl'; +source include/start_slave.inc; + +--echo ==== Do replication as new user ==== +connection master; +CREATE TABLE t1 (n INT); +INSERT INTO t1 VALUES (1); +sync_slave_with_master; +SELECT * FROM t1; + +--echo ==== Delete new replication user ==== +connection master; +DROP USER rpl@127.0.0.1; +FLUSH PRIVILEGES; + +sync_slave_with_master; + +--echo ==== Restart slave without privileges ===== +# (slave.err will contain access denied error for this START SLAVE command) +source include/stop_slave.inc; +START SLAVE; +source include/wait_for_slave_sql_to_start.inc; +source include/wait_for_slave_io_to_stop.inc; + +--echo ==== Verify that Slave IO thread stopped with error ==== +# 1045 = ER_ACCESS_DENIED_ERROR +--let $slave_io_errno= 1045 +--source include/wait_for_slave_io_error.inc + +--echo ==== Cleanup (Note that slave IO thread is not running) ==== + +# cleanup: slave io thread has is stopped so we reset replication +--source include/stop_slave_sql.inc +CHANGE MASTER TO MASTER_USER = 'root', MASTER_PASSWORD = ''; +# clear Slave_IO_Errno +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +connection master; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt b/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt new file mode 100644 index 00000000..43911726 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slow_query_log-slave.opt @@ -0,0 +1 @@ +--log-slow-slave-statements --slow-query-log diff --git a/mysql-test/suite/rpl/t/rpl_slow_query_log.test b/mysql-test/suite/rpl/t/rpl_slow_query_log.test new file mode 100644 index 00000000..558d28b6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slow_query_log.test @@ -0,0 +1,343 @@ +# +# BUG#23300: Slow query log on slave does not log slow replicated statements +# +# Description: +# The slave should log slow queries replicated from master when +# --log-slow-slave-statements is used. +# +# Test is implemented as follows: +# i) stop slave +# ii) On slave, set long_query_time to a small value. +# ii) start slave so that long_query_time variable is picked by sql thread +# iii) On master, do one short time query and one long time query, on slave +# and check that slow query is logged to slow query log but fast query +# is not. +# iv) On slave, check that slow queries go into the slow log and fast don't, +# when issued through a regular client connection +# v) On slave, check that slow queries go into the slow log and fast don't +# when we use SET TIMESTAMP= 1 on a regular client connection. +# vi) check that when setting slow_query_log= OFF in a connection 'extra2' +# prevents logging slow queries in a connection 'extra' +# +# OBS: +# This test only runs for statement binlogging format because on row format +# slow queries do not get slow query logged. +# Note that due to the sleep() command the insert is written to the binary +# log in row format. + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); + +# Prepare slave for different long_query_time we need to stop the slave +# and restart it as long_query_time variable is dynamic and, after +# setting it, it only takes effect on new connections. +# +# Reference: +# http://dev.mysql.com/doc/refman/6.0/en/set-option.html +connection slave; + +source include/stop_slave.inc; + +SET @old_log_output= @@log_output; +SET GLOBAL log_output= 'TABLE'; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL long_query_time= 2; +TRUNCATE mysql.slow_log; + +source include/start_slave.inc; + +connection master; +CREATE TABLE t1 (a int, b int); + +# test: +# check that slave logs the slow query to the slow log, but not the fast one. + +let $slow_query= INSERT INTO t1 values(1, sleep(3)); +let $fast_query= INSERT INTO t1 values(1, 1); + +eval $fast_query; +--disable_warnings +eval $slow_query; +--enable_warnings +sync_slave_with_master; + +let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`; +let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($found_fast_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Fast query FOUND in slow query log. Bailing out!"; +} + +if (!$found_slow_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!"; +} +TRUNCATE mysql.slow_log; + +# regular checks for slow query log (using a new connection - 'extra' - to slave) + +# test: +# when using direct connections to the slave, check that slow query is logged +# but not the fast one. + +connect(extra,127.0.0.1,root,,test,$SLAVE_MYPORT); +connection extra; + +let $fast_query= SELECT 1; +let $slow_query= SELECT 1, sleep(3); + +eval $slow_query; +eval $fast_query; + +let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`; +let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($found_fast_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Fast query FOUND in slow query log. Bailing out!"; +} + +if (!$found_slow_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!"; +} +TRUNCATE mysql.slow_log; + +# test: +# when using direct connections to the slave, check that when setting timestamp to 1 the +# slow query is logged but the fast one is not. + +let $fast_query= SELECT 2; +let $slow_query= SELECT 2, sleep(3); + +SET TIMESTAMP= 1; +eval $slow_query; +eval $fast_query; + +let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`; +let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($found_fast_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Fast query FOUND in slow query log. Bailing out!"; +} + +if (!$found_slow_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Slow query NOT FOUND in slow query log. Bailing out!"; +} +TRUNCATE mysql.slow_log; + +# test: +# check that when setting the slow_query_log= OFF on connection 'extra2' +# prevents connection 'extra' from logging to slow query log. + +let $fast_query= SELECT 3; +let $slow_query= SELECT 3, sleep(3); + +connect(extra2,127.0.0.1,root,,test,$SLAVE_MYPORT); +connection extra2; + +SET @old_slow_query_log= @@slow_query_log; +SET GLOBAL slow_query_log= 'OFF'; + +connection extra; + +eval $slow_query; +eval $fast_query; + +let $found_fast_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$fast_query'`; +let $found_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($found_fast_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Fast query FOUND in slow query log when slow_query_log= OFF. Bailing out!"; +} + +if ($found_slow_query) +{ + SELECT * FROM mysql.slow_log; + die "Assertion failed! Slow query FOUND in slow query log when slow_query_log= OFF. Bailing out!"; +} +TRUNCATE mysql.slow_log; + +# clean up: drop tables, reset the variables back to the previous value, +# disconnect extra connections +connection extra2; + +SET GLOBAL slow_query_log= @old_slow_query_log; + +connection master; +DROP TABLE t1; +sync_slave_with_master; + +source include/stop_slave.inc; + +SET GLOBAL long_query_time= @old_long_query_time; +SET GLOBAL log_output= @old_log_output; + +source include/start_slave.inc; + +disconnect extra; +disconnect extra2; + +# +# BUG#50620: Adding an index to a table prevents slave from logging into slow log +# + +--source include/rpl_reset.inc + +-- connection master +SET @old_log_output= @@log_output; +SET GLOBAL log_output= 'TABLE'; +SET GLOBAL long_query_time= 2; +SET @old_long_query_time= @@long_query_time; +SET SESSION long_query_time= 2; +TRUNCATE mysql.slow_log; +-- connection slave + +-- source include/stop_slave.inc +SET @old_log_output= @@log_output; +SET GLOBAL log_output= 'TABLE'; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL long_query_time= 2; +TRUNCATE mysql.slow_log; +-- source include/start_slave.inc + +let $slow_query= INSERT INTO t1 values(1, sleep(3)); + +-- connection master +CREATE TABLE t1 (a int, b int); + +-- echo ******************************************************************** +-- echo **** INSERT one row that exceeds long_query_time +-- echo **** Outcome: query ends up in both master and slave slow log +-- echo ******************************************************************** + +-- disable_warnings +-- eval $slow_query +-- enable_warnings + +let $master_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; +-- sync_slave_with_master +let $slave_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($master_slow_query != $slave_slow_query) +{ + -- connection master + -- echo *********************************************** + -- echo ** DUMPING MASTER SLOW LOG CONTENTS + -- echo *********************************************** + SELECT * FROM mysql.slow_log; + + -- connection slave + -- echo *********************************************** + -- echo ** DUMPING SLAVE SLOW LOG CONTENTS + -- echo *********************************************** + SELECT * FROM mysql.slow_log; + + -- die "Assertion failed! Master and slave slow log contents differ. Bailing out!" +} + +if ($master_slow_query == $slave_slow_query) +{ + -- echo ### Assertion is good. Both Master and Slave exhibit the + -- echo ### same number of queries in slow log: $master_slow_query +} + +TRUNCATE mysql.slow_log; +-- connection master +TRUNCATE mysql.slow_log; + +-- echo ******************************************************************** +-- echo **** Now do inserts again, but first add an index to the table. +-- echo **** Outcome: Note that the slave contains the same one entry (as +-- echo **** the master does) whereas before the patch it did not. +-- echo ******************************************************************** + +ALTER TABLE t1 ADD INDEX id1(a); + +-- disable_warnings +-- eval $slow_query +-- enable_warnings + +let $master_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; +-- sync_slave_with_master +let $slave_slow_query= `SELECT count(*) = 1 FROM mysql.slow_log WHERE sql_text like '$slow_query'`; + +if ($master_slow_query != $slave_slow_query) +{ + -- connection master + -- echo *********************************************** + -- echo ** DUMPING MASTER SLOW LOG CONTENTS + -- echo *********************************************** + SELECT * FROM mysql.slow_log; + + -- connection slave + -- echo *********************************************** + -- echo ** DUMPING SLAVE SLOW LOG CONTENTS + -- echo *********************************************** + SELECT * FROM mysql.slow_log; + + -- die "Assertion failed! Master and slave slow log contents differ. Bailing out!" +} + +if ($master_slow_query == $slave_slow_query) +{ + -- echo ### Assertion is good. Both Master and Slave exhibit the + -- echo ### same number of queries in slow log: $master_slow_query +} + +-- echo ******************************************************************** +-- echo **** TRUNCATE the slow log then check whether runtime changes of +-- echo **** log_slow_slave_statements work without slave restart. +-- echo ******************************************************************** + +SET @old_log_slow_slave_statements= @@global.log_slow_slave_statements; +SET @@global.log_slow_slave_statements = off; +TRUNCATE mysql.slow_log; + +-- connection master + +--disable_warnings +-- eval $slow_query; +--enable_warnings +sync_slave_with_master; + +-- connection slave + +eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query'; + +SET @@global.log_slow_slave_statements = on; + +-- connection master + +--disable_warnings +-- eval $slow_query; +--enable_warnings +sync_slave_with_master; + +-- connection slave + +eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query'; + +-- connection master +SET @@global.log_output= @old_log_output; +SET @@global.long_query_time= @old_long_query_time; +DROP TABLE t1; + +-- sync_slave_with_master +SET @@global.log_output= @old_log_output; +SET @@global.long_query_time= @old_long_query_time; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_sp-master.opt b/mysql-test/suite/rpl/t/rpl_sp-master.opt new file mode 100644 index 00000000..18c5c969 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp-master.opt @@ -0,0 +1 @@ +--log_bin_trust_function_creators=0 diff --git a/mysql-test/suite/rpl/t/rpl_sp-slave.opt b/mysql-test/suite/rpl/t/rpl_sp-slave.opt new file mode 100644 index 00000000..18c5c969 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp-slave.opt @@ -0,0 +1 @@ +--log_bin_trust_function_creators=0 diff --git a/mysql-test/suite/rpl/t/rpl_sp.test b/mysql-test/suite/rpl/t/rpl_sp.test new file mode 100644 index 00000000..637dda47 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp.test @@ -0,0 +1,730 @@ +# row-based and statement have expected binlog difference in result files + +# Test of replication of stored procedures (WL#2146 for MySQL 5.0) +# Modified by WL#2971. + +source include/have_binlog_format_mixed.inc; +source include/master-slave.inc; + +set local sql_mode=''; +# we need a db != test, where we don't have automatic grants +--disable_warnings +drop database if exists mysqltest1; +--enable_warnings +create database mysqltest1; +use mysqltest1; +create table t1 (a varchar(100)); +sync_slave_with_master; +use mysqltest1; + +# ********************** PART 1 : STORED PROCEDURES *************** + +# Does the same proc as on master get inserted into mysql.proc ? +# (same definer, same properties...) + +connection master; + +delimiter |; + +# Stored procedures don't have the limitations that functions have +# regarding binlogging: it's ok to create a procedure as not +# deterministic and updating data, while it's not ok to create such a +# function. We test this. + +create procedure foo() +begin + declare b int; + set b = 8; + insert into t1 values (b); + insert into t1 values (unix_timestamp()); +end| +delimiter ;| + +# we replace columns having times +# (even with fixed timestamp displayed time may changed based on TZ) +--replace_result localhost.localdomain localhost 127.0.0.1 localhost +--replace_column 13 # 14 # +select * from mysql.proc where name='foo' and db='mysqltest1'; +sync_slave_with_master; +# You will notice in the result that the definer does not match what +# it is on master, it is a known bug on which Alik is working +--replace_result localhost.localdomain localhost 127.0.0.1 localhost +--replace_column 13 # 14 # +select * from mysql.proc where name='foo' and db='mysqltest1'; + +connection master; +# see if timestamp used in SP on slave is same as on master +set timestamp=1000000000; +call foo(); +select * from t1; +sync_slave_with_master; +select * from t1; + +# Now a SP which is not updating tables + +connection master; +delete from t1; +create procedure foo2() + select * from mysqltest1.t1; +call foo2(); + +# check that this is allowed (it's not for functions): +alter procedure foo2 contains sql; + +# SP with definer's right + +drop table t1; +create table t1 (a int); +create table t2 like t1; + +create procedure foo3() + deterministic + insert into t1 values (15); + +# let's create a non-privileged user +grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; +grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; +grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; + +# ToDo: BUG#14931: There is a race between the last grant binlogging, and +# the binlogging in the new connection made below, causing sporadic test +# failures due to switched statement order in binlog. To fix this we do +# SELECT 1 in the first connection before starting the second, ensuring +# that binlogging is done in the expected order. +# Please remove this SELECT 1 when BUG#14931 is fixed. +SELECT 1; + +connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); +connection con1; + +# this routine will fail in the second INSERT because of privileges +delimiter |; +create procedure foo4() + deterministic + begin + insert into t2 values(3); + insert into t1 values (5); + end| + +delimiter ;| + +# I add ,0 so that it does not print the error in the test output, +# because this error is hostname-dependent +--error 1142,0 +call foo4(); # invoker has no INSERT grant on table t1 => failure + +connection master; +call foo3(); # success (definer == root) +show warnings; + +--error 1142,0 +call foo4(); # definer's rights => failure + +# we test replication of ALTER PROCEDURE +alter procedure foo4 sql security invoker; +call foo4(); # invoker's rights => success +show warnings; + +# Note that half-failed procedure calls are ok with binlogging; +# if we compare t2 on master and slave we see they are identical: + +select * from t1; +select * from t2; +sync_slave_with_master; +select * from t1; +select * from t2; + +# Let's check another failing-in-the-middle procedure +connection master; +delete from t2; +alter table t2 add unique (a); + +drop procedure foo4; +delimiter |; +create procedure foo4() + deterministic + begin + insert into t2 values(20),(20); + end| + +delimiter ;| + +--error ER_DUP_ENTRY +call foo4(); +show warnings; + +select * from t2; +sync_slave_with_master; +# check that this failed-in-the-middle replicated right: +select * from t2; + +# Test of DROP PROCEDURE + +--replace_result localhost.localdomain localhost 127.0.0.1 localhost +--replace_column 13 # 14 # +select * from mysql.proc where name="foo4" and db='mysqltest1'; +connection master; +drop procedure foo4; +select * from mysql.proc where name="foo4" and db='mysqltest1'; +sync_slave_with_master; +select * from mysql.proc where name="foo4" and db='mysqltest1'; + +# ********************** PART 2 : FUNCTIONS *************** + +connection master; +drop procedure foo; +drop procedure foo2; +drop procedure foo3; + +delimiter |; +# check that needs "deterministic" +--error 1418 +create function fn1(x int) + returns int +begin + insert into t1 values (x); + return x+2; +end| +create function fn1(x int) + returns int + deterministic +begin + insert into t1 values (x); + return x+2; +end| + +delimiter ;| +delete t1,t2 from t1,t2; +select fn1(20); +insert into t2 values(fn1(21)); +--sorted_result +select * from t1; +select * from t2; +sync_slave_with_master; +--sorted_result +select * from t1; +select * from t2; + +connection master; +delimiter |; + +drop function fn1; + +create function fn1() + returns int + no sql +begin + return unix_timestamp(); +end| + +delimiter ;| +# check that needs "deterministic" +--error 1418 +alter function fn1 contains sql; + +delete from t1; +set timestamp=1000000000; +insert into t1 values(fn1()); + +connection con1; + +delimiter |; +--error 1419 # only full-global-privs user can create a function +create function fn2() + returns int + no sql +begin + return unix_timestamp(); +end| +delimiter ;| +connection master; +set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; +set global log_bin_trust_function_creators=0; +set global log_bin_trust_function_creators=1; +# slave needs it too otherwise will not execute what master allowed: +connection slave; +set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; +set global log_bin_trust_function_creators=1; + +connection con1; + +delimiter |; +create function fn2() + returns int + no sql +begin + return unix_timestamp(); +end| +delimiter ;| + +connection master; + +# Now a function which is supposed to not update tables +# as it's "reads sql data", so should not give error even if +# non-deterministic. + +delimiter |; +create function fn3() + returns int + not deterministic + reads sql data +begin + return 0; +end| +delimiter ;| + +select fn3(); +--replace_result localhost.localdomain localhost 127.0.0.1 localhost +--replace_column 13 # 14 # +select * from mysql.proc where db='mysqltest1'; +select * from t1; + +sync_slave_with_master; +use mysqltest1; +select * from t1; +--replace_result localhost.localdomain localhost 127.0.0.1 localhost +--replace_column 13 # 14 # +select * from mysql.proc where db='mysqltest1'; + +# Let's check a failing-in-the-middle function +connection master; +delete from t2; +alter table t2 add unique (a); + +drop function fn1; + +delimiter |; +create function fn1(x int) + returns int +begin + insert into t2 values(x),(x); + return 10; +end| + +delimiter ;| + +do fn1(100); + +--error ER_DUP_ENTRY +select fn1(20); + +select * from t2; +sync_slave_with_master; + +# check that this failed-in-the-middle replicated right: +select * from t2; + +# ********************** PART 3 : TRIGGERS *************** + +connection con1; +# now fails due to missing trigger grant (err 1142 i/o 1227) due to new +# check in sql_trigger.cc (v1.44) by anozdrin on 2006/02/01 --azundris +--error ER_TABLEACCESS_DENIED_ERROR +create trigger trg before insert on t1 for each row set new.a= 10; + +connection master; +delete from t1; +# TODO: when triggers can contain an update, test that this update +# does not go into binlog. +# I'm not setting user vars in the trigger, because replication of user vars +# would take care of propagating the user var's value to slave, so even if +# the trigger was not executed on slave it would not be discovered. +create trigger trg before insert on t1 for each row set new.a= 10; +insert into t1 values (1); +select * from t1; +sync_slave_with_master; +select * from t1; + +connection master; +delete from t1; +drop trigger trg; +insert into t1 values (1); +select * from t1; +sync_slave_with_master; +select * from t1; + + +# ********************** PART 4 : RELATED FIXED BUGS *************** + + +# +# Test for bug #13969 "Routines which are replicated from master can't be +# executed on slave". +# +connection master; +create procedure foo() + not deterministic + reads sql data + select * from t1; +sync_slave_with_master; +# This should not fail +call foo(); +connection master; +drop procedure foo; +sync_slave_with_master; + + +# Clean up +connection master; +drop function fn1; +drop database mysqltest1; +drop user "zedjzlcsjhd"@127.0.0.1; +use test; +sync_slave_with_master; +use test; + +# +# Bug#14077 "Failure to replicate a stored function with a cursor": +# verify that stored routines with cursors work on slave. +# +connection master; +--disable_warnings +drop function if exists f1; +--enable_warnings +delimiter |; +create function f1() returns int reads sql data +begin + declare var integer; + declare c cursor for select a from v1; + open c; + fetch c into var; + close c; + return var; +end| +delimiter ;| +create view v1 as select 1 as a; +create table t1 (a int); +insert into t1 (a) values (f1()); +select * from t1; +drop view v1; +drop function f1; +sync_slave_with_master; +connection slave; +select * from t1; + +# +# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary +# Log for 5.0.18" +# + +# Prepare environment. + +connection master; + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +# Test case. + +CREATE TABLE t1(col VARCHAR(10)); + +CREATE PROCEDURE p1(arg VARCHAR(10)) + INSERT INTO t1 VALUES(arg); + +CALL p1('test'); + +SELECT * FROM t1; + +sync_slave_with_master; +SELECT * FROM t1; + +# Cleanup +connection master; +DROP PROCEDURE p1; + + +# +# BUG#20438: CREATE statements for views, stored routines and triggers can be +# not replicable. +# + +--echo +--echo ---> Test for BUG#20438 + +# Prepare environment. + +--echo +--echo ---> Preparing environment... +--connection master + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +--connection master + +# Test. + +--echo +--echo ---> Creating procedure... + +/*!50003 CREATE PROCEDURE p1() SET @a = 1 */; + +/*!50003 CREATE FUNCTION f1() RETURNS INT RETURN 0 */; + +--echo +--echo ---> Checking on master... + +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +--echo +--echo ---> Checking on slave... + +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; + +# Cleanup. + +--connection master + +--echo +--echo ---> Cleaning up... + +DROP PROCEDURE p1; +DROP FUNCTION f1; + +--sync_slave_with_master +--connection master + + +# cleanup +connection master; +drop table t1; +sync_slave_with_master; + +# +# Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS" +# + +connection master; +--disable_warnings +drop database if exists mysqltest; +drop database if exists mysqltest2; +--enable_warnings +create database mysqltest; +create database mysqltest2; +use mysqltest2; +create table t ( t integer ); +create procedure mysqltest.test() begin end; +insert into t values ( 1 ); +--error ER_BAD_DB_ERROR +create procedure `\\`.test() begin end; + +# +# BUG#19725: Calls to stored function in other database are not +# replicated correctly in some cases +# + +connection master; +delimiter |; +create function f1 () returns int +begin + insert into t values (1); + return 0; +end| +delimiter ;| +sync_slave_with_master; +# Let us test if we don't forget to binlog the function's database +connection master; +use mysqltest; +set @a:= mysqltest2.f1(); +sync_slave_with_master; +connection master; + +# Final inspection which verifies how all statements of this test file +# were written to the binary log. +--source include/show_binlog_events.inc + + +# Restore log_bin_trust_function_creators to its original value. +# This is a cleanup for all parts above where we tested stored +# functions and triggers. +connection slave; +set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; +connection master; +set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; + +# Clean up +drop database mysqltest; +drop database mysqltest2; +sync_slave_with_master; + +# +# Bug#36570: Parse error of CREATE PROCEDURE stmt with comments on slave +# +connection master; +use test; +delimiter |; + +/*!50001 create procedure `mysqltestbug36570_p1`() */ +begin + select 1; +end| + +use mysql| +create procedure test.` mysqltestbug36570_p2`(/*!50001 a int*/)`label`: +begin + select a; +end| + +/*!50001 create function test.mysqltestbug36570_f1() */ + returns int + /*!50001 deterministic */ +begin + return 3; +end| +use test| + +delimiter ;| + +--replace_column 5 t 6 t +show procedure status like '%mysqltestbug36570%'; +show create procedure ` mysqltestbug36570_p2`; + +sync_slave_with_master; +connection slave; + +--replace_column 5 t 6 t +show procedure status like '%mysqltestbug36570%'; +show create procedure ` mysqltestbug36570_p2`; +call ` mysqltestbug36570_p2`(42); + +--replace_column 5 t 6 t +show function status like '%mysqltestbug36570%'; + +connection master; +flush logs; +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_regex /$MYSQL_TEST_DIR/MYSQL_TEST_DIR/ /TIMESTAMP=[0-9]*/TIMESTAMP=t/ +--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 +use test; +drop procedure mysqltestbug36570_p1; +drop procedure ` mysqltestbug36570_p2`; +drop function mysqltestbug36570_f1; +--echo End of 5.0 tests +--echo # End of 5.1 tests +--echo # +--echo # Test Bug#30977 Concurrent statement using stored +--echo # function and DROP FUNCTION breaks SBR. +--echo # +--echo # Demonstrate that stored function DDL can not go through, +--echo # or, worse yet, make its way into the binary log, while +--echo # the stored function is in use. +--echo # For that, try to insert a result of a stored function +--echo # into a table. Block the insert in the beginning, waiting +--echo # on a table lock. While insert is blocked, attempt to +--echo # drop the routine. Verify that this attempt +--echo # blocks and waits for INSERT to complete. Commit and +--echo # reap the chain of events. Master and slave must contain +--echo # identical data. Statements in the binrary log must be +--echo # consistent with data in the table. +--echo # +connection default; +--disable_warnings +drop table if exists t1, t2; +drop function if exists t1; +--enable_warnings +create table t1 (a int); +create table t2 (a int) as select 1 as a; +create function f1() returns int deterministic return (select max(a) from t2); +lock table t2 write; +connection master; +--echo # Sending 'insert into t1 (a) values (f1())'... +--send insert into t1 (a) values (f1()) +connection master1; +--echo # Waitng for 'insert into t1 ...' to get blocked on table lock... +let $wait_condition=select count(*)=1 from information_schema.processlist +where state='Waiting for table metadata lock' and + info='insert into t1 (a) values (f1())'; +--source include/wait_condition.inc +--echo # Sending 'drop function f1'. It will wait till insert finishes. +--send drop function f1; +connection default; +--echo # Check that 'drop function f1' gets blocked. +let $wait_condition=select count(*)=1 from information_schema.processlist +where state='Waiting for stored function metadata lock' and info='drop function f1'; +--source include/wait_condition.inc +--echo # Now let's let 'insert' go through... +unlock tables; +connection master; +--echo # Reaping 'insert into t1 (a) values (f1())'... +--reap +connection master1; +--echo # Reaping 'drop function f1' +--reap +connection master; +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +# Cleanup +connection master; +drop table t1, t2; +--error ER_SP_DOES_NOT_EXIST +drop function f1; + + +--echo # +--echo # Bug #11918 Can't use a declared variable in LIMIT clause +--echo # +--source include/rpl_reset.inc + +create table t1 (c1 int); +insert into t1 (c1) values +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +create procedure p1(p1 integer) + delete from t1 limit p1; + +set @save_binlog_format=@@session.binlog_format; +set @@session.binlog_format=STATEMENT; + +--disable_warnings +call p1(NULL); +call p1(0); +call p1(1); +call p1(2); +call p1(3); +--enable_warnings + +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +--disable_warnings +call p1(-1); +--enable_warnings +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; + +--echo # Cleanup +set @@session.binlog_format=@save_binlog_format; +drop table t1; +drop procedure p1; + +--echo # End of 5.5 tests. + + +# Cleanup +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_sp004.test b/mysql-test/suite/rpl/t/rpl_sp004.test new file mode 100644 index 00000000..31e4ce37 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp004.test @@ -0,0 +1,92 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/14/2005 # +############################################################################# +# Test: This test contains two sp that create and drop tables, insert and # +# updated data and uses the NOW() function. # +############################################################################# + + +# Includes +-- source include/master-slave.inc + + +# Begin clean up test section +connection master; +--disable_warnings +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t3; +--enable_warnings +# End of cleanup + +# Begin test section 1 + +delimiter |; +CREATE PROCEDURE test.p1() +BEGIN + CREATE TABLE IF NOT EXISTS test.t1(a INT,PRIMARY KEY(a)); + CREATE TABLE IF NOT EXISTS test.t2(a INT,PRIMARY KEY(a)); + INSERT INTO test.t1 VALUES (4),(2),(1),(3); + UPDATE test.t1 SET a=a+4 WHERE a=4; + INSERT INTO test.t2 (a) SELECT t1.a FROM test.t1; + UPDATE test.t1 SET a=a+4 WHERE a=8; + CREATE TABLE IF NOT EXISTS test.t3(n MEDIUMINT NOT NULL AUTO_INCREMENT, f FLOAT, d DATETIME, PRIMARY KEY(n)); +END| +CREATE PROCEDURE test.p2() +BEGIN + DROP TABLE IF EXISTS test.t1; + DROP TABLE IF EXISTS test.t2; + INSERT INTO test.t3 VALUES(NULL,11111111.233333,NOW()); +END| +delimiter ;| + +CALL test.p1(); +SELECT * FROM test.t1 ORDER BY a; +SELECT * FROM test.t2 ORDER BY a; +sync_slave_with_master; +SELECT * FROM test.t1 ORDER BY a; +SELECT * FROM test.t2 ORDER BY a; + +connection master; +CALL test.p2(); +USE test; +SHOW TABLES; +#SELECT * FROM test.t3; +sync_slave_with_master; +USE test; +SHOW TABLES; +#SELECT * FROM test.t3; + +connection master; +CALL test.p1(); +SELECT * FROM test.t1 ORDER BY a; +SELECT * FROM test.t2 ORDER BY a; +#SELECT * FROM test.t3; +sync_slave_with_master; +SELECT * FROM test.t1 ORDER BY a; +SELECT * FROM test.t2 ORDER BY a; +#SELECT * FROM test.t3; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp004_master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/sp004_slave.sql + +# Cleanup +connection master; +#show binlog events; +DROP PROCEDURE IF EXISTS test.p1; +DROP PROCEDURE IF EXISTS test.p2; +DROP TABLE IF EXISTS test.t1; +DROP TABLE IF EXISTS test.t2; +DROP TABLE IF EXISTS test.t3; +sync_slave_with_master; + +# If the test fails, you will need to diff the dumps to see why. + +diff_files $MYSQLTEST_VARDIR/tmp/sp004_master.sql $MYSQLTEST_VARDIR/tmp/sp004_slave.sql; + + +# End of 5.0 test case +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt b/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt new file mode 100644 index 00000000..27fad140 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp_effects-master.opt @@ -0,0 +1 @@ +--log_bin_trust_function_creators=1 diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt b/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt new file mode 100644 index 00000000..27fad140 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp_effects-slave.opt @@ -0,0 +1 @@ +--log_bin_trust_function_creators=1 diff --git a/mysql-test/suite/rpl/t/rpl_sp_effects.test b/mysql-test/suite/rpl/t/rpl_sp_effects.test new file mode 100644 index 00000000..05bd4933 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp_effects.test @@ -0,0 +1,286 @@ +########################################## +# Change Author: JBM +# Change Date: 2006-05-02 +########################################## + +# Test of replication of stored procedures (WL#2146 for MySQL 5.0) +-- source include/master-slave.inc + +# **************************************************************** +connection master; + +SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; + +# cleanup +--disable_warnings +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; +drop table if exists t1,t2; +drop view if exists v1; +--enable_warnings +create table t1 (a int); + +SET GLOBAL log_bin_trust_function_creators = 1; + +# 1. Test simple variables use. +delimiter //; +create procedure p1() +begin + declare spv int default 0; + while spv < 5 do + insert into t1 values(spv+1); + set spv=spv+1; + end while; +end// +delimiter ;// + +call p1(); + +sync_slave_with_master; +connection slave; +SELECT * FROM t1 ORDER BY a; +connection master; +SELECT * FROM t1 ORDER BY a; + +# 2. Test SP variable name +delimiter //; +create procedure p2() +begin + declare a int default 4; + create table t2 as select a; +end// +delimiter ;// + +call p2(); +SELECT * FROM t2 ORDER BY a; +sync_slave_with_master; +connection slave; +SELECT * FROM t2 ORDER BY a; + +connection master; +drop procedure p1; +drop procedure p2; +drop table t2; + +# 3. Test FUNCTIONs in various places + +delimiter //; +create function f1(x int) returns int +begin + insert into t1 values(x); + return x+1; +end// + +create procedure p1(a int, b int) +begin + declare v int default f1(5); + if (f1(6)) then + select 'yes'; + end if; + set v = f1(7); + while f1(8) < 1 do + select 'this cant be'; + end while; + +end// +delimiter ;// + +call p1(f1(1), f1(2)); +SELECT * FROM t1 ORDER BY a; + +create table t2(a int); +insert into t2 values (10),(11); +SELECT a,f1(a) FROM t2 ORDER BY a; + +# This shouldn't put separate 'call f1(3)' into binlog: +insert into t2 select f1(3); +SELECT 'master:',a FROM t1 ORDER BY a; + +sync_slave_with_master; +connection slave; +SELECT 'slave:',a FROM t1 ORDER BY a; + +connection master; +drop procedure p1; +delete from t1; +delete from t2; + +# 4. VIEWs +delete from t1; +insert into t2 values(1),(2); +create view v1 as select f1(a) as f from t2; +select * from v1 order by f; +SELECT 'master:',a FROM t1 ORDER BY a; + +sync_slave_with_master; +connection slave; +SELECT 'slave:',a FROM t1 ORDER BY a; + +connection master; +drop view v1; +delete from t1; + +# 5. Prepared statements. +prepare s1 from 'select f1(?)'; +set @xx=123; +execute s1 using @xx; +SELECT 'master:',a FROM t1 ORDER BY a; + +sync_slave_with_master; +connection slave; +SELECT 'slave:',a FROM t1 ORDER BY a; + +connection master; +delete from t1; + +# 5. Cursors. +# t2 has (1),(2); +delimiter //; +create procedure p1(spv int) +begin + declare c cursor for select f1(spv) from t2; + while (spv > 2) do + open c; + fetch c into spv; + close c; + set spv= spv - 10; + end while; +end// +delimiter ;// +call p1(15); +SELECT 'master:',a FROM t1 ORDER BY a; +sync_slave_with_master; +connection slave; +SELECT 'slave:',a FROM t1 ORDER BY a; + +connection master; +drop procedure p1; +drop function f1; +drop table t1,t2; + +# BUG#12637: User variables + SPs replication +create table t1 (a int); +delimiter //; +create procedure p1() +begin + insert into t1 values(@x); + set @x=@x+1; + insert into t1 values(@x); + if (f2()) then + insert into t1 values(1243); + end if; +end// + +create function f2() returns int +begin + insert into t1 values(@z); + set @z=@z+1; + insert into t1 values(@z); + return 0; +end// + +create function f1() returns int +begin + insert into t1 values(@y); + call p1(); + return 0; +end// + +delimiter ;// + +set @x=10; +set @y=20; +set @z=100; +select f1(); + +set @x=30; +call p1(); + +SELECT 'master', a FROM t1 ORDER BY a; +sync_slave_with_master; +connection slave; +SELECT 'slave', a FROM t1 ORDER BY a; + +# +# cleanup +# + +connection master; +drop table t1; +drop function f1; +drop function f2; +drop procedure p1; +sync_slave_with_master; + +# +# bug#26199 Replication Failure on Slave when using stored procs +# with bit-type parameters + +connection master; + +create table t2 (b BIT(7)); +delimiter //; +create procedure sp_bug26199(bitvalue BIT(7)) +begin + insert into t2 set b = bitvalue; +end // + +create function sf_bug26199(b BIT(7)) returns int +begin + insert into t2 values(b); + return 0; +end// + +DELIMITER ;// + + + +call sp_bug26199(b'1110'); +call sp_bug26199('\0'); +select sf_bug26199(b'1111111'); +SET STATEMENT sql_mode = '' FOR +select sf_bug26199(b'101111111'); +select sf_bug26199('\''); +select hex(b) from t2; + +sync_slave_with_master; +#connection slave; +select hex(b) from t2; + +# +# cleanup bug#26199 +# +connection master; +drop table t2; +drop procedure sp_bug26199; +drop function sf_bug26199; + +SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; + +sync_slave_with_master; + +# +# Bug#16056537: MYSQLD CRASHES IN ITEM_FUNC_GET_USER_VAR::FIX_LENGTH_AND_DEC() +# +set names utf8; +--delimiter | +CREATE FUNCTION f() RETURNS timestamp DETERMINISTIC +BEGIN RETURN '2012-12-21 12:12:12'; END | +CREATE PROCEDURE p(t timestamp) +BEGIN + SET @t = t; + PREPARE stmt FROM " + UPDATE t1 SET a = @t WHERE '2012-12-31 08:00:00' < f() "; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; +END | +--delimiter ; +create table t1 (a timestamp); +call p('2012-12-31 08:00:00'); +drop table t1; +drop procedure p; +drop function f; + +--echo end of the tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_sp_variables.test b/mysql-test/suite/rpl/t/rpl_sp_variables.test new file mode 100644 index 00000000..87e9fe19 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sp_variables.test @@ -0,0 +1,28 @@ +source include/master-slave.inc; + +--echo # +--echo # MDEV-13685 Can not replay binary log due to Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation 'concat' +--echo # + +connection master; +SET NAMES utf8; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE v_id INT DEFAULT 2017; + INSERT INTO test.t1 SELECT CONCAT(v_id, '오'); +END; +$$ +DELIMITER ;$$ +CALL p1; +SELECT * FROM t1; +sync_slave_with_master; +SET NAMES utf8; +SELECT * FROM t1; +connection master; +DROP PROCEDURE p1; +DROP TABLE t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_spec_variables.test b/mysql-test/suite/rpl/t/rpl_spec_variables.test new file mode 100644 index 00000000..fdd000d0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_spec_variables.test @@ -0,0 +1,312 @@ +############################################################# +# Author: Serge Kozlov <skozlov@mysql.com> +# Date: 07/01/2008 +# Purpose: Testing possible affects of some system dynamic +# variables to the replication. +# Scenario for each variable: +# 1) Set different values for master and slave +# 2) Create and replicate a data from master to slave +# 3) Check results on master and slave: changes on slave +# shouldn't be affected to replicated data. +############################################################# +--source include/have_innodb.inc +--source include/master-slave.inc +--echo + +# +# AUTO_INCREMENT +# +--echo * auto_increment_increment, auto_increment_offset * + +--connection master +SET @@global.auto_increment_increment=2; +SET @@session.auto_increment_increment=2; +SET @@global.auto_increment_offset=10; +SET @@session.auto_increment_offset=10; + +--connection slave +SET @@global.auto_increment_increment=3; +SET @@session.auto_increment_increment=3; +SET @@global.auto_increment_offset=20; +SET @@session.auto_increment_offset=20; + +--connection master +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM; +INSERT INTO t1 (b) VALUES ('master'); +INSERT INTO t1 (b) VALUES ('master'); +SELECT * FROM t1 ORDER BY a; + +--sync_slave_with_master +CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM; +INSERT INTO t1 (b) VALUES ('slave'); +INSERT INTO t1 (b) VALUES ('slave'); +INSERT INTO t2 (b) VALUES ('slave'); +INSERT INTO t2 (b) VALUES ('slave'); +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--connection master +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings +SET @@global.auto_increment_increment=1; +SET @@session.auto_increment_increment=1; +SET @@global.auto_increment_offset=1; +SET @@session.auto_increment_offset=1; + +--connection slave +SET @@global.auto_increment_increment=1; +SET @@session.auto_increment_increment=1; +SET @@global.auto_increment_offset=1; +SET @@session.auto_increment_offset=1; + +--connection slave +SET auto_increment_increment=1; +SET auto_increment_offset=1; +--echo + +# +# CHARACTER_SET_DATABASE, COLLATION_SERVER +# +--echo * character_set_database, collation_server * + +--connection master +SET @restore_master_character_set_database=@@global.character_set_database; +SET @restore_master_collation_server=@@global.collation_server; +SET @@global.character_set_database=latin1; +SET @@session.character_set_database=latin1; +SET @@global.collation_server=latin1_german1_ci; +SET @@session.collation_server=latin1_german1_ci; + +--connection slave +SET @restore_slave_character_set_database=@@global.character_set_database; +SET @restore_slave_collation_server=@@global.collation_server; +SET @@global.character_set_database=utf8; +SET @@session.character_set_database=utf8; +SET @@global.collation_server=utf8_bin; +SET @@session.collation_server=utf8_bin; + +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM; +SHOW CREATE TABLE t1; + +--sync_slave_with_master +CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +SET @@global.collation_server=latin1_swedish_ci; +SET @@session.collation_server=latin1_swedish_ci; + +--connection master +SET @@global.collation_server=latin1_swedish_ci; +SET @@session.collation_server=latin1_swedish_ci; + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings +--echo + +# +# DEFAULT_WEEK_FORMAT +# +--echo * default_week_format * + +--connection master +SET @@global.default_week_format=0; +SET @@session.default_week_format=0; + +--connection slave +SET @@global.default_week_format=1; +SET @@session.default_week_format=1; + +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1, 'master ', WEEK('2008-01-07')); +SELECT * FROM t1 ORDER BY a; + +--sync_slave_with_master +INSERT INTO t1 VALUES (2, 'slave ', WEEK('2008-01-07')); +SELECT * FROM t1 ORDER BY a; + +--connection master +DROP TABLE t1; + +--connection slave +SET @@global.default_week_format=0; +SET @@session.default_week_format=0; +--echo + +# +# LOCAL_INFILE +# +--echo * local_infile * + +--connection slave +SET @@global.local_infile=0; + +--connection master +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(20), c CHAR(254)) ENGINE=MyISAM; +--copy_file ./std_data/words.dat $MYSQLTEST_VARDIR/tmp/words.dat +--copy_file ./std_data/words2.dat $MYSQLTEST_VARDIR/tmp/words2.dat +--replace_regex /\'.+\'/'FILE'/ +--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/words.dat' INTO TABLE t1 (b) +SELECT COUNT(*) FROM t1; +--sync_slave_with_master +--replace_regex /\'.+\'/'FILE2'/ +--error ER_LOAD_INFILE_CAPABILITY_DISABLED +--eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/words2.dat' INTO TABLE t1 (b) +SELECT COUNT(*) FROM t1; + +SET @@global.local_infile=1; + +--connection master +DROP TABLE t1; +--echo + +# +# MAX_HEAP_TABLE_SIZE +# +--echo * max_heap_table_size * + +--connection slave +SET @restore_slave_max_heap_table_size=@@global.max_heap_table_size; +SET @@global.max_heap_table_size=16384; +SET @@session.max_heap_table_size=16384; + +--connection master +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), c CHAR(254)) ENGINE=MEMORY; +let $counter=2000; +--disable_query_log +while ($counter) { + INSERT INTO t1 (b,c) VALUES ('master', REPEAT('A', 254)); + dec $counter; +} +--enable_query_log +SELECT COUNT(*)=2000 FROM t1; + +--sync_slave_with_master +let $counter=2000; +--disable_query_log +while ($counter) { + --error 0,1114 + INSERT INTO t1 (b,c) VALUES ('slave', REPEAT('A', 254)); + dec $counter; +} +CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b VARCHAR(10), c CHAR(254)) ENGINE=MEMORY; +let $counter=2000; +--disable_query_log +while ($counter) { + --error 0,1114 + INSERT INTO t2 (b,c) VALUES ('slave', REPEAT('A', 254)); + dec $counter; +} +--enable_query_log +# We don't know how many memory used and can't check exact values so need to check following +# conditions +SELECT COUNT(*)=2000 FROM t1 WHERE b='master' GROUP BY b ORDER BY b; +SELECT COUNT(*)<2000 AND COUNT(*)>0 FROM t1 WHERE b='slave' GROUP BY b ORDER BY b; +SELECT COUNT(*)<2000 AND COUNT(*)>0 FROM t2 WHERE b='slave' GROUP BY b ORDER BY b; + +--connection master +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings +--echo + +# +# STORAGE_ENGINE +# +--echo * storage_engine * + +--connection master +SET @restore_master_storage_engine=@@global.default_storage_engine; +SET @@global.default_storage_engine=InnoDB; +SET @@session.default_storage_engine=InnoDB; + +--connection slave +SET @restore_slave_storage_engine=@@global.default_storage_engine; +SET @@global.default_storage_engine=Memory; +SET @@session.default_storage_engine=Memory; + +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)); +CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB; + +--sync_slave_with_master +CREATE TABLE t3 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10)); + +--connection master +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +--connection slave +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SHOW CREATE TABLE t3; + +SET @@global.default_storage_engine=InnoDB; +SET @@session.default_storage_engine=InnoDB; + +--connection master +--disable_warnings +DROP TABLE IF EXISTS t1,t2,t3; +--enable_warnings +--echo + +# +# SQL_MODE +# +--echo * sql_mode * + +--connection master +SET @old_sql_mode_master= @@global.sql_mode; +SET @@global.sql_mode=ANSI; +SET @@session.sql_mode=ANSI; + +--connection slave +SET @old_sql_mode_slave= @@global.sql_mode; +SET @@global.sql_mode=TRADITIONAL; +SET @@session.sql_mode=TRADITIONAL; + +--connection master +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c DATE); +INSERT INTO t1 VALUES (1, 'master', '0000-00-00'); +SELECT * FROM t1 ORDER BY a; + +--sync_slave_with_master +--error 1292 +INSERT INTO t1 VALUES (1, 'slave', '0000-00-00'); +SELECT * FROM t1 ORDER BY a; +SET @@global.sql_mode=''; +SET @@session.sql_mode=''; + +--connection master +SET @@global.sql_mode=''; +SET @@session.sql_mode=''; +DROP TABLE t1; +--echo + + +# Clean up +--echo *** clean up *** +--connection master +SET @@global.character_set_database=@restore_master_character_set_database; +SET @@global.collation_server=@restore_master_collation_server; +SET @@global.default_storage_engine=@restore_master_storage_engine; +SET @@global.sql_mode=@old_sql_mode_master; +--sync_slave_with_master +SET @@global.character_set_database=@restore_slave_character_set_database; +SET @@global.collation_server=@restore_slave_collation_server; +SET @@global.max_heap_table_size=@restore_slave_max_heap_table_size; +SET @@global.default_storage_engine=@restore_slave_storage_engine; +SET @@global.sql_mode=@old_sql_mode_slave; + +# Put at the end since the test otherwise emptied the table. +remove_file $MYSQLTEST_VARDIR/tmp/words.dat; +remove_file $MYSQLTEST_VARDIR/tmp/words2.dat; +--echo +call mtr.add_suppression("The table 't[12]' is full"); + +# End of 5.1 test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_special_charset.opt b/mysql-test/suite/rpl/t/rpl_special_charset.opt new file mode 100644 index 00000000..b071fb20 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_special_charset.opt @@ -0,0 +1 @@ +--character-set-server=utf16 diff --git a/mysql-test/suite/rpl/t/rpl_special_charset.test b/mysql-test/suite/rpl/t/rpl_special_charset.test new file mode 100644 index 00000000..fa19a17b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_special_charset.test @@ -0,0 +1 @@ +--source include/rpl_special_charset.inc diff --git a/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt b/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt new file mode 100644 index 00000000..5f038b69 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sporadic_master-master.opt @@ -0,0 +1 @@ +--debug-sporadic-binlog-dump-fail --debug-max-binlog-dump-events=2 diff --git a/mysql-test/suite/rpl/t/rpl_sporadic_master.test b/mysql-test/suite/rpl/t/rpl_sporadic_master.test new file mode 100644 index 00000000..397756af --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sporadic_master.test @@ -0,0 +1 @@ +--source include/rpl_sporadic_master.inc diff --git a/mysql-test/suite/rpl/t/rpl_ssl.test b/mysql-test/suite/rpl/t/rpl_ssl.test new file mode 100644 index 00000000..c4a534b9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ssl.test @@ -0,0 +1 @@ +--source include/rpl_ssl.inc diff --git a/mysql-test/suite/rpl/t/rpl_ssl1.test b/mysql-test/suite/rpl/t/rpl_ssl1.test new file mode 100644 index 00000000..d994dd21 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ssl1.test @@ -0,0 +1,110 @@ +source include/have_ssl_communication.inc; +source include/master-slave.inc; + +# We don't test all types of ssl auth params here since it's a bit hard +# until problems with OpenSSL 0.9.7 are unresolved + +# creating replication user for whom ssl auth is required +# preparing playground +connection master; +create user replssl@localhost; +grant replication slave on *.* to replssl@localhost require ssl; +create table t1 (t int); + +sync_slave_with_master; + +#trying to use this user without ssl +stop slave; +--source include/wait_for_slave_to_stop.inc +change master to master_user='replssl',master_password=''; +start slave; + +#showing that replication don't work +connection master; +insert into t1 values (1); +#reasonable timeout for changes to propagate to slave +let $wait_condition= SELECT COUNT(*) = 1 FROM t1; +source include/wait_condition.inc; +connection slave; +select * from t1; + +#showing that replication could work with ssl params +stop slave; +--source include/wait_for_slave_to_stop.inc +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +eval change master to master_ssl=1 , master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem'; +start slave; +--source include/wait_for_slave_to_start.inc + +#avoiding unneeded sleeps +connection master; +sync_slave_with_master; + +#checking that replication is ok +select * from t1; + +#checking show slave status +let $status_items= Master_SSL_Allowed, Master_SSL_CA_Path, Master_SSL_CA_File, Master_SSL_Cert, Master_SSL_Key; +source include/show_slave_status.inc; +source include/check_slave_is_running.inc; + +#checking if replication works without ssl also performing clean up +stop slave; +--source include/wait_for_slave_to_stop.inc +change master to master_user='root',master_password='', master_ssl=0; +start slave; +--source include/wait_for_slave_to_start.inc +connection master; +drop user replssl@localhost; +drop table t1; + +sync_slave_with_master; +source include/show_slave_status.inc; +source include/check_slave_is_running.inc; +# End of 4.1 tests + +# Start replication with ssl_verify_server_cert turned on +connection slave; +stop slave; +--source include/wait_for_slave_to_stop.inc +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +eval change master to + master_host="localhost", + master_ssl=1 , + master_ssl_ca ='$MYSQL_TEST_DIR/std_data/cacert.pem', + master_ssl_cert='$MYSQL_TEST_DIR/std_data/client-cert.pem', + master_ssl_key='$MYSQL_TEST_DIR/std_data/client-key.pem', + master_ssl_verify_server_cert=1; +start slave; +--source include/wait_for_slave_to_start.inc + +connection master; +create table t1 (t int); +insert into t1 values (1); + +sync_slave_with_master; + +echo on slave; +#checking that replication is ok +select * from t1; + +#checking show slave status +source include/show_slave_status.inc; +--source include/check_slave_is_running.inc + +# ==== Clean up ==== + +connection master; +drop table t1; +sync_slave_with_master; +--source include/stop_slave.inc +CHANGE MASTER TO + master_host="127.0.0.1", + master_ssl_ca ='', + master_ssl_cert='', + master_ssl_key='', + master_ssl_verify_server_cert=0, + master_ssl=0; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt new file mode 100644 index 00000000..c7cdc20f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt @@ -0,0 +1 @@ +--loose-innodb-lock-wait-timeout=60 diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test new file mode 100644 index 00000000..23b25b1b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test @@ -0,0 +1,65 @@ +# +#BUG#11752315 : STOP SLAVE UNABLE TO COMPLETE WHEN SLAVE THREAD IS TRYING +# TO RECONNECT TO +# +# ==== Purpose ==== +# +#Tests that the slave does not go to a sleep for a long duration after the +#master is killed and we do a START_SLAVE and STOP_SLAVE. +# +# ==== Method ==== +# +#This is a new functionality of having an interruptable sleep of the slave. +#We find the thread id for the slave thread. On finding the thread ID of the +#slave thread we kill the slave thread. A successful kill in less than 60 sec +#should serve the purpose of checking the functionality. +# + +--source include/have_log_bin.inc +--source include/master-slave.inc + +connection slave; +--let $connection_id=`SELECT id FROM information_schema.processlist where state LIKE 'Waiting for master to send event'` + +if(!$connection_id) +{ + # Something went wrong (timing) + # Show process list so that we can debug. In this case we will abort with + # wrong result + -- echo "Could not find connect id. Dumping process list for debugging" + SELECT * FROM information_schema.processlist; + exit; +} + +set @time_before_kill := (select CURRENT_TIMESTAMP); + +--echo [Time before the query] +--echo [Connection ID of the slave I/O thread found] + +--replace_regex /kill [0-9]*/kill <connection_id>/ +--eval kill $connection_id +--source include/wait_for_slave_io_to_stop.inc + +set @time_after_kill := (select CURRENT_TIMESTAMP); + +--echo [Time after the query] + +if(`select TIMESTAMPDIFF(SECOND,@time_after_kill, @time_before_kill) > 60`) +{ +--echo # assert : The difference between the timestamps 'time_after_kill' and 'time_before_kill' should be less than 60sec. +--die +} +--echo [Killing of the slave IO thread was successful] + +START SLAVE IO_THREAD; +--source include/wait_for_slave_io_to_start.inc + +# Ensure that the slave io thread started properly +connection master; +create table t1 (a int primary key); +sync_slave_with_master; +connection master; +drop table t1; + +# End of test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_000001.test b/mysql-test/suite/rpl/t/rpl_stm_000001.test new file mode 100644 index 00000000..62b5c5b1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_000001.test @@ -0,0 +1,118 @@ +# Requires binlog_format=statement format since query involving +# get_lock() is logged in row format if binlog_format=mixed or row. +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +# Load some data into t1 +create table t1 (word char(20) not null); +load data infile '../../std_data/words.dat' into table t1; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +eval load data local infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1; +select * from t1 limit 10; + +# +# Test slave with wrong password +# +sync_slave_with_master; +stop slave; +connection master; +create temporary table tmp select * from mysql.global_priv where host="localhost" and user="root"; +set password for root@"localhost" = password('foo'); +connection slave; +start slave; +connection master; +# +# Give slave time to do at last one failed connect retry +# This one must be short so that the slave will not stop retrying +real_sleep 2; +replace into mysql.global_priv select * from tmp; +drop temporary table tmp; +flush privileges; +# Give slave time to connect (will retry every second) +sleep 2; + +create table t3(n int); +insert into t3 values(1),(2); +sync_slave_with_master; +select * from t3; +select sum(length(word)) from t1; +connection master; +drop table t1,t3; +sync_slave_with_master; + +# Test if the slave SQL thread can be more than 16K behind the slave +# I/O thread (> IO_SIZE) + +connection master; +# we'll use table-level locking to delay slave SQL thread +eval create table t1 (n int); +sync_slave_with_master; +connection master; +reset master; +connection slave; +stop slave; +reset slave; + +connection master; +let $1=5000; +# Generate 16K of relay log +disable_query_log; +while ($1) +{ + eval insert into t1 values($1); + dec $1; +} +enable_query_log; + +# Try to cause a large relay log lag on the slave by locking t1 +connection slave; +lock tables t1 read; +start slave; +connection master; +--source include/sync_slave_io_with_master.inc +unlock tables; + +#test handling of aborted connection in the middle of update + +connection master; +create table t2(id int); +insert into t2 values(connection_id()); + +connection master1; +# Avoid generating result +create temporary table t3(n int); +--disable_warnings +insert into t3 select get_lock('crash_lock%20C', 1) from t2; +--enable_warnings + +connection master; +send update t1 set n = n + get_lock('crash_lock%20C', 2); +connection master1; +let $wait_condition= SELECT count(*) > 0 FROM information_schema.processlist WHERE info LIKE 'update%' AND state='User lock'; +source include/wait_condition.inc; +select (@id := id) - id from t2; +kill @id; +drop table t2; +drop temporary table t3; +connection master; +# The get_lock function causes warning for unsafe statement. +--disable_warnings +# 2013 = CR_SERVER_LOST +--error ER_QUERY_INTERRUPTED,ER_CONNECTION_KILLED,2013 +reap; +--enable_warnings +connection slave; +# The SQL slave thread should now have stopped because the query was killed on +# the master (so it has a non-zero error code in the binlog). +# 1927 = ER_CONNECTION_KILLED +--let $slave_sql_errno= 1927 +--source include/wait_for_slave_sql_error_and_skip.inc + +select count(*) from t1; +connection master1; +drop table t1; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test b/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test new file mode 100644 index 00000000..07b1000c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_EE_err2.test @@ -0,0 +1,8 @@ +############################# +# Author: JBM +# Date: 2006-01-11 +# Purpose: Engine Wrapper for rpl_stm_EE_err2.test +############################## +-- source include/have_binlog_format_mixed_or_statement.inc +let $engine_type=myisam; +-- source include/rpl_stm_EE_err2.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test b/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test new file mode 100644 index 00000000..280cfcc5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_auto_increment_bug33029.test @@ -0,0 +1,106 @@ +# BUG#33029 5.0 to 5.1 replication fails on dup key when inserting +# using a trig in SP + +# For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12 exclusive, +# if one statement in a SP generated AUTO_INCREMENT value by the top +# statement, all statements after it would be considered generated +# AUTO_INCREMENT value by the top statement, and a erroneous INSERT_ID +# value might be associated with these statement, which could cause +# duplicate entry error and stop the slave. + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--connection slave +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--connection master + +CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY); + +delimiter //; + +CREATE PROCEDURE p1() +BEGIN + DECLARE ins_count INT DEFAULT 10; + + WHILE ins_count > 0 DO + INSERT INTO t1 VALUES (NULL); + SET ins_count = ins_count - 1; + END WHILE; + + DELETE FROM t1 WHERE id = 1; + DELETE FROM t1 WHERE id = 2; + DELETE FROM t2 WHERE id = 1; + DELETE FROM t2 WHERE id = 2; +END// + +CREATE PROCEDURE p2() +BEGIN + INSERT INTO t1 VALUES (NULL); + DELETE FROM t1 WHERE id = f1(3); + DELETE FROM t1 WHERE id = f1(4); + DELETE FROM t2 WHERE id = 3; + DELETE FROM t2 WHERE id = 4; +END// + +CREATE TRIGGER tr1 BEFORE DELETE + ON t1 FOR EACH ROW + BEGIN + INSERT INTO t2 VALUES (NULL); + END// + +CREATE FUNCTION f1 (i int) RETURNS int + BEGIN + INSERT INTO t2 VALUES (NULL); + RETURN i; + END// + +delimiter ;// + +# the $binlog_start will be used by the show_binlog_events.inc, so +# that we can skip binlog events we don't care +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CALL p1(); +source include/show_binlog_events.inc; + +echo # Result on master; +SELECT * FROM t1; +SELECT * FROM t2; + +sync_slave_with_master; + +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; + +DROP TRIGGER tr1; + +# the $binlog_start will be used by the show_binlog_events.inc, so +# that we can skip binlog events we don't care +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CALL p2(); +source include/show_binlog_events.inc; + +echo # Result on master; +SELECT * FROM t1; +SELECT * FROM t2; + +sync_slave_with_master; + +SELECT * FROM t1; +SELECT * FROM t2; + +# clean up +connection master; +disable_warnings; +DROP TABLE IF EXISTS t1, t2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP FUNCTION IF EXISTS f1; +DROP TRIGGER IF EXISTS tr1; +enable_warnings; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt new file mode 100644 index 00000000..561902d0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_direct-master.opt @@ -0,0 +1 @@ +--binlog-direct-non-transactional-updates diff --git a/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test b/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test new file mode 100644 index 00000000..f893f909 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_binlog_max_cache_size.test @@ -0,0 +1,8 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/not_windows.inc +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +--source include/rpl_binlog_max_cache_size.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_conflicts.test b/mysql-test/suite/rpl/t/rpl_stm_conflicts.test new file mode 100644 index 00000000..a4f59253 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_conflicts.test @@ -0,0 +1,6 @@ +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; + +source include/rpl_conflicts.test; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test b/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test new file mode 100644 index 00000000..b971af71 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_drop_create_temp_table.test @@ -0,0 +1,12 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. Specifically when drop temporary tables and create temporary tables +# are used. +################################################################################### +--source include/big_test.inc +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--source include/rpl_drop_create_temp_table.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test new file mode 100644 index 00000000..70178c2e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_flsh_tbls.test @@ -0,0 +1,6 @@ +# depends on the binlog output +--source include/have_binlog_format_mixed_or_statement.inc +--source include/binlog_start_pos.inc + +let $rename_event_pos= `select @binlog_start_pos + 578`; +-- source include/rpl_flsh_tbls.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_found_rows.test b/mysql-test/suite/rpl/t/rpl_stm_found_rows.test new file mode 100644 index 00000000..9d76879a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_found_rows.test @@ -0,0 +1,116 @@ +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +# It is not possible to replicate FOUND_ROWS() using statement-based +# replication, but there is a workaround that stores the result of +# FOUND_ROWS() into a user variable and then replicates this instead. +# +# The purpose of this test case is to test that the workaround works +# properly even when inside stored programs (i.e., stored routines and +# triggers). + +--echo ==== Initialize ==== + +connection master; +CREATE TABLE t1 (a INT); +CREATE TABLE logtbl (sect INT, test INT, count INT); + +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; +INSERT INTO t1 SELECT 2*a+3 FROM t1; + + +--echo ==== Simple test ==== + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; + +# Instead of +# INSERT INTO logtbl VALUES(1, 1, FOUND_ROWS()); +# we write +SELECT FOUND_ROWS() INTO @a; +INSERT INTO logtbl VALUES(1,1,@a); + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1; +# Instead of +# INSERT INTO logtbl VALUES(1, 2, FOUND_ROWS()); +# we write +SELECT FOUND_ROWS() INTO @a; +INSERT INTO logtbl VALUES(1,2,@a); + +SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test; +sync_slave_with_master; +SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test; + + +--echo ==== Stored procedure ==== + +# Here we do both the calculation and the logging. We also do it twice +# to make sure that there are no limitations on how many times it can +# be used. + +connection master; +--delimiter $$ +CREATE PROCEDURE calc_and_log(sect INT, test INT) BEGIN + DECLARE cnt INT; + SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1; + SELECT FOUND_ROWS() INTO cnt; + INSERT INTO logtbl VALUES(sect,test,cnt); + SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; + SELECT FOUND_ROWS() INTO cnt; + INSERT INTO logtbl VALUES(sect,test+1,cnt); +END $$ +--delimiter ; + +CALL calc_and_log(2,1); + +--delimiter $$ +CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN + INSERT INTO logtbl VALUES (sect,test,found_rows); +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +SELECT FOUND_ROWS() INTO @found_rows; +CALL just_log(2,3,@found_rows); + +SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test; +sync_slave_with_master; +SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test; + + +--echo ==== Stored functions ==== +connection master; +--delimiter $$ +CREATE FUNCTION log_rows(sect INT, test INT, found_rows INT) + RETURNS INT +BEGIN + INSERT INTO logtbl VALUES(sect,test,found_rows); + RETURN found_rows; +END $$ +--delimiter ; + +SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1; +SELECT FOUND_ROWS() INTO @found_rows; +SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows); + +SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test; +sync_slave_with_master; +SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test; + + +--echo ==== Cleanup ==== +connection master; +DROP TABLE t1, logtbl; +DROP PROCEDURE just_log; +DROP PROCEDURE calc_and_log; +DROP FUNCTION log_rows; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test b/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test new file mode 100644 index 00000000..6b127182 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_implicit_commit_binlog.test @@ -0,0 +1,12 @@ +################################################################################ +# Check file include/rpl_implicit_commit_binlog.test +################################################################################ +--source include/have_udf.inc +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--let $engine=Innodb +set session default_storage_engine=innodb; +--source include/rpl_implicit_commit_binlog.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_innodb.test b/mysql-test/suite/rpl/t/rpl_stm_innodb.test new file mode 100644 index 00000000..dbfbc7f6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_innodb.test @@ -0,0 +1,9 @@ +# File for specialities regarding replication from or to InnoDB +# tables. + +source include/have_innodb.inc; +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; + +source include/rpl_innodb.test; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt new file mode 100644 index 00000000..8be29bbe --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames-slave.opt @@ -0,0 +1 @@ +--replicate-do-db=bug_37656 --replicate-ignore-table=bug_37656.t1 --replicate-do-table=bug_37656.t2 --replicate-do-table=bug_37656.t3 --lower-case-table-names=1 diff --git a/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test new file mode 100644 index 00000000..619b5799 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_lcase_tblnames.test @@ -0,0 +1,12 @@ +# BUG#37656 +# +# For details look into extra/rpl_tests/rpl_lower_case_table_names.test +# + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc +-- source include/have_innodb.inc +-- source include/not_windows.inc + +-- let $engine=InnoDB +-- source include/rpl_lower_case_table_names.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test new file mode 100644 index 00000000..4409a1a8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_loaddata_concurrent.test @@ -0,0 +1,14 @@ +-- source include/have_log_bin.inc +-- source include/have_binlog_format_statement.inc +RESET MASTER; + +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +CREATE TABLE t1 (c1 char(50)) ENGINE=MyISAM; +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +-- source include/show_binlog_events.inc +DROP TABLE t1; + +let $lock_option= CONCURRENT; +let $engine_type=MyISAM; +-- source include/rpl_loaddata.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_loadfile.test b/mysql-test/suite/rpl/t/rpl_stm_loadfile.test new file mode 100644 index 00000000..5ff3846d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_loadfile.test @@ -0,0 +1,24 @@ +############################################################################# +# Original Author: JBM # +# Original Date: Aug/18/2005 # +############################################################################# +# TEST: To test the LOAD_FILE() in rbr # +############################################################################# +# Change Author: JBM +# Change Date: 2006-01-16 +# Change: Split the original test file. This one forces STATEMENT only because +# when in STATEMENT mode, the load_file will issue a warning, whereas +# in RBR or MIXED mode it does not (by lsoares). +########## + +# Includes +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +-- source include/rpl_loadfile.test + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt new file mode 100644 index 00000000..203fc228 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_log-slave.opt @@ -0,0 +1 @@ +--log-slave-updates diff --git a/mysql-test/suite/rpl/t/rpl_stm_log.test b/mysql-test/suite/rpl/t/rpl_stm_log.test new file mode 100644 index 00000000..4a0df442 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_log.test @@ -0,0 +1,8 @@ +# Requires statement logging +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc +let $engine_type=MyISAM; +-- source include/rpl_log.test + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_maria.test b/mysql-test/suite/rpl/t/rpl_stm_maria.test new file mode 100644 index 00000000..d5a4c5c3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_maria.test @@ -0,0 +1,59 @@ +# Test of Maria-specific replication bugs + +--source include/have_maria.inc +--source include/have_binlog_format_mixed_or_statement.inc +--source include/master-slave.inc + +# Suppress warnings that rand() is unsafe in statement binlog mode +CALL mtr.add_suppression('Unsafe statement written to the binary log using statement format'); + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +--enable_warnings + +# This one taken from rpl_trigger.test (from BUG#12482) +# used to segfault slave in execution of row-based events + +# Need an explicit ENGINE= clause as @@STORAGE_ENGINE is not replicated +create table t1 (a int auto_increment, primary key (a), b int, +rand_value double not null) engine=maria; +create table t2 (a int auto_increment, primary key (a), b int) engine=maria; +create table t3 (a int auto_increment, primary key (a), name +varchar(64) not null, old_a int, old_b int, rand_value double not +null) engine=maria; + +delimiter |; +create trigger t1 before insert on t1 for each row +begin + insert into t3 values (NULL, "t1", new.a, new.b, rand()); +end| + +create trigger t2 after insert on t2 for each row +begin + insert into t3 values (NULL, "t2", new.a, new.b, rand()); +end| +delimiter ;| + +insert into t3 values(100,"log",0,0,0); + +SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186; + +--disable_warnings +insert into t1 values(1,1,rand()),(NULL,2,rand()); +insert into t2 (b) values(last_insert_id()); +insert into t2 values(3,0),(NULL,0); +insert into t2 values(NULL,0),(500,0); +--enable_warnings + +select a,b, truncate(rand_value,4) from t1; +select * from t2; +select a,name, old_a, old_b, truncate(rand_value,4) from t3; +sync_slave_with_master; +connection master; +drop table t1,t2,t3; +sync_slave_with_master; + +# End of tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test b/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test new file mode 100644 index 00000000..bea51ed2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_max_relay_size.test @@ -0,0 +1,8 @@ +# Test of options max_binlog_size and max_relay_log_size and +# how they act (if max_relay_log_size == 0, use max_binlog_size +# for relay logs too). +# Test of manual relay log rotation with FLUSH LOGS. + +# Requires statement logging +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/rpl_max_relay_size.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test b/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test new file mode 100644 index 00000000..ab823799 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_mix_show_relaylog_events.test @@ -0,0 +1,19 @@ +# BUG#28777 SHOW BINLOG EVENTS does not work on relay log files +# +# GOAL +# ==== +# +# Test that SHOW BINLOG EVENTS and the new SHOW RELAYLOG EVENTS works after +# the patch, both on master and slave. +# +# HOW +# === +# +# This test issues SHOW [BINLOG|RELAYLOG] EVENTS both on master and slave after +# some statements have been issued. + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc + +-- source include/rpl_show_relaylog_events.inc +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test new file mode 100644 index 00000000..9cb440b6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test @@ -0,0 +1,48 @@ +################################################################################### +# This test cases evaluates the mixture of non-transactional and transcational +# tables. For further details, please, read WL#2687 and WL#5072. +################################################################################### +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +let $engine_type=Innodb; +let $database_name=test; +--source include/rpl_mixing_engines.test + +# +# BUG#49522: Replication problem with mixed MyISAM/InnoDB +# + +--source include/rpl_reset.inc +-- connection master + +CREATE TABLE `t1` ( + `c1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `c2` tinyint(1) unsigned DEFAULT NULL, + `c3` varchar(300) DEFAULT NULL, + `c4` int(10) unsigned NOT NULL, + `c5` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`c1`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- sync_slave_with_master +ALTER TABLE `t1` Engine=InnoDB; + +-- connection master +SET AUTOCOMMIT=0; + +INSERT INTO t1 (c1,c2,c3,c4,c5) VALUES (1, 1, 'X', 1, NULL); +COMMIT; +ROLLBACK; +SET AUTOCOMMIT=1; + +-- sync_slave_with_master + +-- let $diff_tables= master:t1, slave:t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE `t1`; +-- sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_multi_query.test b/mysql-test/suite/rpl/t/rpl_stm_multi_query.test new file mode 100644 index 00000000..2a593efd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_multi_query.test @@ -0,0 +1,7 @@ +# Test for BUG#8436: verify that a multi-query (i.e. one query +# containing several queries (assuming client has +# CLIENT_MULTI_STATEMENTS) will be binlogged ONE-query-per-event (not +# one binlog event containing all queries) + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/rpl_multi_query.test diff --git a/mysql-test/suite/rpl/t/rpl_stm_no_op.test b/mysql-test/suite/rpl/t/rpl_stm_no_op.test new file mode 100644 index 00000000..1605b177 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_no_op.test @@ -0,0 +1,94 @@ +# It's true only in statement-based replication that a statement which +# updates no rows (UPDATE/DELETE) is binlogged; in row-based +# replication, as we log modified rows, nothing is binlogged in this +# case. So this test is meaningul only in statement-based (and if it was +# enabled in row-based, it would fail as expected). + +-- source include/have_binlog_format_mixed_or_statement.inc + +source include/master-slave.inc; + +# see if DROP DATABASE is binlogged even if no effect +connection slave; +create database mysqltest; +connection master; +drop database if exists mysqltest; +sync_slave_with_master; +# can't read dir +--replace_result "Errcode: 1" "Errcode: X" "Errcode: 2" "Errcode: X" \\ / +--error 1049 +show tables from mysqltest; + +# see if DROP TABLE is binlogged even if no effect +connection slave; +create table t1 (a int); +connection master; +drop table if exists t1; +sync_slave_with_master; +# table does not exist +--error 1146 +select * from t1; + +# see if single-table DELETE is binlogged even if no effect +connection master; +create table t1 (a int, b int); +sync_slave_with_master; +insert into t1 values(1,1); +connection master; +delete from t1; +sync_slave_with_master; +select * from t1; + +# see if single-table UPDATE is binlogged even if no effect +insert into t1 values(1,1); +connection master; +insert into t1 values(2,1); +update t1 set a=2; +sync_slave_with_master; +select * from t1; + +# End of 4.1 tests + +# see if multi-table UPDATE is binlogged even if no effect (BUG#13348) + +connection master; +create table t2 (a int, b int); +delete from t1; +insert into t1 values(1,1); +insert into t2 values(1,1); + +sync_slave_with_master; +# force a difference to see if master's multi-UPDATE will correct it +update t1 set a=2; + +connection master; +UPDATE t1, t2 SET t1.a = t2.a; + +sync_slave_with_master; +select * from t1; +select * from t2; + +# See if multi-table DELETE is binlogged even if no effect + +connection master; +delete from t1; +delete from t2; + +sync_slave_with_master; +# force a difference to see if master's multi-DELETE will correct it +insert into t1 values(1,1); +insert into t2 values(1,1); + +connection master; +DELETE t1.*, t2.* from t1, t2; + +sync_slave_with_master; +select * from t1; +select * from t2; + + +# cleanup +connection master; +drop table t1, t2; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt new file mode 100644 index 00000000..f780540a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt @@ -0,0 +1 @@ +--relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test new file mode 100644 index 00000000..b4e53358 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -0,0 +1 @@ +--source include/rpl_stm_relay_ign_space.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test b/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test new file mode 100644 index 00000000..e32b0a78 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_reset_slave.test @@ -0,0 +1,6 @@ +# TBF - difference in row level logging +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/rpl_reset_slave.test + +# End of 4.1 tests +# diff --git a/mysql-test/suite/rpl/t/rpl_stm_sp.test b/mysql-test/suite/rpl/t/rpl_stm_sp.test new file mode 100644 index 00000000..b99906b8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_sp.test @@ -0,0 +1,30 @@ +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly +--echo # + +connection master; +CREATE TABLE t1(a INT); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a TIME DEFAULT '01:01:01'; + INSERT INTO t1 VALUES (a=10101); +END; +$$ +DELIMITER ;$$ +CALL p1; +SELECT * FROM t1; + +sync_slave_with_master; +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +DROP PROCEDURE p1; +sync_slave_with_master; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test b/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test new file mode 100644 index 00000000..56821621 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_sql_mode.test @@ -0,0 +1,25 @@ +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc + +# +# Bug #51055 Replication failure on duplicate key + traditional SQL mode +# + +CREATE TABLE t1 (pk integer auto_increment , primary key (pk)); + +SET SESSION SQL_MODE='traditional'; + +-- echo # **** [MASTER] ***** +-- echo # action: raise DUP KEY error (error code should be set in the +-- echo # query log event) +-- error ER_DUP_ENTRY +INSERT INTO t1 (`pk`) VALUES (1), (1); + +DROP TABLE t1; + +-- echo # **** [ sync slave with master ] **** +-- echo # assertion: sync slave with master makes slave not to stop with +-- echo # duplicate key error (because it has received event +-- echo # with expected error code). +-- sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test new file mode 100644 index 00000000..f401db33 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test @@ -0,0 +1,26 @@ +################################################################################ +# Please, check ./include/rpl_start_stop_slave.test +################################################################################ +--source include/have_binlog_format_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +# make innodb updates run fast +--connection slave +SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit; +SET @@global.innodb_flush_log_at_trx_commit= 0; +--connection master +SET @old_innodb_flush_log_at_trx_commit= @@global.innodb_flush_log_at_trx_commit; +SET @@global.innodb_flush_log_at_trx_commit= 0; + +SET @@session.binlog_direct_non_transactional_updates= FALSE; +--source ./include/rpl_start_stop_slave.test + +# clean up +--connection slave +SET @@global.innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit; +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); +--connection master +SET @@global.innodb_flush_log_at_trx_commit= @old_innodb_flush_log_at_trx_commit; +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test b/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test new file mode 100644 index 00000000..f2315f5e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_stop_middle_group.test @@ -0,0 +1,11 @@ +################################################################################### +# Please, check include/rpl_stop_middle_group.test. +################################################################################### +-- source include/have_debug.inc +-- source include/have_innodb.inc +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc + +SET @@session.binlog_direct_non_transactional_updates= FALSE; +-- source include/rpl_stop_middle_group.test +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_until.test b/mysql-test/suite/rpl/t/rpl_stm_until.test new file mode 100644 index 00000000..c9a922e4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_until.test @@ -0,0 +1,183 @@ +# ==== Purpose ==== +# +# Verify that START SLAVE UNTIL replicates until the given binlog +# position but not longer. Verify that START SLAVE UNTIL with various +# incorrect arguments gives an error. +# +# ==== Method ==== +# +# On master, create a table and insert some rows. On slave, START +# SLAVE UNTIL so that it reads one event at a time, and check the +# table and the slave status each time. +# +# Then, on slave, run START SLAVE UNTIL with incorrect arguments and +# verify that it gives an error. +# +# ==== Related bugs ==== +# +# Bug in this test: BUG#37717: rpl.rpl_stm_until 'stmt' fails sporadically on pushbuild + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc +-- source include/rpl_reset.inc + +# Test is dependent on binlog positions +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +# prepare version for substitutions +let $VERSION=`select version()`; + +# Stop slave before it starts replication. Also sync with master +# to avoid nondeterministic behaviour. +sync_slave_with_master; +--source include/stop_slave.inc + +--echo ==== Create some events on master ==== + +connection master; +create table t1(n int not null auto_increment primary key); +insert into t1 values (1),(2),(3),(4); +let $master_log_pos_1= query_get_value(SHOW MASTER STATUS, Position, 1); +let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1); +drop table t1; +create table t2(n int not null auto_increment primary key); +insert into t2 values (1),(2); +let $master_log_pos_2= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t2 values (3),(4); +drop table t2; + +--echo ==== Replicate one event at a time on slave ==== + +# try to replicate all queries until drop of t1 +connection slave; +--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_1 MASTER_LOG_POS +eval start slave until master_log_file='$master_log_file', master_log_pos=$master_log_pos_1; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc +# here table should be still not deleted +select * from t1; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_log_pos_1 +--source include/check_slave_param.inc + +# this should fail right after start +start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc +# again this table should be still not deleted +select * from t1; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_log_pos_1 +--source include/check_slave_param.inc + +let $relay_log_file= slave-relay-bin.000003; +let $master_log_pos= $master_log_pos_2; +source include/get_relay_log_pos.inc; +# try replicate all up to and not including the second insert to t2; +--replace_result $relay_log_pos RELAY_LOG_POS +eval start slave until relay_log_file='$relay_log_file', relay_log_pos=$relay_log_pos; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc +select * from t2; +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $master_log_pos +--source include/check_slave_param.inc + +# clean up +start slave; +connection master; +sync_slave_with_master; +--source include/stop_slave.inc + +--let $exec_log_pos_1= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1) +# this should stop immediately as we are already there +--replace_result $master_log_file MASTER_LOG_FILE $master_log_pos_2 MASTER_LOG_POS +eval start slave until master_log_file='$master_log_file', master_log_pos=$master_log_pos_2; +--source include/wait_for_slave_io_to_start.inc +--source include/wait_for_slave_sql_to_stop.inc +--let $slave_param= Exec_Master_Log_Pos +--let $slave_param_value= $exec_log_pos_1 +--source include/check_slave_param.inc + +--echo ==== Test various error conditions ==== + +--error 1277 +start slave until master_log_file='master-bin', master_log_pos=561; +--error 1277 +start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; +--error 1277 +start slave until master_log_file='master-bin.000001'; +--error 1277 +start slave until relay_log_file='slave-relay-bin.000002'; +--error 1277 +start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; +# Warning should be given for second command +start slave sql_thread; +start slave until master_log_file='master-bin.000001', master_log_pos=776; + +# +# bug#47210 first execution of "start slave until" stops too early +# +# testing that a slave rotate event that is caused by stopping the slave +# does not intervene anymore in UNTIL condition. +# + +connection slave; +source include/stop_slave.inc; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; +create table t1 (a int primary key auto_increment); +save_master_pos; +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; +start slave; +sync_with_master; + +# at this point slave will close the relay log stamping it with its own +# Rotate log event. This event won't be examined on matter of the master +# UNTIL pos anymore. +source include/stop_slave.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); + +--echo master and slave are in sync now +let $diff_pos= `select $master_pos - $slave_exec_pos`; +eval select $diff_pos as zero; + +connection master; +insert into t1 set a=null; +let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t1 set a=null; +select count(*) as two from t1; + +connection slave; +--replace_result $master_log_file MASTER_LOG_FILE $until_pos UNTIL_POS; +eval start slave until master_log_file='$master_log_file', master_log_pos= $until_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +--echo slave stopped at the prescribed position +let $diff_pos= `select $until_pos - $slave_exec_pos`; +eval select $diff_pos as zero; +select count(*) as one from t1; + + +connection master; +drop table t1; + +connection slave; +start slave; +sync_with_master; + +# End of tests +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_user_variables.test b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test new file mode 100644 index 00000000..18b90658 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_user_variables.test @@ -0,0 +1,202 @@ +# +# BUG#49562: SBR out of sync when using numeric data types + user variable +# + +-- source include/have_binlog_format_statement.inc +-- source include/master-slave.inc + +## Setup user variables for several numeric types, so that we get +## coverage on the User_var_log_event different val types + +-- let $max_unsigned_long= 18446744073709551615 +-- let $min_signed_long= -9223372036854775808 +-- eval SET @positive= $max_unsigned_long +-- eval SET @negative= $min_signed_long + +CREATE TABLE t1 (`tinyint` TINYINT, + `smallint` SMALLINT, + `mediumint` MEDIUMINT, + `integer` INTEGER, + `bigint` BIGINT, + `utinyint` TINYINT UNSIGNED, + `usmallint` SMALLINT UNSIGNED, + `umediumint` MEDIUMINT UNSIGNED, + `uinteger` INTEGER UNSIGNED, + `ubigint` BIGINT UNSIGNED, + `double` DOUBLE, + `float` FLOAT, + `real` REAL(30,2), + `decimal` DECIMAL(30,2)) ENGINE = MyISAM; + +-- disable_warnings + +-- echo ### insert max unsigned +-- echo ### a) declarative +-- eval INSERT IGNORE INTO t1 VALUES ($max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long,$max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long, $max_unsigned_long); + +-- echo ######################################### +-- query_vertical SELECT * FROM t1 +-- sync_slave_with_master +-- query_vertical SELECT * FROM t1 +-- echo ######################################### +-- connection master +-- echo ## assertion: master and slave tables are in sync +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc +-- connection master +TRUNCATE t1; + +-- echo ### b) user var +INSERT IGNORE INTO t1 VALUES (@positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive, + @positive); + +-- echo ######################################### +-- query_vertical SELECT * FROM t1 +-- sync_slave_with_master +-- query_vertical SELECT * FROM t1 +-- echo ######################################### +-- connection master +-- echo ## assertion: master and slave tables are in sync +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc +-- connection master +TRUNCATE t1; + + +-- echo ### insert min signed +-- echo ### a) declarative +-- eval INSERT IGNORE INTO t1 VALUES ($min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long,$min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long, $min_signed_long); + +-- echo ######################################### +-- query_vertical SELECT * FROM t1 +-- sync_slave_with_master +-- query_vertical SELECT * FROM t1 +-- echo ######################################### +-- connection master +-- echo ## assertion: master and slave tables are in sync +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc +-- connection master +TRUNCATE t1; + +-- echo ### b) user var +INSERT IGNORE INTO t1 VALUES (@negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative, + @negative); + +-- echo ######################################### +-- query_vertical SELECT * FROM t1 +-- sync_slave_with_master +-- query_vertical SELECT * FROM t1 +-- echo ######################################### +-- connection master + +-- echo ## assertion: master and slave tables are in sync +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc +-- connection master +TRUNCATE t1; + +-- echo ## check: contents of both tables master's and slave's +-- enable_warnings + +## cleanup +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +##################################################################### +# +# BUG#51426 +# +##################################################################### +--source include/rpl_reset.inc +-- connection master +SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; +CREATE TABLE t1 ( c INT, PRIMARY KEY (c)) Engine=MyISAM; + +# offending trigger that would reset the unsigned flag for aux before +# binlogging of User_var_log_event would take place. +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW SET @aux = -1 ; + +SET @aux = 10294947273192243200; +SET @aux1= @aux; +-- error ER_DUP_ENTRY +INSERT INTO t1 VALUES (@aux) , (@aux1); +SET sql_mode = DEFAULT; + +-- sync_slave_with_master + +-- echo ## assertion: master and slave tables are in sync +-- let $diff_tables=master:t1,slave:t1 +-- source include/diff_tables.inc + +--connection master +DROP TRIGGER tr1; +DROP TABLE t1; + +-- sync_slave_with_master + +--echo +--echo # The GET DIAGNOSTICS itself is not replicated, but it can set +--echo # variables which can be used in statements that are replicated. +--echo + +--source include/rpl_reset.inc +connection master; + +CREATE TABLE t1 (a INT, b INT); +GET DIAGNOSTICS @var1 = NUMBER; +INSERT INTO t1 VALUES (@var1, 0), (@var1, 0); + +DELIMITER |; +CREATE PROCEDURE p1() +LANGUAGE SQL +BEGIN + DECLARE count INT; + UPDATE t1 SET b = 2 WHERE a = 0; + GET DIAGNOSTICS count = ROW_COUNT; + INSERT INTO t1 VALUES (1, count); +END| +DELIMITER ;| + +CALL p1(); + +-- sync_slave_with_master + +connection slave; +--echo # check if the statement was replicated. +SELECT * FROM t1 ORDER BY a; + +connection master; +--echo # Show events and cleanup +--source include/show_binlog_events.inc +DROP TABLE t1; +DROP PROCEDURE p1; + +-- sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave.test b/mysql-test/suite/rpl/t/rpl_stop_slave.test new file mode 100644 index 00000000..17efa7ad --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stop_slave.test @@ -0,0 +1,140 @@ +source include/have_innodb.inc; +source include/have_debug.inc; +source include/have_debug_sync.inc; +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; + +--echo +--echo # BUG#56118 STOP SLAVE does not wait till trx with CREATE TMP TABLE ends +--echo # +--echo # If a temporary table is created or dropped, the transaction should be +--echo # regarded similarly that a non-transactional table is modified. So +--echo # STOP SLAVE should wait until the transaction has finished. + +CREATE TABLE t1(c1 INT) ENGINE=InnoDB; +CREATE TABLE t2(c1 INT) ENGINE=InnoDB; + +sync_slave_with_master; +SET DEBUG_SYNC= 'RESET'; +source include/stop_slave.inc; + +--echo +--echo # Suspend the INSERT statement in current transaction on SQL thread. +--echo # It guarantees that SQL thread is applying the transaction when +--echo # STOP SLAVE command launchs. +SET @saved_dbug = @@GLOBAL.debug_dbug; +set global debug_dbug= '+d,after_mysql_insert'; +source include/start_slave.inc; + +--echo +--echo # CREATE TEMPORARY TABLE with InnoDB engine +--echo # ----------------------------------------- +let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB; +source include/rpl_stop_slave.test; + +--echo +--echo # CREATE TEMPORARY TABLE ... SELECT with InnoDB engine +--echo # ---------------------------------------------------- +let $tmp_table_stm= CREATE TEMPORARY TABLE tt1(c1 INT) ENGINE = InnoDB + SELECT c1 FROM t2; +source include/rpl_stop_slave.test; + +# Don't need to verify 'CREATE TEMPORARY TABLE' with MyIASM engine, as it +# never is binlogged into a transaction since 5.5. + +--echo +--echo # Test end +SET @@GLOBAL.debug_dbug = @saved_dbug; +source include/restart_slave_sql.inc; + +connection slave; +call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); +connection master; + +DROP TABLE t1, t2; + +--echo +--echo # Bug#58546 test rpl_packet timeout failure sporadically on PB +--echo # ---------------------------------------------------------------------- +--echo # STOP SLAVE stopped IO thread first and then stopped SQL thread. It was +--echo # possible that IO thread stopped after replicating part of a transaction +--echo # which SQL thread was executing. SQL thread would be hung if the +--echo # transaction could not be rolled back safely. +--echo # It caused some sporadic failures on PB2. +--echo # +--echo # This test verifies that when 'STOP SLAVE' is issued by a user, IO +--echo # thread will continue to fetch the rest events of the transaction which +--echo # is being executed by SQL thread and is not able to be rolled back safely. + +CREATE TABLE t1 (c1 INT KEY, c2 INT) ENGINE=InnoDB; +CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; +INSERT INTO t1 VALUES(1, 1); + +sync_slave_with_master; +--source include/stop_slave.inc + +connection master; +# make sure that there are no zombie threads +--source include/stop_dump_threads.inc + +SET @saved_dbug = @@GLOBAL.debug_dbug; +set global debug_dbug= '+d,dump_thread_wait_before_send_xid'; + +connection slave; +--source include/start_slave.inc + +BEGIN; +UPDATE t1 SET c2 = 2 WHERE c1 = 1; + +connection master; +BEGIN; +INSERT INTO t1 VALUES(2, 2); +INSERT INTO t2 VALUES(1); +UPDATE t1 SET c2 = 3 WHERE c1 = 1; +COMMIT; + +# wait for the dump thread reach the sync point +--let $wait_condition= select count(*)=1 from information_schema.processlist where state LIKE '%debug sync point%' and command='Binlog Dump' +--source include/wait_condition.inc + +connection slave1; +let $show_statement= SHOW PROCESSLIST; +let $field= Info; +let $condition= = 'UPDATE t1 SET c2 = 3 WHERE c1 = 1'; +source include/wait_show_condition.inc; + +send STOP SLAVE; + +connection slave; +ROLLBACK; + +connection master; + +SET DEBUG_SYNC= 'now SIGNAL signal.continue'; +SET DEBUG_SYNC= 'now WAIT_FOR signal.continued'; + +connection slave; +source include/wait_for_slave_to_stop.inc; + +connection slave1; +reap; + +# Slave has stopped, thence lets make sure that +# we kill the zombie dump threads. Also, make +# sure that we disable the DBUG_EXECUTE_IF +# that would set the dump thread to wait +connection master; +SET @@GLOBAL.debug_dbug = @saved_dbug; +# make sure that there are no zombie threads +--source include/stop_dump_threads.inc + +connection slave1; +# now the dump thread on the master will start +# from a clean slate, i.e. without the +# DBUG_EXECUTE_IF set +source include/start_slave.inc; + +connection master; +DROP TABLE t1, t2; +--source include/rpl_end.inc +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt b/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt new file mode 100644 index 00000000..32c4527a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stop_slave_error-slave.opt @@ -0,0 +1 @@ +--log-error=$MYSQLTEST_VARDIR/tmp/slave_log.err diff --git a/mysql-test/suite/rpl/t/rpl_stop_slave_error.test b/mysql-test/suite/rpl/t/rpl_stop_slave_error.test new file mode 100644 index 00000000..10d7c773 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stop_slave_error.test @@ -0,0 +1,16 @@ +# +# MDEV-8345 STOP SLAVE should not cause an ERROR to be logged to the error log +# +source include/have_binlog_format_mixed.inc; # don't repeat the test three times +source include/master-slave.inc; + +connection master; +sync_slave_with_master; +source include/stop_slave.inc; +let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/slave_log.err; +let SEARCH_PATTERN=Error reading packet from server: Lost connection; +source include/search_pattern_in_file.inc; + +source include/start_slave.inc; +source include/rpl_end.inc; + diff --git a/mysql-test/suite/rpl/t/rpl_strict_password_validation.test b/mysql-test/suite/rpl/t/rpl_strict_password_validation.test new file mode 100644 index 00000000..c4dda1e1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_strict_password_validation.test @@ -0,0 +1,24 @@ +if (!$SIMPLE_PASSWORD_CHECK_SO) { + skip No SIMPLE_PASSWORD_CHECK plugin; +} + +--source include/master-slave.inc + + +--connection slave +install soname "simple_password_check"; +select @@strict_password_validation; + +--connection master +create user foo1 identified by password '11111111111111111111111111111111111111111'; +set password for foo1 = PASSWORD('PLAINtext-password!!99'); +drop user foo1; +--sync_slave_with_master + +--connection slave +--error ER_OPTION_PREVENTS_STATEMENT +create user foo1 identified by password '11111111111111111111111111111111111111111'; + +uninstall plugin simple_password_check; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test new file mode 100644 index 00000000..26255085 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test @@ -0,0 +1 @@ +--source include/rpl_switch_stm_row_mixed.inc diff --git a/mysql-test/suite/rpl/t/rpl_sync-master.opt b/mysql-test/suite/rpl/t/rpl_sync-master.opt new file mode 100644 index 00000000..04b06bfa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sync-master.opt @@ -0,0 +1,2 @@ +--default-storage-engine=MyISAM +--loose-innodb-file-per-table=0 diff --git a/mysql-test/suite/rpl/t/rpl_sync-slave.opt b/mysql-test/suite/rpl/t/rpl_sync-slave.opt new file mode 100644 index 00000000..fc560657 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sync-slave.opt @@ -0,0 +1,2 @@ +--sync-relay-log-info=1 --relay-log-recovery=1 --default-storage-engine=MyISAM --loose-innodb-file-per-table=0 +--skip-core-file diff --git a/mysql-test/suite/rpl/t/rpl_sync.test b/mysql-test/suite/rpl/t/rpl_sync.test new file mode 100644 index 00000000..bdb0d8ec --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_sync.test @@ -0,0 +1,2 @@ +--source include/rpl_sync_test.inc + diff --git a/mysql-test/suite/rpl/t/rpl_table_options.test b/mysql-test/suite/rpl/t/rpl_table_options.test new file mode 100644 index 00000000..335bf8d8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_table_options.test @@ -0,0 +1,38 @@ +--source include/not_windows_embedded.inc +--source include/have_example_plugin.inc +--source include/master-slave.inc + +--replace_regex /\.dll/.so/ +eval install plugin example soname '$HA_EXAMPLE_SO'; +set default_storage_engine=example; + +sync_slave_with_master; +connection master; + +# +# only master has example engine installed, +# the slave will have the table created in myisam, +# that does not have ULL table option. +# but because the table was created by the replication +# slave thread, the table will be created anyway, even if +# the option is unknown. +# +create table t1 (a int not null) ull=12340; +alter table t1 ull=12350; +show create table t1; + +sync_slave_with_master; +connection slave; +show create table t1; +set sql_mode=ignore_bad_table_options; +show create table t1; + +connection master; +drop table t1; +set default_storage_engine=default; +select 1; + +# Cleanup +uninstall plugin example; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temp_table.test b/mysql-test/suite/rpl/t/rpl_temp_table.test new file mode 100644 index 00000000..8b3af5d5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temp_table.test @@ -0,0 +1,85 @@ +# drop table t1 t2 t3 are included int master-slave.inc +# meaningful only in statement-based: + +-- source include/have_binlog_format_mixed_or_statement.inc +-- source include/master-slave.inc + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +create table t2 (n int, PRIMARY KEY(n)); +create temporary table t1 (n int); +create temporary table t3 (n int not null); + +insert into t1 values(1),(2),(3),(100),(25),(26),(200),(300); +--disable_warnings +insert into t2 select * from t1; +--enable_warnings +alter table t3 add primary key(n); + +flush logs; +insert into t3 values (1010); +--disable_warnings +insert into t2 select * from t3; +--enable_warnings + +drop table if exists t3; +insert into t2 values (1012); + +connection master1; +create temporary table t1 (n int); +insert into t1 values (4),(5); +--disable_warnings +insert into t2 select * from t1; +--enable_warnings + +save_master_pos; +disconnect master; + +connection slave; +#add 1 to the saved position, so we will catch drop table on disconnect +#for sure +sync_with_master 1; + +connection master1; +insert into t2 values(61); + +save_master_pos; +disconnect master1; + +connection slave; +#same trick - make sure we catch drop of temporary table on disconnect +sync_with_master 1; + +select * from t2; +select count(*) from t2; +select sum(n) from t2; +show status like 'Slave_open_temp_tables'; + +--echo *** MDEV-8016: Replication aborts on DROP /*!40005 TEMPORARY */ TABLE IF EXISTS *** +connect (master2,localhost,root,,); +INSERT INTO t2 VALUES (2000), (2001); +CREATE FUNCTION f() RETURNS INTEGER RETURN 1; +CREATE TEMPORARY TABLE t3 AS SELECT f() AS col FROM t2; +--let $gtid=`SELECT @@gtid_binlog_pos` +--disconnect master2 +--connection default +# Wait for implicit DROP TEMPORARY TABLE tmp to be binlogged. +--let $wait_condition= SELECT @@gtid_binlog_pos != '$gtid' +--source include/wait_condition.inc + +--sync_slave_with_master + + +# +# Clean up +# +connect (master2,localhost,root,,); +connection master2; +drop table if exists t1,t2; +drop function f; +sync_slave_with_master; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test new file mode 100644 index 00000000..cbbf4c5f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test @@ -0,0 +1,205 @@ +# ==== Purpose ==== +# +# Test that temporary tables are correctly replicated after switching to ROW format in MIX mode. +# This test case will test the condition of the bug#40013. +# The test step is: +# 1: create temp table on connection 'master'; +# 2: switch to ROW format using 'INSERT INTO t1 VALUES (UUID());' +# 3: disconnect 'master' and connect to a new connection 'master1'; +# 4: sync to slave and check the number of temp tables on slave. +# + +source include/have_binlog_format_mixed.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +--echo ==== Initialize ==== + +--connection master + +CREATE TABLE t1 (a CHAR(48)); +CREATE TEMPORARY TABLE t1_tmp1(a INT); +INSERT INTO t1 VALUES (UUID()); + +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--connection master + +disconnect master; +--connection master1 + +# waiting DROP TEMPORARY TABLE event to be written into binlog +let $wait_binlog_event= DROP; +source include/wait_for_binlog_event.inc; + +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--echo ==== Clean up ==== + +--let $rpl_connection_name= master +--let $rpl_server_number= 1 +--source include/rpl_connect.inc +--connection master +DROP TABLE t1; + +sync_slave_with_master; + +# +# BUG#43046: mixed mode switch to row format with temp table lead to wrong +# result +# +# NOTES +# ===== +# +# 1. Temporary tables cannot be logged using the row-based +# format. Thus, once row-based logging is used, all subsequent +# statements using that table are unsafe, and we approximate this +# condition by treating all statements made by that client as +# unsafe until the client no longer holds any temporary tables. +# +# 2. Two different connections can use the same temporary table +# name without conflicting with each other or with an +# existing non-TEMPORARY table of the same name. +# +# DESCRIPTION +# =========== +# +# The test is implemented as follows: +# 1. create regular tables +# 2. create a temporary table t1_tmp: should be logged as statement +# 3. issue an alter table: should be logged as statement +# 4. issue statement that forces switch to RBR +# 5. create another temporary table t2_tmp: should not be logged +# 6. issue alter table on t1_tmp: should not be logged +# 7. drop t1_tmp and regular table on same statement: should log both in +# statement format (but different statements) +# 8. issue deterministic insert: logged as row (because t2_tmp still +# exists). +# 9. drop t2_tmp and issue deterministic statement: should log drop and +# query in statement format (show switch back to STATEMENT format) +# 10. in the end the slave should not have open temp tables. +# + +--source include/rpl_reset.inc +-- connection master + +# action: setup environment +CREATE TABLE t1 (a int) engine=innodb; +CREATE TABLE t2 ( i1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (i1) ); +CREATE TABLE t3 ( i1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (i1) ); +CREATE TRIGGER tr1 AFTER DELETE ON t2 FOR EACH ROW INSERT INTO t3 () VALUES (); + +# assertion: assert that CREATE is logged as STATEMENT +CREATE TEMPORARY TABLE t1_tmp (i1 int); + +# assertion: assert that ALTER TABLE is logged as STATEMENT +ALTER TABLE t1_tmp ADD COLUMN b INT; + +# action: force switch to RBR +INSERT INTO t1 values(1); +INSERT INTO t2 (i1) select * from t1; + +# assertion: assert that t2_tmp will not make into the binlog (RBR logging atm) +CREATE TEMPORARY TABLE t2_tmp (a int); + +# assertion: assert that ALTER TABLE on t1_tmp will not make into the binlog +ALTER TABLE t1_tmp ADD COLUMN c INT; + +-- echo ### assertion: assert that there is one open temp table on slave +-- sync_slave_with_master +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +-- connection master + +# assertion: assert that both drops are logged +DROP TABLE t1_tmp, t2; + +# assertion: assert that statement is logged as row (master still has one +# opened temporary table - t2_tmp. +INSERT INTO t1 VALUES (1); + +# assertion: assert that DROP TABLE *is* logged despite CREATE is not. +DROP TEMPORARY TABLE t2_tmp; + +# assertion: assert that statement is now logged as STMT (mixed mode switches +# back to STATEMENT). +INSERT INTO t1 VALUES (2); + +-- sync_slave_with_master + +-- echo ### assertion: assert that slave has no temporary tables opened +SHOW STATUS LIKE 'Slave_open_temp_tables'; + +-- connection master + +# action: drop remaining tables +DROP TABLE t3, t1; + +-- sync_slave_with_master + +-- source include/show_binlog_events.inc + +--echo +--echo # Bug#55478 Row events wrongly apply on the temporary table of the same name +--echo # ========================================================================== +connection master; + +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +--echo # The statement should be binlogged +CREATE TEMPORARY TABLE t1(c1 INT) ENGINE=InnoDB; + +--echo +--echo # Case 1: CREATE TABLE t1 ... SELECT +--echo # ---------------------------------- +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +--echo +--echo # The statement generates row events on t1. And the rows events should +--echo # be inserted into the base table on slave. +CREATE TABLE t1 ENGINE=MyISAM SELECT rand(); + +source include/show_binlog_events.inc; +let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); + +--echo +--echo # Case 2: DROP TEMPORARY TABLE in a transacation +--echo # ---------------------------------------------- +--echo + +BEGIN; +DROP TEMPORARY TABLE t1; + +# The patch for BUG#55478 fixed the problem only on RBR. The problem on SBR +# will be fixed by the patch for bug#55709. So This statement cannot be +# executed until Bug#55709 is fixed +# +# INSERT INTO t1 VALUES(1); + +--echo # The rows event will binlogged after 'INSERT INTO t1 VALUES(1)' +--disable_warnings +INSERT IGNORE INTO t1 VALUES(uuid()+0); +--enable_warnings +COMMIT; + +source include/show_binlog_events.inc; + +--sync_slave_with_master + +--echo # Compare the base table. +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + +--echo +connection master; +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test b/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test new file mode 100644 index 00000000..d976ae37 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_default_to_default.test @@ -0,0 +1 @@ +--source include/rpl_temporal_format_default_to_default.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test new file mode 100644 index 00000000..058ad017 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mariadb53.test @@ -0,0 +1,4 @@ +--let $force_master_mysql56_temporal_format=false; +--let $force_slave_mysql56_temporal_format=false; + +--source rpl_temporal_format_default_to_default.test diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test new file mode 100644 index 00000000..547b0831 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56.test @@ -0,0 +1,14 @@ +# +# MariaDB-5.3 fractional temporal types do not store metadata +# when running with --binlog-format=row, thus can replicate +# only into a field with exactly the same data type and format. +# +# Skip when running with --binlog-format=row. +# But mixed and statement formats should work without problems. +# +-- source include/have_binlog_format_mixed_or_statement.inc + +--let $force_master_mysql56_temporal_format=false; +--let $force_slave_mysql56_temporal_format=true; + +--source rpl_temporal_format_default_to_default.test diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test new file mode 100644 index 00000000..511bdc15 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mariadb53_to_mysql56_dst.test @@ -0,0 +1,37 @@ +# +# MDEV-12672 Replicated TIMESTAMP fields given wrong value near DST change +# +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +connection slave; +set global time_zone='Europe/Moscow'; +set time_zone='UTC'; +stop slave; +start slave; + +connection master; +set global mysql56_temporal_format=false; +set global time_zone='Europe/Moscow'; +set time_zone='UTC'; + +create table t1 (pk int primary key, t timestamp not null); +set timestamp = 1288477526; +insert into t1 values (1,null); +set timestamp = 1288481126; +insert into t1 values (2,null); + +sync_slave_with_master; + +select pk, t, unix_timestamp(t) from t1; +set time_zone=default; +select pk, t, unix_timestamp(t) from t1; + +set global time_zone=default; + +connection master; +drop table t1; +set global time_zone=default; +set global mysql56_temporal_format=default; + +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test new file mode 100644 index 00000000..dbee9f05 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mariadb53.test @@ -0,0 +1,4 @@ +--let $force_master_mysql56_temporal_format=true; +--let $force_slave_mysql56_temporal_format=false; + +--source rpl_temporal_format_default_to_default.test diff --git a/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test new file mode 100644 index 00000000..9c7994b6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_format_mysql56_to_mysql56.test @@ -0,0 +1,4 @@ +--let $force_master_mysql56_temporal_format=true; +--let $force_slave_mysql56_temporal_format=true; + +--source rpl_temporal_format_default_to_default.test diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test new file mode 100644 index 00000000..f21f125b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56.test @@ -0,0 +1,48 @@ +--source include/master-slave.inc + +connection master; +SET TIME_ZONE='+00:00'; +let $MYSQLD_MASTER_DATADIR= `select @@datadir`; + +connection slave; +SET TIME_ZONE='+00:00'; +let $MYSQLD_SLAVE_DATADIR= `select @@datadir`; + +--copy_file std_data/mysql56time.frm $MYSQLD_MASTER_DATADIR/test/mysql56time.frm +--copy_file std_data/mysql56time.MYD $MYSQLD_MASTER_DATADIR/test/mysql56time.MYD +--copy_file std_data/mysql56time.MYI $MYSQLD_MASTER_DATADIR/test/mysql56time.MYI +--copy_file std_data/mysql56time.frm $MYSQLD_SLAVE_DATADIR/test/mysql56time.frm +--copy_file std_data/mysql56time.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYD +--copy_file std_data/mysql56time.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56time.MYI + +--copy_file std_data/mysql56datetime.frm $MYSQLD_MASTER_DATADIR/test/mysql56datetime.frm +--copy_file std_data/mysql56datetime.MYD $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYD +--copy_file std_data/mysql56datetime.MYI $MYSQLD_MASTER_DATADIR/test/mysql56datetime.MYI +--copy_file std_data/mysql56datetime.frm $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.frm +--copy_file std_data/mysql56datetime.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYD +--copy_file std_data/mysql56datetime.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56datetime.MYI + +--copy_file std_data/mysql56timestamp.frm $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.frm +--copy_file std_data/mysql56timestamp.MYD $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYD +--copy_file std_data/mysql56timestamp.MYI $MYSQLD_MASTER_DATADIR/test/mysql56timestamp.MYI +--copy_file std_data/mysql56timestamp.frm $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.frm +--copy_file std_data/mysql56timestamp.MYD $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYD +--copy_file std_data/mysql56timestamp.MYI $MYSQLD_SLAVE_DATADIR/test/mysql56timestamp.MYI + +connection master; +INSERT INTO mysql56time VALUES ('01:01:01','01:01:01.1','01:01:01.11','01:01:01.111','01:01:01.1111','01:01:01.11111','01:01:01.111111'); +INSERT INTO mysql56datetime VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111'); +INSERT INTO mysql56timestamp VALUES ('2001-01-01 01:01:01','2001-01-01 01:01:01.1','2001-01-01 01:01:01.11','2001-01-01 01:01:01.111','2001-01-01 01:01:01.1111','2001-01-01 01:01:01.11111','2001-01-01 01:01:01.111111'); +sync_slave_with_master; + +connection slave; +--query_vertical SELECT * FROM mysql56time +--query_vertical SELECT * FROM mysql56datetime +--query_vertical SELECT * FROM mysql56timestamp + +connection master; +DROP TABLE mysql56time; +DROP TABLE mysql56datetime; +DROP TABLE mysql56timestamp; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test new file mode 100644 index 00000000..efbff934 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb.test @@ -0,0 +1,55 @@ +--source include/master-slave.inc + +if ($force_slave_mysql56_temporal_format) +{ + connection slave; + eval SET @@global.mysql56_temporal_format=$force_slave_mysql56_temporal_format; + connection master; +} + + +--echo # +--echo # Testing replication from MariaDB-10.0 master +--echo # started over MySQL-5.6 data directory +--echo # to MariaDB-10.0 slave running with natively created tables +--echo # + +connection master; +SET TIME_ZONE='+00:00'; +let $MYSQLD_MASTER_DATADIR= `select @@datadir`; + +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.frm +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYD +--copy_file std_data/temporal_upgrade/mysql050614_temporal0.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal0.MYI + +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.frm $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.frm +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYD $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYD +--copy_file std_data/temporal_upgrade/mysql050614_temporal1.MYI $MYSQLD_MASTER_DATADIR/test/mysql050614_temporal1.MYI +SHOW CREATE TABLE mysql050614_temporal0; +SHOW CREATE TABLE mysql050614_temporal1; + +connection slave; +SELECT @@mysql56_temporal_format; +SET TIME_ZONE='+00:00'; +CREATE TABLE mysql050614_temporal0 (a time(0), b datetime(0), c timestamp(0)) engine=myisam; +CREATE TABLE mysql050614_temporal1 (a time(1), b datetime(1), c timestamp(1)) engine=myisam; + +connection master; +INSERT INTO mysql050614_temporal0 VALUES ('00:00:02','2001-01-01 00:00:02','2001-01-01 00:00:02'); +INSERT INTO mysql050614_temporal1 VALUES ('00:00:02.1','2001-01-01 00:00:02.2','2001-01-01 00:00:02.3'); +SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME LIKE 'mysql050614_temporal%' ORDER BY TABLE_NAME; +sync_slave_with_master; + +connection slave; +SELECT * FROM mysql050614_temporal0; +SELECT * FROM mysql050614_temporal1; +SELECT TABLE_NAME, TABLE_ROWS, AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_NAME LIKE 'mysql050614_temporal%' ORDER BY TABLE_NAME; +SET @@global.mysql56_temporal_format=DEFAULT; + +connection master; +DROP TABLE mysql050614_temporal0; +DROP TABLE mysql050614_temporal1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test new file mode 100644 index 00000000..435dad57 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_mysql56_to_mariadb53.test @@ -0,0 +1,2 @@ +--let $force_slave_mysql56_temporal_format=false; +--source rpl_temporal_mysql56_to_mariadb.test diff --git a/mysql-test/suite/rpl/t/rpl_temporal_round.test b/mysql-test/suite/rpl/t/rpl_temporal_round.test new file mode 100644 index 00000000..c13c18bd --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_round.test @@ -0,0 +1,35 @@ +--source include/master-slave.inc + +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); + +CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t2 (id SERIAL, a DATETIME(4)); +INSERT INTO t2 (a) VALUES (now(6)); +INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t3 (id SERIAL, a TIME(4)); +INSERT INTO t3 (a) VALUES (now(6)); +INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999'); + +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +sync_slave_with_master; +connection slave; +SET time_zone='+00:00'; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporary.test b/mysql-test/suite/rpl/t/rpl_temporary.test new file mode 100644 index 00000000..729f275b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary.test @@ -0,0 +1,416 @@ +# Test need anonymous user when connection are made as "zedjzlcsjhd" +# But we only need it on the master, not the slave. +SET sql_log_bin = 0; +source include/add_anonymous_users.inc; +SET sql_log_bin = 1; + +-- source include/master-slave.inc + +# Clean up old slave's binlogs. +# The slave is started with --log-slave-updates +# and this test does SHOW BINLOG EVENTS on the slave's +# binlog. But previous tests can influence the current test's +# binlog (e.g. a temporary table in the previous test has not +# been explicitly deleted, or it has but the slave hasn't had +# enough time to catch it before STOP SLAVE, +# and at the beginning of the current +# test the slave immediately writes DROP TEMPORARY TABLE this_old_table). +# We wait for the slave to have written all he wants to the binlog +# (otherwise RESET MASTER may come too early). +save_master_pos; +connection slave; + +sync_with_master; +reset master; + +# ################################################################## +# BUG#41725: slave crashes when inserting into temporary table after +# stop/start slave +# +# This test checks that both reported issues (assertion failure and +# crash) go away. It is implemented as follows: +# +# case 1: assertion failure +# i) create and insert into temporary table on master +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master another value +# v) sync slave with master +# +# +# case 2: crash (SIGSEV) +# i) create and insert into temporary table on master (insert +# produces warnings) +# ii) sync slave with master +# iii) stop and restart slave +# iv) insert into master more values +# v) sync slave with master + +# case 1: Assertion in Field_string::store() failed because current +# thread reference differed from table->in_use after slave +# restart + +connection master; + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; + +CREATE TEMPORARY TABLE t1 (a char(1)); +INSERT INTO t1 VALUES ('a'); +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT INTO t1 VALUES ('b'); +sync_slave_with_master; + +# case 2: crash on sp_rcontext::find_handler because it used +# reference to invalid THD object after slave restart + +connection master; + +disable_warnings; +DROP TABLE IF EXISTS t1; +enable_warnings; +CREATE TEMPORARY TABLE `t1`(`a` tinyint,`b` char(1))engine=myisam; +INSERT IGNORE INTO `t1` set `a`=128,`b`='128'; + +sync_slave_with_master; + +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; +INSERT IGNORE INTO `t1` set `a`=128,`b`='128'; +sync_slave_with_master; + +# cleanup + +connection master; +DROP TABLE t1; +sync_slave_with_master; + +connection master; + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +# We want to connect as an unprivileged user. But if we use user="" then this +# will pick the Unix login, which will cause problems if you're running the test +# as root. +connect (con3,localhost,zedjzlcsjhd,,); + +# We are going to use SET PSEUDO_THREAD_ID in this test; +# check that it requires the SUPER privilege. + +connection con3; +SET @save_select_limit=@@session.sql_select_limit; +--error 1227 +SET @@session.sql_select_limit=10, @@session.pseudo_thread_id=100; +SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed +# While we are here we also test that SQL_LOG_BIN can't be set +--error 1227 +SET @@session.sql_select_limit=10, @@session.sql_log_bin=0; +SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed +# Now as root, to be sure it works +connection con2; +SET @save_conn_id= connection_id(); +SET @@session.pseudo_thread_id=100; +SET @@session.pseudo_thread_id=connection_id(); +SET @@session.pseudo_thread_id=@save_conn_id; +SET @@session.sql_log_bin=0; +SET @@session.sql_log_bin=1; + +connection con3; +let $VERSION=`select version()`; + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +create table t1(f int); +create table t2(f int); +insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +# Auxiliary select (We want that all rows are in the table) +SELECT COUNT(*) FROM t1; + +connection con1; +create temporary table t3(f int); +--disable_warnings +insert into t3 select * from t1 where f<6; +--enable_warnings +let $wait_condition= SELECT COUNT(*) = 5 FROM t3; +--source include/wait_condition.inc + +connection con2; +create temporary table t3(f int); + +connection con1; +--disable_warnings +insert into t2 select count(*) from t3; +--enable_warnings +let $wait_condition= SELECT COUNT(*) = 1 FROM t2; +--source include/wait_condition.inc + +connection con2; +--disable_warnings +insert into t3 select * from t1 where f>=4; +--enable_warnings +let $wait_condition= SELECT COUNT(*) = 7 FROM t3; +--source include/wait_condition.inc + +connection con1; +drop temporary table t3; + +connection con2; +--disable_warnings +insert into t2 select count(*) from t3; +--enable_warnings +drop temporary table t3; + +select * from t2 ORDER BY f; + +# Commented out 8/30/2005 to make compatable with both sbr and rbr +#--replace_result $VERSION VERSION +#--replace_column 2 # 5 # +#show binlog events; + +drop table t1, t2; + +use test; +SET TIMESTAMP=1040323920; +create table t1(f int); +SET TIMESTAMP=1040323931; +create table t2(f int); +SET TIMESTAMP=1040323938; +insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +SET TIMESTAMP=1040323945; +SET @@session.pseudo_thread_id=1; +create temporary table t3(f int); +SET TIMESTAMP=1040323952; +SET @@session.pseudo_thread_id=1; +--disable_warnings +insert into t3 select * from t1 where f<6; +--enable_warnings +SET TIMESTAMP=1040324145; +SET @@session.pseudo_thread_id=2; +create temporary table t3(f int); +SET TIMESTAMP=1040324186; +SET @@session.pseudo_thread_id=1; +--disable_warnings +insert into t2 select count(*) from t3; +--enable_warnings +SET TIMESTAMP=1040324200; +SET @@session.pseudo_thread_id=2; +--disable_warnings +insert into t3 select * from t1 where f>=4; +--enable_warnings +SET TIMESTAMP=1040324211; +SET @@session.pseudo_thread_id=1; +drop temporary table t3; +SET TIMESTAMP=1040324219; +SET @@session.pseudo_thread_id=2; +--disable_warnings +insert into t2 select count(*) from t3; +--enable_warnings +SET TIMESTAMP=1040324224; +SET @@session.pseudo_thread_id=2; +drop temporary table t3; + +select * from t2 ORDER BY f; +drop table t1,t2; + +# Create last a temporary table that is not dropped at end to ensure that we +# don't get any memory leaks for this + +create temporary table t3 (f int); +sync_slave_with_master; + +# The server will now close done + +# +# Bug#17284 erroneous temp table cleanup on slave +# The test targets at verifying that reconnected slave +# retained the former session's temporary tables +# +connection master; +create temporary table t4 (f int); +create table t5 (f int); +sync_slave_with_master; +# connection slave +stop slave; # to prepare for reconnecting w/o waiting for timeout +connection master; +--disable_warnings +insert into t5 select * from t4; +--enable_warnings +save_master_pos; + +connection slave; +start slave; +sync_with_master; +select * from t5 /* must be 1 after reconnection */; + +connection master; +drop temporary table t4; +drop table t5; + +# +# BUG#17263 incorrect generation DROP temp tables +# Temporary tables of connection are dropped in batches +# where a batch correspond to pseudo_thread_id +# value was set up at the moment of temp table creation +# +connection con1; +set @@session.pseudo_thread_id=100; +create temporary table t101 (id int); +create temporary table t102 (id int); +set @@session.pseudo_thread_id=200; +create temporary table t201 (id int); +create temporary table `t``201` (id int); +# emulate internal temp table not to come to binlog +create temporary table `#sql_not_user_table202` (id int); +set @@session.pseudo_thread_id=300; +create temporary table t301 (id int); +create temporary table t302 (id int); +create temporary table `#sql_not_user_table303` (id int); +disconnect con1; + +#now do something to show that slave is ok after DROP temp tables +connection master; +create table t1(f int); +insert into t1 values (1); + +sync_slave_with_master; +#connection slave; +select * from t1 /* must be 1 */; + +connection master; +drop table t1; + +# +#14157: utf8 encoding in binlog without set character_set_client +# +--write_file $MYSQLTEST_VARDIR/tmp/bug14157.sql +create table t1 (a int); +set names latin1; +create temporary table `äöüÄÖÜ` (a int); +insert into `äöüÄÖÜ` values (1); +insert into t1 select * from `äöüÄÖÜ` +EOF +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test < $MYSQLTEST_VARDIR/tmp/bug14157.sql + +sync_slave_with_master; +#connection slave; +select * from t1; + +connection master; +drop table t1; +--remove_file $MYSQLTEST_VARDIR/tmp/bug14157.sql + +--sync_slave_with_master + +# Delete the anonymous users. +--source include/stop_slave.inc +source include/delete_anonymous_users.inc; +--connection master +source include/delete_anonymous_users.inc; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + + +# +# Bug#43748: crash when non-super user tries to kill the replication threads +# + +--echo -- Bug#43748 + +--echo -- make a user on the slave that can list but not kill system threads. +connection slave; + +FLUSH PRIVILEGES; +GRANT USAGE ON *.* TO user43748@127.0.0.1 IDENTIFIED BY 'meow'; +GRANT PROCESS ON *.* TO user43748@127.0.0.1; + +--echo -- try to KILL system-thread as that non-privileged user (on slave). +connect (cont43748,127.0.0.1,user43748,meow,test,$SLAVE_MYPORT,); +connection cont43748; + +SELECT id INTO @id FROM information_schema.processlist WHERE user='system user' LIMIT 1; + +--error ER_KILL_DENIED_ERROR,ER_NO_SUCH_THREAD +KILL @id; + +disconnect cont43748; + +--echo -- throw out test-user on slave. +connection slave; + +DROP USER user43748@127.0.0.1; + +--echo # +--echo # MDEV-10216: Assertion `strcmp(share->unique_file_name,filename) || +--echo # share->last_version' failed in myisam/mi_open.c:67: test_if_reopen +--echo # + +connection master; +CREATE TEMPORARY TABLE t1(i INT PRIMARY KEY) ENGINE=MYISAM; +INSERT INTO t1 VALUES(1); +SELECT COUNT(*)=1 FROM t1; + +ALTER TABLE t1 RENAME t2; +SELECT COUNT(*)=1 FROM t2; +ALTER TABLE t2 RENAME t1; + +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; + +# LOCK TABLES is ignored for temporary tables. +LOCK TABLES t1 WRITE; +ALTER TABLE t1 RENAME t2; +SELECT COUNT(*)=1 FROM t2; +ALTER TABLE t2 RENAME t1; +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; +UNLOCK TABLES; + +LOCK TABLES t1 READ; +ALTER TABLE t1 RENAME t2; +SELECT COUNT(*)=1 FROM t2; +ALTER TABLE t2 RENAME t1; +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; +UNLOCK TABLES; + +FLUSH TABLES WITH READ LOCK; +ALTER TABLE t1 RENAME t2; +SELECT COUNT(*)=1 FROM t2; +ALTER TABLE t2 RENAME t1; +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; +UNLOCK TABLES; + +ALTER TABLE t1 RENAME t2, LOCK SHARED; +ALTER TABLE t2 RENAME t1, LOCK EXCLUSIVE; + +DROP TABLE t1; + +--echo # +--echo # MDEV-10320: NO-OP ALTER TABLE on temporary tables getting logged +--echo # under row binlog format +--echo # +connection master; +CREATE TEMPORARY TABLE t1(i INT PRIMARY KEY) ENGINE=MYISAM; +ALTER TABLE t1; +ALTER TABLE t1 ADD COLUMN IF NOT EXISTS I INT; +DROP TABLE t1; + +--echo End of 5.1 tests +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporary_error2.test b/mysql-test/suite/rpl/t/rpl_temporary_error2.test new file mode 100644 index 00000000..49194c5d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary_error2.test @@ -0,0 +1,79 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); + +--echo *** Provoke a deadlock on the slave, check that transaction retry succeeds. *** +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5); + +--sync_slave_with_master +SELECT * FROM t1 ORDER BY a; +# Use MyISAM for t2 on the slave, so we have a way to see how far the +# slave replication thread has proceeded in the transaction. +SET sql_log_bin=0; +ALTER TABLE t2 ENGINE=MyISAM; +SET sql_log_bin=1; +let $old_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); + +# Setup a separate connection that can deadlock with the replication thread. +# Docs say that InnoDB will try to roll back the smaller transaction. So +# let us make this transaction a big one, so the one in the replication +# thread will be selected for rollback and retry. +--connect (con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,) +--connection con_temp1 +BEGIN; +UPDATE t1 SET b=2 WHERE a=4; +--disable_query_log +--let $count=200 +while ($count) +{ + eval INSERT INTO t1(a) VALUES ($count + 10); + dec $count; +} +--enable_query_log +# Note that InnoDB also (undocumented?) tries to avoid rolling back a +# "transaction" that modified non-transactional tables. So be sure to also +# touch the MyISAM table in this transaction. +INSERT INTO t2 VALUES (2); +DELETE FROM t2 WHERE a=2; + +# Create the transaction that should participate in the deadlock on the slave. +--connection master +BEGIN; +UPDATE t1 SET b=1 WHERE a=2; +INSERT INTO t2 VALUES (1); +UPDATE t1 SET b=1 WHERE a=4; +COMMIT; +--save_master_pos + +--connection slave +# Wait until replication thread has gone to wait on the a=4 row lock. +--let $wait_condition= SELECT COUNT(*) = 1 FROM t2 WHERE a=1 +--source include/wait_condition.inc + +# Now provoke the deadlock by waiting on the a=2 row lock while the +# other thread is waiting for our a=4 row lock. +--connection con_temp1 +UPDATE t1 SET b=2 WHERE a=2; +SELECT * FROM t1 WHERE a<10 ORDER BY a; +ROLLBACK; + +--connection slave +--sync_with_master +SELECT * FROM t1 ORDER BY a; +--echo * There will be two rows in t2 due to the retry. +SELECT * FROM t2 ORDER BY a; +let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); +--disable_query_log +eval SELECT $new_retry - $old_retry AS retries; +--enable_query_log +--let $status_items= Last_SQL_Errno, Last_SQL_Error +--source include/show_slave_status.inc + +--connection master +DROP TABLE t1; +DROP TABLE t2; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt b/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt new file mode 100644 index 00000000..5c5164c6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary_errors-slave.opt @@ -0,0 +1 @@ +--loose-debug-dbug="+d,all_errors_are_temporary_errors" --slave-transaction-retries=2 diff --git a/mysql-test/suite/rpl/t/rpl_temporary_errors.test b/mysql-test/suite/rpl/t/rpl_temporary_errors.test new file mode 100644 index 00000000..85e16afa --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary_errors.test @@ -0,0 +1,116 @@ +source include/have_binlog_format_row.inc; +source include/have_innodb.inc; +source include/master-slave.inc; + +call mtr.add_suppression("Deadlock found"); +call mtr.add_suppression("Can't find record in 't.'"); + +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=innodb; +INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4); +sync_slave_with_master; +SHOW STATUS LIKE 'Slave_retried_transactions'; +# since bug#31552/31609 idempotency is not default any longer. In order +# the following UPDATE t1 to pass the mode is switched temprorarily +set @@global.slave_exec_mode= 'IDEMPOTENT'; +UPDATE t1 SET a = 5, b = 47 WHERE a = 1; +SELECT * FROM t1 ORDER BY a; +connection master; +UPDATE t1 SET a = 5, b = 5 WHERE a = 1; +SELECT * FROM t1 ORDER BY a; +#SHOW BINLOG EVENTS; +sync_slave_with_master; +set @@global.slave_exec_mode= default; +SHOW STATUS LIKE 'Slave_retried_transactions'; +SELECT * FROM t1 ORDER BY a; +source include/check_slave_is_running.inc; + +connection slave; +call mtr.add_suppression("Slave SQL.*Could not execute Update_rows event on table test.t1"); +call mtr.add_suppression("Slave SQL for channel '': worker thread retried transaction"); +call mtr.add_suppression("The slave coordinator and worker threads are stopped"); +# +# Bug#24764800 REPLICATION FAILING ON SLAVE WITH XAER_RMFAIL ERROR +# +# Verify that a temporary failing replicated xa transaction completes +# upon slave applier restart after previous +# @@global.slave_transaction_retries number of retries in vain. +# +connection slave; + +set @save_innodb_lock_wait_timeout=@@global.innodb_lock_wait_timeout; +set @save_slave_transaction_retries=@@global.slave_transaction_retries; + +# Slave applier parameters for the failed retry +set @@global.innodb_lock_wait_timeout=1; +set @@global.slave_transaction_retries=2; +--source include/restart_slave_sql.inc + +# Temporary error implement: a record is blocked by slave local trx +connection slave1; +BEGIN; +INSERT INTO t1 SET a = 6, b = 7; + +connection master; +INSERT INTO t1 SET a = 99, b = 99; # slave applier warm up trx +XA START 'xa1'; +INSERT INTO t1 SET a = 6, b = 6; # this record eventually must be found on slave +XA END 'xa1'; +XA PREPARE 'xa1'; + +connection slave; +# convert_error(ER_LOCK_WAIT_TIMEOUT) +--let $err_timeout= 1205 +# convert_error(ER_LOCK_DEADLOCK) +--let $err_deadlock= 1213 +--let $slave_sql_errno=$err_deadlock,$err_timeout +--let $show_slave_sql_error= +--source include/wait_for_slave_sql_error.inc + +# b. Slave applier parameters for successful retry after restart +set @@global.innodb_lock_wait_timeout=1; +set @@global.slave_transaction_retries=100; + +--source include/restart_slave_sql.inc + +--let $last_retries= query_get_value(SHOW GLOBAL STATUS LIKE 'Slave_retried_transactions', Value, 1) +--let $status_type=GLOBAL +--let $status_var=Slave_retried_transactions +--let $status_var_value=`SELECT 1 + $last_retries` +--let $$status_var_comparsion= > +--source include/wait_for_status_var.inc + +# Release the record after just one retry +connection slave1; +ROLLBACK; + +connection master; +XA COMMIT 'xa1'; + +--source include/sync_slave_sql_with_master.inc + +# Proof of correctness: the committed XA is on the slave +connection slave; +--let $assert_text=XA transaction record must be in the table +--let $assert_cond=count(*)=1 FROM t1 WHERE a=6 AND b=6 +--source include/assert.inc + +# Bug#24764800 cleanup: +set @@global.innodb_lock_wait_timeout=@save_innodb_lock_wait_timeout; +set @@global.slave_transaction_retries= @save_slave_transaction_retries; + +# +# Total cleanup: +# +connection master; +DROP TABLE t1; +--sync_slave_with_master +--connection master + +# We must wait for the slave to stop. +# Otherwise the warnings in the error log about deadlock may be written to +# the error log only during shutdown, and currently the suppression of +# "Deadlock found" set in this test case is not effective during server +# shutdown. + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_test_framework.cnf b/mysql-test/suite/rpl/t/rpl_test_framework.cnf new file mode 100644 index 00000000..755e3622 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_test_framework.cnf @@ -0,0 +1,28 @@ +!include ../my.cnf +[mysqld.1] +log-slave-updates +[mysqld.2] +log-slave-updates +[mysqld.3] +log-slave-updates +[mysqld.4] +log-slave-updates +[mysqld.5] +log-slave-updates +[mysqld.6] +log-slave-updates +[mysqld.7] +log-slave-updates +[mysqld.8] +log-slave-updates +[mysqld.9] +log-slave-updates + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYPORT_4= @mysqld.4.port +SERVER_MYPORT_5= @mysqld.5.port +SERVER_MYPORT_6= @mysqld.6.port +SERVER_MYPORT_7= @mysqld.7.port +SERVER_MYPORT_8= @mysqld.8.port +SERVER_MYPORT_9= @mysqld.9.port diff --git a/mysql-test/suite/rpl/t/rpl_test_framework.test b/mysql-test/suite/rpl/t/rpl_test_framework.test new file mode 100644 index 00000000..cf559072 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_test_framework.test @@ -0,0 +1,143 @@ +# ==== Purpose ==== +# +# Test that the sync chain generated by +# include/rpl_change_topology.inc (sourced from include/rpl_init.inc) +# is correct. +# +# We test a number of different topologies. Each topology is tested +# in include/rpl_test_framework.inc. See +# include/rpl_test_framework.inc for details on how the sync +# chain is tested. +# +# ==== Related bugs ==== +# +# BUG#49978: Replication tests don't clean up replication state at the end + + +# We only need to execute this test once. Also, we rely on 'DELETE +# FROM t1' to remove rows in slave tables that don't exist in master +# tables (see include/rpl_test_framework.inc for details). +--source include/have_binlog_format_statement.inc + + +--echo ==== Create t1 on all servers. ==== +if ($mtr_supports_more_than_10_servers) +{ + --let $rpl_server_count= 15 + --let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15 +} +if (!$mtr_supports_more_than_10_servers) +{ + --let $rpl_server_count= 9 + --let $rpl_topology= 1->2->3->4->5->6->7->8->9 +} +--source include/rpl_init.inc +CREATE TABLE t1 (a INT); +--source include/rpl_end.inc + +# Initialize $next_number before first call to +# include/rpl_test_framework.text +--let $next_number= 0 + + +--echo ==== Test 3-server topologies ==== + +--let $rpl_server_count= 3 + +--let $rpl_topology= 1 -> 2 +--let $masters= 1,3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 2 -> 3 +--let $masters= 1,2 +--source include/rpl_test_framework.inc + +--let $rpl_topology= none +--let $masters= 1,2,3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->2, 2->1 +--let $masters= 1,3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->2->1 +--let $masters= 2,3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 2->1->2 +--let $masters= 1,3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->2->3 +--let $masters= 1 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 2->3->2->1 +--let $masters= 3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->2,2->3,3->1 +--let $masters= 3 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->3->2->1 +--let $masters= 3 +--source include/rpl_test_framework.inc + + +--echo ==== Test 6-server topologies ==== + +--let $rpl_server_count= 6 + +--let $rpl_topology= 1->2->3->4->1->5->6 +--let $masters= 1 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 3->4->5->6->3->1->2 +--let $masters= 4 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 6->5->4->3->2->1 +--let $masters= 6 +--source include/rpl_test_framework.inc + +--let $rpl_topology= 1->2->3->1,4->5->6 +--let $masters= 3,4 +--source include/rpl_test_framework.inc + + +--echo ==== Test 9-server topology ==== + +--let $rpl_server_count= 9 + +--let $rpl_topology= 1->2, 2->3, 3->4, 4->5, 5->1, 1->6, 6->7, 6->8, 8->9 +--let $masters= 2 +--source include/rpl_test_framework.inc + +if ($mtr_supports_more_than_10_servers) { +--echo ==== Test 15-server topologies ==== + +--let $rpl_server_count= 15 + +--let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15->1 +--let $masters= 2 +--source include/rpl_test_framework.inc + +# This is a binary tree +--let $rpl_topology= 1->2->4->8,1->3->6->12,2->5->10,3->7->14,4->9,5->11,6->13,7->15 +--let $masters= 1 +--source include/rpl_test_framework.inc +} + +--echo ==== Clean up ==== + +if ($mtr_supports_more_than_10_servers) { + --let $rpl_topology= 1->2->3->4->5->6->7->8->9->10->11->12->13->14->15 +} +if (!$mtr_supports_more_than_10_servers) { + --let $rpl_topology= 1->2->3->4->5->6->7->8->9 +} +--source include/rpl_init.inc +--connection server_1 +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_timezone-master.opt b/mysql-test/suite/rpl/t/rpl_timezone-master.opt new file mode 100644 index 00000000..8e43bfbb --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_timezone-master.opt @@ -0,0 +1 @@ +--default-time-zone=Europe/Moscow diff --git a/mysql-test/suite/rpl/t/rpl_timezone-slave.opt b/mysql-test/suite/rpl/t/rpl_timezone-slave.opt new file mode 100644 index 00000000..191182c3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_timezone-slave.opt @@ -0,0 +1 @@ +--default-time-zone=Japan diff --git a/mysql-test/suite/rpl/t/rpl_timezone.test b/mysql-test/suite/rpl/t/rpl_timezone.test new file mode 100644 index 00000000..4b5778ca --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_timezone.test @@ -0,0 +1,211 @@ +####################################### +# Change Author: JBM +# Change Date: 2006-01-17 +# Change: Added order by +####################################### +# Test of replication of time zones. +###################################### +# There is currently some bug possibly in prepared statements (this +# test fails with --ps-protocol): sys_var_thd_time_zone::value_ptr() +# is called only at prepare time, not at execution time. So, +# thd->time_zone_used is not equal to 1 (it is back to 0, because of +# reset_thd_for_next_command called at execution time), so the +# timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem +# and possibly Konstantin). + +source include/master-slave.inc; + +--disable_query_log +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +--enable_query_log + +--disable_ps_protocol + +# Save original timezone +set @my_time_zone= @@global.time_zone; + +# Some preparations +let $VERSION=`select version()`; +set timestamp=100000000; # for fixed output of mysqlbinlog +create table t1 (t timestamp, n int not null auto_increment, PRIMARY KEY(n)); +create table t2 (t char(32), n int not null auto_increment, PRIMARY KEY(n)); + +connection slave; +select @@time_zone; +#set time_zone='UTC'; +#select @@time_zone; +# +# Let us check how well replication works when we are saving datetime +# value in TIMESTAMP field. +# +connection master; +select @@time_zone; +#set time_zone='UTC'; +#select @@time_zone; +insert into t1 values ('20050101000000', NULL), ('20050611093902',NULL); +insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); +SELECT * FROM t1 ORDER BY n; +sync_slave_with_master; +#set time_zone='UTC'; +SELECT * FROM t1 ORDER BY n; + +# Let us check also that setting of time_zone back to default also works +# well +connection master; +delete from t1; +set time_zone='Europe/Moscow'; +insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); +SELECT * FROM t1 ORDER BY n; +sync_slave_with_master; +set time_zone='Europe/Moscow'; +SELECT * FROM t1 ORDER BY n; +connection master; +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Comment out the exec of the binlog so test works for both SBR and RBR +#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +#--exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000001 + +# Let us check with LOAD DATA INFILE +# (we do it after mysqlbinlog because the temp files names are not constant) +connection master; +delete from t1; +set time_zone='UTC'; +load data infile '../../std_data/rpl_timezone2.dat' ignore into table t1; +SELECT * FROM t1 ORDER BY n; +sync_slave_with_master; +set time_zone='UTC'; +SELECT * FROM t1 ORDER BY n; +set time_zone='Europe/Moscow'; + +# Put back values of before the LOAD +connection master; +set time_zone='Europe/Moscow'; +delete from t1; +insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); + +# +# Now let us check how well we replicate statments reading TIMESTAMP fields +# (We should see the same data on master and on slave but it should differ +# from originally inserted) +# +set time_zone='MET'; +--disable_warnings ONCE +insert into t2 (select * from t1); +SELECT * FROM t1 ORDER BY n; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY n; + +# +# Now let us check how well we replicate various CURRENT_* functions +# +connection master; +delete from t2; +set timestamp=1000072000; +insert into t2 values (current_timestamp,NULL), (current_date,NULL), (current_time,NULL); +sync_slave_with_master; +SELECT * FROM t2 ORDER BY n; + +# +# At last let us check replication of FROM_UNIXTIME/UNIX_TIMESTAMP functions. +# +connection master; +delete from t2; +insert into t2 values (from_unixtime(1000000000),NULL), + (unix_timestamp('2001-09-09 03:46:40'),NULL); +SELECT * FROM t2 ORDER BY n; +sync_slave_with_master; +# We should get same result on slave as on master +SELECT * FROM t2 ORDER BY n; + +# +# Let us check that we are allowing to set global time_zone with +# replication +# +connection master; +set global time_zone='MET'; + +# +# Let us see if CONVERT_TZ(@@time_zone) replicates +# +delete from t2; +set time_zone='UTC'; +insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone),NULL); +insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'),NULL); +SELECT * FROM t2 ORDER BY n; +sync_slave_with_master; +SELECT * FROM t2 ORDER BY n; + +# Clean up +connection master; +drop table t1, t2; +sync_slave_with_master; + + +# Restore original timezone +connection master; +set global time_zone= @my_time_zone; + +--echo End of 4.1 tests + +# +# Bug #29536: timestamp inconsistent in replication around 1970 +# +connection master; + +CREATE TABLE t1 (a INT, b TIMESTAMP); +INSERT INTO t1 VALUES (1, NOW()); + +SET @@session.time_zone='Japan'; +--disable_warnings +UPDATE IGNORE t1 SET b= '1970-01-01 08:59:59' WHERE a= 1; +--enable_warnings +SELECT * FROM t1 ORDER BY a; + +sync_slave_with_master; +SET @@session.time_zone='Japan'; +# must procdure the same result as the SELECT on the master +SELECT * FROM t1 ORDER BY a; + +SET @@session.time_zone = default; +connection master; +DROP TABLE t1; +SET @@session.time_zone = default; +--sync_slave_with_master +--source include/stop_slave.inc + +# Bug#41719 delayed INSERT into timestamp col needs set time_zone for concurrent binlogging +# To test that time_zone is correctly binloging for 'insert delayed' statement +# Insert 2 values into timestamp col with different time_zone. Check result. + +--connection master +reset master; +CREATE TABLE t1 (date timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, a int(11) default NULL); + +SET @@session.time_zone='+01:00'; +insert into t1 values('2008-12-23 19:39:39',1); + +--connection master1 +SET @@session.time_zone='+02:00'; +insert delayed into t1 values ('2008-12-23 19:39:39',2); + +# wait for the delayed insert to be executed +let $wait_condition= SELECT date FROM t1 WHERE a=2; +--source include/wait_condition.inc + +flush table t1; +flush logs; +select * from t1; +DROP TABLE t1; + +let $MYSQLD_DATADIR= `select @@datadir;`; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL +--connection master1 +select * from t1 order by a; +DROP TABLE t1; +SET @@session.time_zone = default; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc + +--echo End of 5.0 tests diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test new file mode 100644 index 00000000..7029729d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test @@ -0,0 +1,169 @@ +# +# Bug#49132 +# This test verifies if executing DDL statement before trying to manipulate +# a temporary table causes row-based replication to break with error 'table +# does not exist' base on myisam engine. +# + +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +LET $ENGINE_TYPE= MyISAM; +source include/rpl_tmp_table_and_DDL.test; +sync_slave_with_master; + +# +# BUG #51839 +# The test makes sure the binlog format is not changed +# after a execution of DDL with a table locked, so that +# the following DML statements will not cause the slave +# to stop. +# + +--connection master +--disable_abort_on_error + +CREATE TABLE t1 (a CHAR(30)); +CREATE TEMPORARY TABLE t2 (b CHAR(60)); + +# CREATE FUNCTION when a table is locked. +LOCK TABLE t1 WRITE; +CREATE FUNCTION f1 () RETURNS TINYINT RETURN 13; +INSERT INTO t2 VALUES ("CREATE FUNCTION f1 with table locked"); + +UNLOCK TABLE; +CREATE FUNCTION f2 () RETURNS TINYINT RETURN 13; + +# ALTER FUNCTION when a table is locked. +LOCK TABLE t1 WRITE; +ALTER FUNCTION f2 SQL SECURITY INVOKER; +INSERT INTO t2 VALUES ("ALTER FUNCTION f2 with table locked"); + +# DROP FUNCTION when a table is locked. +LOCK TABLE t1 WRITE; +DROP FUNCTION f2; +INSERT INTO t2 VALUES ("DROP FUNCTION f2 with table locked"); + + +# CREATE PROCEDURE when a table is locked. +CREATE PROCEDURE p1() SELECT 1; +INSERT INTO t2 VALUES ("CREATE PROCEDURE p1 with table locked"); + +UNLOCK TABLE; +CREATE PROCEDURE p2() SELECT 1; + +# ALTER PROCEDURE when a table is locked. +LOCK TABLE t1 WRITE; +ALTER PROCEDURE p2 SQL SECURITY INVOKER; +INSERT INTO t2 VALUES ("ALTER PROCEDURE P2 with table locked"); + +# DROP PROCEDURE when a table is locked. +DROP PROCEDURE p2; +INSERT INTO t2 VALUES ("DROP PROCEDURE p2 with table locked"); + + +# CREATE EVENT when a table is locked. +CREATE EVENT e1 ON SCHEDULE EVERY 10 HOUR DO SELECT 1; +INSERT INTO t2 VALUES ("CREATE EVENT e1 with table locked"); + +UNLOCK TABLE; +CREATE EVENT e2 ON SCHEDULE EVERY 10 HOUR DO SELECT 1; + +# ALTER EVENT when a table is locked. +LOCK TABLE t1 WRITE; +ALTER EVENT e2 ON SCHEDULE EVERY 20 HOUR DO SELECT 1; +INSERT INTO t2 VALUES ("ALTER EVENT e2 with table locked"); + +# DROP EVENT when a table is locked. +DROP EVENT e2; +INSERT INTO t2 VALUES ("DROP EVENT e2 with table locked"); + + +# CREATE DATABASE when a table is locked. +CREATE DATABASE mysqltest1; +INSERT INTO t2 VALUES ("CREATE DATABASE mysqltest1 with table locked"); + +UNLOCK TABLE; +CREATE DATABASE mysqltest2; + +# DROP DATABASE when a table is locked. +LOCK TABLE t1 WRITE; +DROP DATABASE mysqltest2; +INSERT INTO t2 VALUES ("DROP DATABASE mysqltest2 with table locked"); + +UNLOCK TABLE; +DROP DATABASE mysqltest2; + +# CREATE USER when a table is locked. +LOCK TABLE t1 WRITE; +CREATE USER test_1@localhost; +INSERT INTO t2 VALUES ("CREATE USER test_1@localhost with table locked"); + +UNLOCK TABLE; +CREATE USER test_2@localhost; + +# GRANT select on table to user when a table is locked. +LOCK TABLE t1 WRITE; +GRANT SELECT ON t1 TO test_2@localhost; +INSERT INTO t2 VALUES ("GRANT select on table to user with table locked"); + +# GRANT all on function to user when a table is locked. +GRANT ALL ON f2 TO test_2@localhost; +INSERT INTO t2 VALUES ("GRANT ALL ON f2 TO test_2 with table locked"); + +# GRANT all on procdure to user when a table is locked. +GRANT ALL ON p2 TO test_2@localhost; +INSERT INTO t2 VALUES ("GRANT ALL ON p2 TO test_2 with table locked"); + +# GRANT USAGE ON *.* to user when a table is locked. +GRANT USAGE ON *.* TO test_2@localhost; +INSERT INTO t2 VALUES ("GRANT USAGE ON *.* TO test_2 with table locked"); + + +# REVOKE ALL PRIVILEGES on function to user when a table is locked. +REVOKE ALL PRIVILEGES ON f2 FROM test_2@localhost; +INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on function to user with table locked"); + +# REVOKE ALL PRIVILEGES on procedure to user when a table is locked. +REVOKE ALL PRIVILEGES ON p2 FROM test_2@localhost; +INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on procedure to user with table locked"); + +# REVOKE ALL PRIVILEGES on table to user when a table is locked. +REVOKE ALL PRIVILEGES ON t1 FROM test_2@localhost; +INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on table to user with table locked"); + +# REVOKE USAGE ON *.* to user when a table is locked. +REVOKE USAGE ON *.* FROM test_2@localhost; +INSERT INTO t2 VALUES ("REVOKE USAGE ON *.* TO test_2 with table locked"); + + +# RENAME USER when a table is locked. +RENAME USER test_2@localhost TO test_3@localhost; +INSERT INTO t2 VALUES ("RENAME USER test_2 TO test_3 with table locked"); + +UNLOCK TABLE; +RENAME USER test_2@localhost TO test_3@localhost; + +# DROP USER when a table is locked. +LOCK TABLE t1 WRITE; +DROP USER test_3@localhost; +INSERT INTO t2 VALUES ("DROP USER test_3@localhost with table locked"); + +UNLOCK TABLE; + +# Bug #20439913 CREATE TABLE DB.TABLE LIKE TMPTABLE IS +# BINLOGGED INCORRECTLY - BREAKS A SLAVE +CREATE DATABASE db; +CREATE TABLE db.t1 LIKE t2; +CREATE TABLE t3 LIKE t2; +DROP TABLE t3; +DROP DATABASE db; +# end of Bug #20439913 test + +DROP USER test_3@localhost; +DROP FUNCTION f2; +DROP PROCEDURE p2; +DROP EVENT e2; +DROP TABLE t1, t2; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test new file mode 100644 index 00000000..1a09b685 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test @@ -0,0 +1,55 @@ +source include/have_innodb.inc; +source include/have_binlog_format_row.inc; +source include/master-slave.inc; +# +# BUG#20574550 +# CREATE TABLE LIKE <TEMP_TABLE> does not preserve original table storage +# engine when using row based replication +# +--connection master + +# Define temp_t1 and temp_t2 storage engines +--let $engine_temp_t1= InnoDB +--let $engine_temp_t2= MyISAM + +# Create the two temporary tables +--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1 +--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2 + +# Create t1 and t2 based on temporary tables +CREATE TABLE t1 LIKE temp_t1; +CREATE TABLE t2 LIKE temp_t2; +--sync_slave_with_master + +# On master +--connection master +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on master and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on master and temp_t2 have the same storage engine" +--source include/assert.inc + +# On slave +--connection slave +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on slave and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on slave and temp_t2 have the same storage engine" +--source include/assert.inc + +# Cleanup +--connection master +DROP TEMPORARY TABLE temp_t1, temp_t2; +DROP TABLE t1, t2; +--source include/rpl_end.inc + diff --git a/mysql-test/suite/rpl/t/rpl_trans_no_trans.test b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test new file mode 100644 index 00000000..f6e3731d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_trans_no_trans.test @@ -0,0 +1,72 @@ +# +# Test mixing transactional and non transactional tables +# + +--source include/master-slave.inc +--source include/have_innodb.inc +--source include/have_binlog_format_row.inc + +# +# Test updating conditionally a non transactinal table in a function +# This verifies that we don't write only a table map for a non transactional, +# without any row events +# The original bug caused a crash on the slave when doing a sync_slave +# + +create or replace table t1(id int)engine=innodb; +create or replace table t3(id int)engine=myisam; + +delimiter //; +create or replace function t99 (a int) +returns int(10) +MODIFIES SQL DATA +begin + if (a > 100) + then + insert into t3 values (a); + end if; + return a; +end// +delimiter ;// +begin; +insert into t1 values(t99(1)); +insert into t1 values(t99(101)); +commit; +select * from t1; +select * from t3; +insert into t1 values(t99(1)); + +drop function t99; +drop table t1,t3; + +sync_slave_with_master; +connection master; + +# +# MDEV-8203 +# Assertion `!current_stmt_is_commit || !rgi->tables_to_lock' failed in +# Query_log_event::do_apply_event(rpl_group_info*, const char*, uint32) +# + +CREATE TABLE t1 (i INT) ENGINE=InnoDB; +CREATE TABLE t2 (j INT) ENGINE=MyISAM; + +--delimiter || +CREATE TRIGGER tr AFTER INSERT ON t1 FOR EACH ROW +BEGIN + SET @a = unknown_column_just_to_raise_an_error; + INSERT INTO t2 VALUES (NULL) ; +END|| +--delimiter ; + +--error ER_BAD_FIELD_ERROR +INSERT INTO t1 VALUES (1); +--sync_slave_with_master + +connection master; + +drop trigger tr; +drop table t1,t2; + +# End of 4.1 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test new file mode 100644 index 00000000..f692816b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_trigger.test @@ -0,0 +1,585 @@ +# +# Test of triggers with replication +# Adding statement include due to Bug 12574 +# TODO: Remove statement include once 12574 is patched +--source include/have_binlog_format_mixed_or_statement.inc +--source include/have_innodb.inc +--source include/master-slave.inc +connection master; + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; + +--enable_warnings + +# +# #12482: Triggers has side effects with auto_increment values +# + +create table t1 (a int auto_increment, primary key (a), b int, rand_value double not null); +create table t2 (a int auto_increment, primary key (a), b int) engine=innodb; +create table t3 (a int auto_increment, primary key (a), name varchar(64) not null, old_a int, old_b int, rand_value double not null); + +delimiter |; +create trigger t1 before insert on t1 for each row +begin + insert into t3 values (NULL, "t1", new.a, new.b, rand()); +end| + +create trigger t2 after insert on t2 for each row +begin + insert into t3 values (NULL, "t2", new.a, new.b, rand()); +end| +delimiter ;| + +insert into t3 values(100,"log",0,0,0); + +# Ensure we always have same random numbers +SET @@RAND_SEED1=658490765, @@RAND_SEED2=635893186; + +# Emulate that we have rows 2-9 deleted on the slave +--disable_warnings +insert into t1 values(1,1,rand()),(NULL,2,rand()); +insert into t2 (b) values(last_insert_id()); +insert into t2 values(3,0),(NULL,0); +insert into t2 values(NULL,0),(500,0); +--enable_warnings + +select a,b, truncate(rand_value,4) from t1; +select * from t2; +select a,name, old_a, old_b, truncate(rand_value,4) from t3; +sync_slave_with_master; +select a,b, truncate(rand_value,4) from t1; +select * from t2; +select a,name, old_a, old_b, truncate(rand_value,4) from t3; +connection master; +drop table t1,t2,t3; + +# +# #12480: NOW() is not constant in a trigger +# #12481: Using NOW() in a stored function breaks statement based replication +# + +# Start by getting a lock on 'bug12480' to be able to use get_lock() as sleep() +connect (con2,localhost,root,,); +connection con2; +select get_lock("bug12480",2); +connection default; + +create table t1 (a datetime,b datetime, c datetime); +--disable_warnings +drop function if exists bug12480; +--enable_warnings + +delimiter |; + +create function bug12480() returns datetime +begin + set @a=get_lock("bug12480",2); + return now(); +end| + +create trigger t1_first before insert on t1 +for each row begin + set @a=get_lock("bug12480",2); + set new.b= now(); + set new.c= bug12480(); +end +| + +delimiter ;| +# The trigger causes a warning for unsafe statement when +# binlog_format=statement since it uses get_lock. +--disable_warnings +insert into t1 set a = now(); +--enable_warnings +select a=b && a=c from t1; +let $time=`select a from t1`; + +# Check that definer attribute is replicated properly: +# - dump definers on the master; +# - wait for the slave to synchronize with the master; +# - dump definers on the slave; + +SELECT routine_name, definer +FROM information_schema.routines +WHERE routine_name = 'bug12480'; + +SELECT trigger_name, definer +FROM information_schema.triggers +WHERE trigger_name = 't1_first'; + +sync_slave_with_master; + +# XXX: Definers of stored procedures and functions are not replicated. WL#2897 +# (Complete definer support in the stored routines) addresses this issue. So, +# the result file is expected to be changed after implementation of this WL +# item. + +SELECT routine_name, definer +FROM information_schema.routines +WHERE routine_name = 'bug12480'; + +SELECT trigger_name, definer +FROM information_schema.triggers +WHERE trigger_name = 't1_first'; + +select a=b && a=c from t1; +--disable_query_log +eval select a='$time' as 'test' from t1; +--enable_query_log + +connection master; +disconnect con2; + +truncate table t1; +drop trigger t1_first; + +# The trigger causes a warning for unsafe statement when +# binlog_format=statement since it uses get_lock. +--disable_warnings +insert into t1 values ("2003-03-03","2003-03-03","2003-03-03"),(bug12480(),bug12480(),bug12480()),(now(),now(),now()); +--enable_warnings +select a=b && a=c from t1; + +drop function bug12480; +drop table t1; + +# +# #14614: Replication of tables with trigger generates error message if databases is changed +# Note. The error message is emitted by _myfree() using fprintf() to the stderr +# and because of that does not fall into the .result file. +# + +create table t1 (i int); +create table t2 (i int); + +delimiter |; +create trigger tr1 before insert on t1 for each row +begin + insert into t2 values (1); +end| +delimiter ;| + +create database other; +use other; +insert into test.t1 values (1); + +sync_slave_with_master; + +connection master; +use test; +drop table t1,t2; +drop database other; + + +# +# Test specific triggers including SELECT into var with replication +# BUG#13227: +# slave performs an update to the replicatable table, t1, +# and modifies its local data, t3, by mean of its local trigger that uses +# another local table t2. +# Expected values are commented into queries. +# +# Body of the test executes in a loop since the problem occurred randomly. +# + +let $max_rows=5; +let $rnd=10; + +--echo test case for BUG#13227 +while ($rnd) +{ + --echo ------------------- + echo $rnd; + --echo ------------------- + +### SETUP + +--disable_warnings + connection master; + eval drop table if exists t1$rnd; + connection slave; + eval drop table if exists t2$rnd,t3$rnd; +--enable_warnings + + connection master; + eval create table t1$rnd (f1 int) /* 2 replicate */; + let $i=$max_rows; + while ($i) + { + eval insert into t1$rnd values (-$i); + dec $i; + } + + sync_slave_with_master; +#connection slave; + eval select * from t1$rnd; + delimiter |; + eval create trigger trg1$rnd before update on t1$rnd /* slave local */ + for each row + begin + DECLARE r integer; + SELECT f2 INTO r FROM t2$rnd where f1=NEW.f1; + INSERT INTO t3$rnd values (r); + end| + delimiter ;| + eval create table t2$rnd (f1 int, f2 int) /* slave local */; + eval create table t3$rnd (f3 int) /* slave local */; + let $i=$max_rows; + while ($i) + { + eval insert into t2$rnd values ($i, $i*100); + dec $i; + } + +### Test + +#connection slave; + +# trigger works as specified when updates from slave + eval select * from t2$rnd; + eval UPDATE t1$rnd SET f1=$max_rows where f1=-$max_rows; + eval SELECT * from t1$rnd /* must be f1 $max_rows, 1 - $max_rows 2 - $max_rows ... -1 */; + eval SELECT * from t3$rnd /* must be f3 $max_rows*100 */; + + connection master; + let $i=$max_rows; + while ($i) + { + eval UPDATE t1$rnd SET f1=$i where f1=-$i; + dec $i; + } + + sync_slave_with_master; +#connection slave; + eval SELECT * from t1$rnd /* must be f1 $max_rows ... 1 */; + eval SELECT * from t3$rnd /* must be f3 $max_rows * 100 ... 100 */; + +### CLEANUP +#connection slave; + eval drop trigger trg1$rnd; + eval drop table t2$rnd,t3$rnd; + + connection master; + eval drop table t1$rnd; + sync_slave_with_master; + connection master; + + dec $rnd; +} + + +# +# BUG#16266: Definer is not fully qualified error during replication. +# +# The idea of this test is to emulate replication of a trigger from the old +# master (master w/o "DEFINER in triggers" support) to the new slave and check +# that: +# 1. the trigger on the slave will be replicated w/o errors; +# 2. the trigger on the slave will be non-SUID (will have no DEFINER); +# 3. the trigger can be activated later on the slave w/o errors. +# +# In order to emulate this kind of replication, we make the slave playing the binlog, +# recorded by 5.0.16 master. This binlog contains the following statements: +# CREATE TABLE t1(c INT); +# CREATE TABLE t2(s CHAR(200)); +# CREATE TRIGGER trg1 AFTER INSERT ON t1 +# FOR EACH ROW +# INSERT INTO t2 VALUES(CURRENT_USER()); +# INSERT INTO t1 VALUES(1); +# + +# 1. Check that the trigger's replication is succeeded. + +# Stop the slave. + +connection slave; +STOP SLAVE; + +# Replace master's binlog. + +connection master; +let $MYSQLD_DATADIR= `select @@datadir`; +FLUSH LOGS; + +# Stop master server +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +# Replace binlog +remove_file $MYSQLD_DATADIR/master-bin.000001; +copy_file $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLD_DATADIR/master-bin.000001; + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +let $binlog_version= query_get_value(SHOW BINLOG EVENTS, Info, 1); + + +# Make the slave to replay the new binlog. +--echo --> Master binlog: $binlog_version + +# Make the slave to replay the new binlog. + +connection slave; +RESET SLAVE; +START SLAVE; + +SELECT MASTER_POS_WAIT('master-bin.000001', 513) >= 0; + +# Check that the replication succeeded. + +SHOW TABLES LIKE 't_'; +--replace_column 6 # +SHOW TRIGGERS; +SELECT * FROM t1; +SELECT * FROM t2; + +# 2. Check that the trigger is non-SUID on the slave; +# 3. Check that the trigger can be activated on the slave. +# +# We disable warnings here since it affects the result file in +# different ways depending on the mode being used. + +disable_warnings; +INSERT INTO t1 VALUES(2); +enable_warnings; + +SELECT * FROM t1; +SELECT * FROM t2; + +# That's all, cleanup. + +DROP TRIGGER trg1; +DROP TABLE t1; +DROP TABLE t2; + +STOP SLAVE; +RESET SLAVE; + +# The master should be clean. + +connection master; +SHOW TABLES LIKE 't_'; +--replace_column 6 # +SHOW TRIGGERS; + +RESET MASTER; + +# Restart slave. + +connection slave; +START SLAVE; + + +# +# BUG#20438: CREATE statements for views, stored routines and triggers can be +# not replicable. +# + +--echo +--echo ---> Test for BUG#20438 + +# Prepare environment. + +--echo +--echo ---> Preparing environment... +--connection master + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +--echo +--connection master + +# Test. + +--echo +--echo ---> Creating objects... + +CREATE TABLE t1(c INT); +CREATE TABLE t2(c INT); + +/*!50003 CREATE TRIGGER t1_bi BEFORE INSERT ON t1 + FOR EACH ROW + INSERT INTO t2 VALUES(NEW.c * 10) */; + +--echo +--echo ---> Inserting value... + +INSERT INTO t1 VALUES(1); + +--echo +--echo ---> Checking on master... + +SELECT * FROM t1; +SELECT * FROM t2; + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +--echo +--echo ---> Checking on slave... + +SELECT * FROM t1; +SELECT * FROM t2; + +# Cleanup. + +--echo +--connection master + +--echo +--echo ---> Cleaning up... + +DROP TABLE t1; +DROP TABLE t2; + +--sync_slave_with_master +--connection master + +# +# BUG#23703: DROP TRIGGER needs an IF EXISTS +# + +connection master; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(a int, b varchar(50)); + +-- error ER_TRG_DOES_NOT_EXIST +drop trigger not_a_trigger; + +drop trigger if exists not_a_trigger; + +create trigger t1_bi before insert on t1 +for each row set NEW.b := "In trigger t1_bi"; + +insert into t1 values (1, "a"); +drop trigger if exists t1_bi; +insert into t1 values (2, "b"); +drop trigger if exists t1_bi; +insert into t1 values (3, "c"); + +select * from t1; +sync_slave_with_master; +select * from t1; + +connection master; + +drop table t1; +sync_slave_with_master; + +# +# Bug#40116: Uncommited changes are replicated and stay on slave after +# rollback on master +# + +connection master; +--source include/rpl_reset.inc + +connection slave; +connection master; + +create table t1 ( f int ) engine = innodb; +create table log ( r int ) engine = myisam; +create trigger tr + after insert on t1 + for each row insert into log values ( new.f ); + +set autocommit = 0; +--disable_warnings +insert into t1 values ( 1 ); +--enable_warnings +rollback; +sync_slave_with_master; + +let $diff_tables= master:t1, slave:t1; +--source include/diff_tables.inc + +let $diff_tables= master:log, slave:log; +--source include/diff_tables.inc + +connection master; +drop table t1, log; +sync_slave_with_master; + +# +# MDEV-6769 DROP TRIGGER IF NOT EXIST binlogged on master but not on slave +# +let $slave_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +connection master; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +drop trigger if exists notexistent; +source include/show_binlog_events.inc; +sync_slave_with_master; +let $binlog_start= $slave_pos; +source include/show_binlog_events.inc; +connection master; + +# +# MDEV-6112 multiple triggers per table +# + +create table t1 (a int primary key, b int); +create trigger tr3 + before insert on t1 + for each row set NEW.b := (NEW.b+1)*4; +create trigger tr1 + before insert on t1 + for each row precedes tr3 set NEW.b := (NEW.b+1)*2; +create trigger tr2 + before insert on t1 + for each row follows tr1 set NEW.b := (NEW.b+1)*3; + +--replace_column 6 # +show triggers; +insert into t1 values (1,1); +select * from t1; +sync_slave_with_master; +--replace_column 6 # +show triggers; +select * from t1; +connection master; +drop table t1; + +# +# MDEV-10924 CREATE OR REPLACE TRIGGER which fails on PRECEDES/FOLLOWS drops +# the trigger, but isn't written to binlog; replication fails +# + +CREATE TABLE t1 (i INT); +CREATE OR REPLACE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW SET @a=1; +--error ER_REFERENCED_TRG_DOES_NOT_EXIST +CREATE OR REPLACE TRIGGER tr BEFORE DELETE ON t1 FOR EACH ROW PRECEDES non_existing_trigger SET @a=2; +--replace_column 6 # +SHOW TRIGGERS; +--sync_slave_with_master +--replace_column 6 # +SHOW TRIGGERS; +connection master; +drop table t1; + +# +# End of tests +# +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_trunc_temp.test b/mysql-test/suite/rpl/t/rpl_trunc_temp.test new file mode 100644 index 00000000..1ef0fced --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_trunc_temp.test @@ -0,0 +1,57 @@ +# ==== Purpose ==== +# +# Verify that Slave_open_temp_tables is increased when a temporary +# table is opened on the slave, and decreased when a temporary table +# is closed on the slave, and that it is preserved during 'DELETE FROM +# table' and 'TRUNCATE table'. +# +# ==== Method ==== +# +# Create a temporary table on master, insert rows, and try: +# - delete rows from the table +# - truncate the table +# - drop the table +# +# ==== Related bugs ==== +# +# BUG#17137 Running "truncate table" on temporary table leaves the table open on a slave +# +# Bug in this test: BUG#37493: rpl_trunc_temp.test nondeterministic + + +# Requires statement-based logging since temporary tables are not +# logged in row-based logging +-- source include/have_binlog_format_mixed_or_statement.inc + +source include/master-slave.inc; + +create temporary table t1 (n int); +insert into t1 values(1); +sync_slave_with_master; +show status like 'Slave_open_temp_tables'; + +# Perform a delete from temp table +connection master; +delete from t1; +sync_slave_with_master; +show status like 'Slave_open_temp_tables'; + +# Perform truncate on temp table +connection master; +truncate t1; +sync_slave_with_master; +show status like 'Slave_open_temp_tables'; + +# Disconnect the master, temp table on slave should disappear +disconnect master; + +connection slave; + +# Wait until drop of temp tables appers in slave's binlog +let $wait_binlog_event= DROP; +source include/wait_for_binlog_event.inc; + +show status like 'Slave_open_temp_tables'; + + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test b/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test new file mode 100644 index 00000000..e8b55b86 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_truncate_2myisam.test @@ -0,0 +1,2 @@ +let $engine=MyISAM; +--source include/rpl_truncate.test diff --git a/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test b/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test new file mode 100644 index 00000000..bac911b9 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_truncate_3innodb.test @@ -0,0 +1,3 @@ +--source include/have_innodb.inc +let $engine=InnoDB; +--source include/rpl_truncate.test diff --git a/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt new file mode 100644 index 00000000..48457b17 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt @@ -0,0 +1 @@ +--loose-innodb diff --git a/mysql-test/suite/rpl/t/rpl_typeconv.test b/mysql-test/suite/rpl/t/rpl_typeconv.test new file mode 100644 index 00000000..c2517086 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_typeconv.test @@ -0,0 +1 @@ +--source include/rpl_typeconv.inc diff --git a/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test b/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test new file mode 100644 index 00000000..ba217210 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_typeconv_innodb.test @@ -0,0 +1,26 @@ +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +# +# BUG#49618: Field length stored incorrectly in binary log for InnoDB +# + +connection slave; +SET @saved_slave_type_conversions = @@GLOBAL.SLAVE_TYPE_CONVERSIONS; +SET GLOBAL SLAVE_TYPE_CONVERSIONS = ''; + +connection master; +CREATE TABLE t1(b1 BIT(1), b2 BIT(2), b3 BIT(3)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (b'0', b'01', b'101'); +sync_slave_with_master; + +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; + +connection master; +DROP TABLE t1; +sync_slave_with_master; + +SET GLOBAL SLAVE_TYPE_CONVERSIONS = @saved_slave_type_conversions; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_udf.test b/mysql-test/suite/rpl/t/rpl_udf.test new file mode 100644 index 00000000..cda99ace --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_udf.test @@ -0,0 +1,11 @@ +################################################################### +# Author: Chuck Bell # +# Date: 2006-12-21 # +# Purpose: To test that UDFs are replicated in both row based and # +# statement based format. This tests work completed in WL#3629. # +################################################################### + +let $engine_type= MyISAM; +--source include/rpl_udf.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test new file mode 100644 index 00000000..aa0bd076 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test @@ -0,0 +1,176 @@ +################################################################################ +# Bug#17047208 REPLICATION DIFFERENCE FOR MULTIPLE TRIGGERS +# Problem: If DML invokes a trigger or a stored function that inserts into an +# AUTO_INCREMENT column, that DML has to be marked as 'unsafe' statement. If the +# tables are locked in the transaction prior to DML statement (using LOCK +# TABLES), then the DML statement is not marked as 'unsafe' statement. + +# Steps to reproduce the reported test case (BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS) +# Case-1: +# > Create a trigger on a table and do a insert in the trigger that updates +# auto increment column +# > A DML that executes the trigger in step.1 and check that DML is marked +# as unsafe and DML is written into binlog using row format (in MBR) +# > Execute the step 2 by locking the required tables prior to DML and check +# that DML is marked as unsafe and DML is written into binlog using row +# format (in MBR) +# +# This test script also adds test cases to cover few other unsafe statements. +# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT +# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST +# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS +################################################################################ + +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS +# Statement is unsafe because it invokes a trigger or a +# stored function that inserts into an AUTO_INCREMENT column. + +# Step-1.1: Create two tables, one with AUTO_INCREMENT column. +CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; + +# Step-1.2: Create a trigger that inserts into an AUTO_INCREMENT column. +CREATE TRIGGER trig1 AFTER INSERT ON t1 +FOR EACH ROW + INSERT INTO t2(i) VALUES(new.i); + +# Step-1.3: Create some gap in auto increment value on master's t2 table +# but not on slave (by doing rollback). Just in case if the unsafe statements +# are written in statement format, diff tables will fail. +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; + +# Step-1.4: Insert a tuple into table t1 that triggers trig1 which inserts +# into an AUTO_INCREMENT column. +INSERT INTO t1(i) VALUES(2); + +# Step-1.5: Repeat step 1.4 but using 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t1(i) VALUES(3); +UNLOCK TABLES; +COMMIT; + +# Step-1.6: Sync slave with master +--sync_slave_with_master + +# Step-1.7: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +--let $diff_tables=master:t2, slave:t2 +--source include/diff_tables.inc + +# Step-1.8: Cleanup +--connection master +DROP TABLE t1,t2; + +# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT +# Statements writing to a table with an auto-increment column after selecting +# from another table are unsafe because the order in which rows are retrieved +# determines what (if any) rows will be written. This order cannot be +# predicted and may differ on master and the slave. + +# Step-2.1: Create two tables, one with AUTO_INCREMENT column. +CREATE TABLE t1(i INT) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; + +# Step-2.2: Create some tuples in table t1. +INSERT INTO t1 values (1), (2), (3); + +# Step-2.3: Create some gap in auto increment value on master's t2 table +# but not on slave (by doing rollback). Just in case if the unsafe statements +# are written in statement format, diff tables will fail. +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; + +# Step-2.4: Insert into t2 (table with an auto-increment) by selecting tuples +# from table t1. +INSERT INTO t2(i) SELECT i FROM t1; + +# Step-2.5: Repeat step 2.4 but now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t2 WRITE, t1 READ; +INSERT INTO t2(i) SELECT i FROM t1; +UNLOCK TABLES; +COMMIT; + +# Step-2.6: Sync slave with master +--sync_slave_with_master + +# Step-2.7: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +--let $diff_tables=master:t2, slave:t2 +--source include/diff_tables.inc + +# Step-2.8: Cleanup +--connection master +DROP TABLE t1,t2; + +# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST +# INSERT into autoincrement field which is not the first part in the +# composed primary key is unsafe +# +# Step-3.1: Create a table with auto increment column and a composed primary key +# (second column is auto increment column). Such a definition is allowed only +# with 'myisam' engine. +CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM; + +# Step-3.2: Inserting into such a table is unsafe. +INSERT INTO t1 (i) values (1); + +# Step-3.3: Repeat step 3.2, now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i) values (2); +UNLOCK TABLES; +COMMIT; + +# Step-3.4: Sync slave with master +--sync_slave_with_master + +# Step-3.5: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +# Step-3.6: Cleanup +--connection master +DROP TABLE t1; + +# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS +# INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY +# is unsafe Statement + +# Step-4.1: Create a table with two unique keys +CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB; + +# Step-4.2: Inserting into such a table is unsafe. +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; + +# Step-4.3: Repeat step 3.2, now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; +UNLOCK TABLES; +COMMIT; + +# Step-4.4: Sync slave with master +--sync_slave_with_master + +# Step-4.5: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +# Step-4.6: Cleanup +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_update.test b/mysql-test/suite/rpl/t/rpl_update.test new file mode 100644 index 00000000..b3807877 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_update.test @@ -0,0 +1,15 @@ +source include/master-slave.inc; + +# +# MDEV-13417 UPDATE produces wrong values if an updated column is later used as an update source +# +set sql_mode=simultaneous_assignment; +create table t1 (a int, b int); +insert into t1 values(1, 2); +update t1 set a=b, b=a; +select * from t1; +sync_slave_with_master; +select * from t1; +connection master; +drop table t1; +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test new file mode 100644 index 00000000..42b375c4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test @@ -0,0 +1,168 @@ +--source include/master-slave.inc + +--echo *** MDEV-9383: Server fails to read master.info after upgrade 10.0 -> 10.1 *** + +--connection slave +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=CURRENT_POS; +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +CREATE TABLE t1 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1; + +--source include/stop_slave.inc + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad2_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +INSERT INTO t1 VALUES (2); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad3_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +INSERT INTO t1 VALUES (3); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad4_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +INSERT INTO t1 VALUES (4); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad5_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +INSERT INTO t1 VALUES (5); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; +SELECT * FROM t1 ORDER BY a; + +--source include/stop_slave.inc + +--let $rpl_server_number= 2 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master.info +--copy_file $MYSQL_TEST_DIR/std_data/bad6_master.info $datadir/master.info + +--let $rpl_server_number= 2 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection master +INSERT INTO t1 VALUES (6); +--source include/save_master_gtid.inc + +--connection slave +# Fix the port after we replaced master.info. +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +# Cleanup +--connection master +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_user.test b/mysql-test/suite/rpl/t/rpl_user.test new file mode 100644 index 00000000..079c2bf2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_user.test @@ -0,0 +1,73 @@ +# BUG#33862 completely failed DROP USER statement gets replicated + +--source include/master-slave.inc + +# +# remove all users will be used in the test +# +connection master; +set session sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set session sql_log_bin=1; + +connection slave; +set session sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set session sql_log_bin=1; + +# +# Test create user +# +connection master; +create user 'foo'@'fakehost'; +--error ER_CANNOT_USER +create user 'foo'@'fakehost', 'bar'@'fakehost'; +--error ER_CANNOT_USER +create user 'foo'@'fakehost', 'bar'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# Test rename user +# +connection master; +rename user 'foo'@'fakehost' to 'foofoo'@'fakehost'; +--error ER_CANNOT_USER +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost'; +--error ER_CANNOT_USER +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'not_exist_user2'@'fakehost' to 'barfoo'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# Test alter user +# +connection master; +alter user 'foofoo'@'fakehost' identified by 'foo'; +--error ER_CANNOT_USER +alter user 'non_exist_user1'@'fakehost' identified by 'foo', 'barbar'@'fakehost' identified by 'bar'; +--error ER_CANNOT_USER +alter user 'non_exist_user1'@'fakehost' identified by 'foo', 'non_exist_user2'@'fakehost' identified by 'bar'; +sync_slave_with_master; + +# +# Test drop user +# +connection master; +drop user 'foofoo'@'fakehost'; +--error ER_CANNOT_USER +drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost'; +--error ER_CANNOT_USER +drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# show the binlog events on the master +# +connection master; +source include/show_binlog_events.inc; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_user_variables.test b/mysql-test/suite/rpl/t/rpl_user_variables.test new file mode 100644 index 00000000..08d9b4ae --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_user_variables.test @@ -0,0 +1,385 @@ +################################### +# +# Test of replicating user variables +# +################################### + +-- source include/master-slave.inc + +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + +# Disable PS as the log positions differs +--disable_ps_protocol + + +# Clean up old slave's binlogs. +# The slave is started with --log-slave-updates +# and this test does SHOW BINLOG EVENTS on the slave's +# binlog. But previous tests can influence the current test's +# binlog (e.g. a temporary table in the previous test has not +# been explicitly deleted, or it has but the slave hasn't had +# enough time to catch it before STOP SLAVE, +# and at the beginning of the current +# test the slave immediately writes DROP TEMPORARY TABLE this_old_table). +# We wait for the slave to have written all he wants to the binlog +# (otherwise RESET MASTER may come too early). +sync_slave_with_master; +reset master; +connection master; + +create table t1(n char(30)); +set @i1:=12345678901234, @i2:=-12345678901234, @i3:=0, @i4:=-1; +set @s1:='This is a test', @r1:=12.5, @r2:=-12.5; +set @n1:=null; +set @s2:='', @s3:='abc\'def', @s4:= 'abc\\def', @s5:= 'abc''def'; +insert into t1 values (@i1), (@i2), (@i3), (@i4); +insert into t1 values (@r1), (@r2); +insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5); +insert into t1 values (@n1); +insert into t1 values (@n2); # not explicitly set before +insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1); +insert into t1 values (@a+(@b:=@a+1)); +set @q:='abc'; +insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')); +set @a:=5; +insert into t1 values (@a),(@a); +# To flush the pending event, we add the following statement. RBR can +# concatenate the result of several statements, which SBR cannot. +select * from t1 where n = '<nonexistant>'; +connection master1; # see if variable is reset in binlog when thread changes +insert into t1 values (@a),(@a),(@a*5); +SELECT * FROM t1 ORDER BY n; +sync_slave_with_master; +SELECT * FROM t1 ORDER BY n; +connection master; +insert into t1 select * FROM (select @var1 union select @var2) AS t2; +drop table t1; +--echo End of 4.1 tests. + +# BUG#20141 +# The following tests ensure that if user-defined variables are used in SF/Triggers +# that they are replicated correctly. These tests should be run in both SBR and RBR +# modes. + +# This test uses a procedure that inserts data values based on the value of a +# user-defined variable. It also has a trigger that inserts data based on the +# same variable. Successful test runs show that the @var is replicated +# properly and that the procedure and trigger insert the correct data on the +# slave. +# +# The test of stored procedure was included for completeness. Replication of stored +# procedures was not directly affected by BUG#20141. +# +# This test was constructed for BUG#20141 + +--disable_warnings +DROP TABLE IF EXISTS t20; +DROP TABLE IF EXISTS t21; +DROP PROCEDURE IF EXISTS test.insert; +--enable_warnings + +CREATE TABLE t20 (a VARCHAR(20)); +CREATE TABLE t21 (a VARCHAR(20)); +DELIMITER |; + +# Create a procedure that uses the @var for flow control + +CREATE PROCEDURE test.insert() +BEGIN + IF (@VAR) + THEN + INSERT INTO test.t20 VALUES ('SP_TRUE'); + ELSE + INSERT INTO test.t20 VALUES ('SP_FALSE'); + END IF; +END| + +# Create a trigger that uses the @var for flow control + +CREATE TRIGGER test.insert_bi BEFORE INSERT + ON test.t20 FOR EACH ROW + BEGIN + IF (@VAR) + THEN + INSERT INTO test.t21 VALUES ('TRIG_TRUE'); + ELSE + INSERT INTO test.t21 VALUES ('TRIG_FALSE'); + END IF; + END| +DELIMITER ;| + +sync_slave_with_master; +connection master; + +# Set @var and call the procedure, repeat with different values + +SET @VAR=0; +CALL test.insert(); +SET @VAR=1; +CALL test.insert(); + +--echo Check the tables for correct data + +SELECT * FROM t20; +SELECT * FROM t21; + +sync_slave_with_master; + +--echo Check the tables for correct data and it matches master + +SELECT * FROM t20; +SELECT * FROM t21; +connection master; + +# Cleanup + +DROP TABLE t20; +DROP TABLE t21; +DROP PROCEDURE test.insert; + +# This test uses a stored function that uses user-defined variables to return data +# This test was constructed for BUG#20141 + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS test.square; +--enable_warnings + +CREATE TABLE t1 (i INT); + +# Create function that returns a value from @var. In this case, the square function + +CREATE FUNCTION test.square() RETURNS INTEGER DETERMINISTIC RETURN +(@var * @var); + +# Set the @var to different values and insert them into a table + +SET @var = 1; +INSERT INTO t1 VALUES (square()); +SET @var = 2; +INSERT INTO t1 VALUES (square()); +SET @var = 3; +INSERT INTO t1 VALUES (square()); +SET @var = 4; +INSERT INTO t1 VALUES (square()); +SET @var = 5; +INSERT INTO t1 VALUES (square()); + +--echo Retrieve the values from the table + +SELECT * FROM t1; + +sync_slave_with_master; + +--echo Retrieve the values from the table and verify they are the same as on master + +SELECT * FROM t1; + +connection master; + +# Cleanup + +DROP TABLE t1; +DROP FUNCTION test.square; + +# This test uses stored functions that uses user-defined variables to return data +# based on the use of @vars inside a function body. +# This test was constructed for BUG#14914 + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +--enable_warnings + +CREATE TABLE t1(a int); +DELIMITER |; + +# Create a function that simply returns the value of an @var. +# Create a function that uses an @var for flow control, creates and uses another +# @var and sets its value to a value based on another @var. + +CREATE FUNCTION f1() returns int deterministic BEGIN + return @a; +END | + +CREATE FUNCTION f2() returns int deterministic BEGIN + IF (@b > 0) then + SET @c = (@a + @b); + else + SET @c = (@a - 1); + END if; + return @c; +END | +DELIMITER ;| + +sync_slave_with_master; +connection master; + +# Set an @var to a value and insert data into a table using the first function. +# Set two more @vars to some values and insert data into a table using the second function. + +SET @a=500; +INSERT INTO t1 values(f1()); +SET @b = 125; +SET @c = 1; +INSERT INTO t1 values(f2()); + +--echo Retrieve the values from the table + +sync_slave_with_master; +connection master; + +SELECT * from t1; + +connection slave; + +--echo Check the tables for correct data and it matches master + +SELECT * from t1; + +connection master; + +# Cleanup + +DROP TABLE t1; +DROP FUNCTION f1; +DROP FUNCTION f2; + +# This test uses a function that changes a user-defined variable in its body. This test +# will ensure the @vars are replicated when needed and not interrupt the normal execution +# of the function on the slave. This also applies to procedures and triggers. + +# This test was constructed for BUG#25167 + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings +CREATE TABLE t1 (i int); +CREATE TABLE t2 (k int); +DELIMITER |; + +# Create a trigger that inserts data into another table, changes the @var then inserts +# another row with the modified value. + +CREATE trigger t1_bi before INSERT on t1 for each row BEGIN + INSERT INTO t2 values (@a); + SET @a:=42; + INSERT INTO t2 values (@a); +END | +DELIMITER ;| + +sync_slave_with_master; +connection master; + +# Set the @var to a value then insert data into first table. + +SET @a:=100; +INSERT INTO t1 values (5); + +--echo Check to see that data was inserted correctly in both tables + +SELECT * from t1; +SELECT * from t2; + +sync_slave_with_master; + +--echo Check the tables for correct data and it matches master + +SELECT * from t1; +SELECT * from t2; + +connection master; +drop table t1, t2; + +# +# Bug #12826: Possible to get inconsistent slave using SQL syntax Prepared Statements +# +connection master; +create table t1(a int, b int); +prepare s1 from 'insert into t1 values (@x:=@x+1, ?)'; +set @x=1; execute s1 using @x; +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +# +# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210 +# + +connection master; +create table t1(a int); +insert into t1 values (1),(2); +prepare s1 from 'insert into t1 select a from t1 limit ?'; +set @x='1.1'; +--disable_warnings +execute s1 using @x; +--enable_warnings +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + +--echo End of 5.0 tests. + +# This test uses a stored function that uses user-defined variables to return data +# The test ensures the value of the user-defined variable is replicated correctly +# and in the correct order of assignment. + +# This test was constructed for BUG#20141 + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +--enable_warnings + +CREATE TABLE t1 (i INT); + +# Create two functions. One simply returns the user-defined variable. The other +# returns a value based on the user-defined variable. + +CREATE FUNCTION f1() RETURNS INT RETURN @a; DELIMITER |; CREATE +FUNCTION f2() RETURNS INT BEGIN + INSERT INTO t1 VALUES (10 + @a); + RETURN 0; +END| +DELIMITER ;| + +sync_slave_with_master; +connection master; + +# Set the variable and execute the functions. + +SET @a:=123; +SELECT f1(), f2(); + +--echo Check to see that data was inserted correctly + +INSERT INTO t1 VALUES(f1()); +SELECT * FROM t1; + +sync_slave_with_master; + +--echo Check the table for correct data and it matches master + +SELECT * FROM t1; + +connection master; + +# Cleanup + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1; + +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_variables.test b/mysql-test/suite/rpl/t/rpl_variables.test new file mode 100644 index 00000000..1b83d5d5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_variables.test @@ -0,0 +1,738 @@ +# ==== Purpose ==== +# +# Test that queries referencing variables are replicated correctly in +# mixed and row-based logging mode. +# +# +# ==== Method ==== +# +# The test simply does a lot of "INSERT INTO t1 VALUES (@@variable)" +# and checks the result on the slave. +# +# Statements referencing a variable only replicate correctly in mixed +# and row mode: in row mode, the values inserted are replicated. In +# mixed mode, statements referencing a variable are marked as unsafe, +# meaning they will be replicated by row. In statement mode, the +# slave's value will be used and replication will break. (Except in a +# small number of special cases: random seeds, insert_id, and +# auto_increment are replicated). +# +# We test the following variable scopes: +# - server system variables +# - server session variables +# - server "both" variables +# - user variables +# +# For each scope, we use variables of the following types if they +# exist: +# - boolean +# - numeric +# - string +# - enumeration variables +# +# We use these types of variables in the following contexts: +# - directly +# - from a stored procedure +# - from a stored function +# - from a trigger +# - from a prepared statement +# +# For all variables where it is possible, we set the variable to one +# value on slave, and insert it on the master with two distinct +# values. +# +# The same insertions are made in four different tables using direct +# insert, stored procedure, stored function, or trigger. Then all +# eight resulting tables on master and slave are compared. +# +# +# ==== Related bugs ==== +# +# BUG#31168: @@hostname does not replicate +# +# +# ==== Related test cases ==== +# +# binlog.binlog_unsafe tests that a warning is issued if system +# variables are replicated in statement mode. +# +# rpl.rpl_variables_stm tests the small subset of variables that +# actually can be replicated safely in statement mode. + + +source include/have_binlog_format_mixed_or_row.inc; +source include/master-slave.inc; + + +--echo ==== Initialization ==== + +# Backup the values of global variables so that they can be restored +# later. +connection master; +SET @m_default_week_format= @@global.default_week_format; +SET @m_init_slave= @@global.init_slave; +SET @m_lc_time_names= @@global.lc_time_names; +SET @m_low_priority_updates= @@global.low_priority_updates; +SET @m_relay_log_purge= @@global.relay_log_purge; +SET @m_slave_exec_mode= @@global.slave_exec_mode; +SET @m_sql_mode= @@global.sql_mode; +SET @m_sync_binlog= @@global.sync_binlog; + +connection slave; +SET @s_default_week_format= @@global.default_week_format; +SET @s_init_slave= @@global.init_slave; +SET @s_lc_time_names= @@global.lc_time_names; +SET @s_low_priority_updates= @@global.low_priority_updates; +SET @s_relay_log_purge= @@global.relay_log_purge; +SET @s_slave_exec_mode= @@global.slave_exec_mode; +SET @s_sql_mode= @@global.sql_mode; +SET @s_sync_binlog= @@global.sync_binlog; + +# Set global variables on slave to something different than on master. +SET @@global.relay_log_purge = OFF; +SET @@global.sync_binlog = 1000000; +SET @@global.slave_exec_mode = 'STRICT'; +SET @@sql_big_selects = OFF; +SET @@last_insert_id = 10; +SET @@global.low_priority_updates = OFF; +SET @@local.low_priority_updates = OFF; +SET @@global.default_week_format = 1; +SET @@local.default_week_format = 2; +SET @@global.lc_time_names = 'zh_HK'; +SET @@local.lc_time_names = 'zh_TW'; +SET @@global.sql_mode = 'ALLOW_INVALID_DATES'; +SET @@local.sql_mode = 'ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE'; +SET @user_num = 10; +SET @user_text = 'Alunda'; + +# Stop slave so that we get a fresh sql thread, reading the slave's +# global values of variables into its local copies. +--source include/stop_slave.inc +--source include/start_slave.inc + +# We would have wanted to set this together with the other variables +# above, but can't because it affects how the slave works. +SET @@global.init_slave = 'SELECT 1'; + + +connection master; +# checking values of read-only variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@pid_file, @@datadir; +--echo **** Relay log variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@relay_log, @@relay_log_index, @@relay_log_basename; +--echo **** Binary log variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@log_bin, @@log_bin_index, @@log_bin_basename; + +connection slave; +# checking values of read-only variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@pid_file, @@datadir; +--echo **** Relay log variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@relay_log, @@relay_log_index, @@relay_log_basename; +--echo **** Binary log variables +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +query_vertical SELECT @@log_bin, @@log_bin_index, @@log_bin_basename; + +connection master; + +# Tables where everything happens. +CREATE TABLE tstmt (id INT AUTO_INCREMENT PRIMARY KEY, + truth BOOLEAN, + num INT, + text VARCHAR(100)); +CREATE TABLE tproc LIKE tstmt; +CREATE TABLE tfunc LIKE tstmt; +CREATE TABLE ttrig LIKE tstmt; +CREATE TABLE tprep LIKE tstmt; + +# Table on which we put a trigger. +CREATE TABLE trigger_table (text CHAR(4)); + + +--echo ==== Insert variables directly ==== + +--echo ---- global variables ---- + +# boolean +SET @@global.relay_log_purge = ON; +INSERT INTO tstmt(truth) VALUES (@@global.relay_log_purge); +SET @@global.relay_log_purge = OFF; +INSERT INTO tstmt(truth) VALUES (@@global.relay_log_purge); + +# numeric +SET @@global.sync_binlog = 2000000; +INSERT INTO tstmt(num) VALUES (@@global.sync_binlog); +SET @@global.sync_binlog = 3000000; +INSERT INTO tstmt(num) VALUES (@@global.sync_binlog); + +# string +SET @@global.init_slave = 'SELECT 2'; +INSERT INTO tstmt(text) VALUES (@@global.init_slave); +SET @@global.init_slave = 'SELECT 3'; +INSERT INTO tstmt(text) VALUES (@@global.init_slave); + +# enumeration +SET @@global.slave_exec_mode = 'IDEMPOTENT'; +INSERT INTO tstmt(text) VALUES (@@global.slave_exec_mode); +SET @@global.slave_exec_mode = 'STRICT'; +INSERT INTO tstmt(text) VALUES (@@global.slave_exec_mode); + + +--echo ---- session variables ---- + +# boolean +SET @@sql_big_selects = ON; +INSERT INTO tstmt(truth) VALUES (@@sql_big_selects); +SET @@sql_big_selects = OFF; +INSERT INTO tstmt(truth) VALUES (@@sql_big_selects); + +# numeric +SET @@last_insert_id = 20; +INSERT INTO tstmt(num) VALUES (@@last_insert_id); +SET @@last_insert_id = 30; +INSERT INTO tstmt(num) VALUES (@@last_insert_id); + +--echo ---- global and session variables ---- + +# boolean +SET @@global.low_priority_updates = ON; +SET @@local.low_priority_updates = OFF; +INSERT INTO tstmt(truth) VALUES (@@global.low_priority_updates); +INSERT INTO tstmt(truth) VALUES (@@local.low_priority_updates); +SET @@global.low_priority_updates = OFF; +SET @@local.low_priority_updates = ON; +INSERT INTO tstmt(truth) VALUES (@@global.low_priority_updates); +INSERT INTO tstmt(truth) VALUES (@@local.low_priority_updates); + +# numeric +SET @@global.default_week_format = 3; +SET @@local.default_week_format = 4; +INSERT INTO tstmt(num) VALUES (@@global.default_week_format); +INSERT INTO tstmt(num) VALUES (@@local.default_week_format); +SET @@global.default_week_format = 5; +SET @@local.default_week_format = 6; +INSERT INTO tstmt(num) VALUES (@@global.default_week_format); +INSERT INTO tstmt(num) VALUES (@@local.default_week_format); + +# string +SET @@global.lc_time_names = 'sv_SE'; +SET @@local.lc_time_names = 'sv_FI'; +INSERT INTO tstmt(text) VALUES (@@global.lc_time_names); +INSERT INTO tstmt(text) VALUES (@@local.lc_time_names); +SET @@global.lc_time_names = 'ar_TN'; +SET @@local.lc_time_names = 'ar_IQ'; +INSERT INTO tstmt(text) VALUES (@@global.lc_time_names); +INSERT INTO tstmt(text) VALUES (@@local.lc_time_names); + +# enum +SET @@global.sql_mode = ''; +SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER'; +INSERT INTO tstmt(text) VALUES (@@global.sql_mode); +INSERT INTO tstmt(text) VALUES (@@local.sql_mode); +SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION'; +SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS'; +INSERT INTO tstmt(text) VALUES (@@global.sql_mode); +INSERT INTO tstmt(text) VALUES (@@local.sql_mode); + +--echo ---- user variables ---- + +# numeric +SET @user_num = 20; +INSERT INTO tstmt(num) VALUES (@user_num); +SET @user_num = 30; +INSERT INTO tstmt(num) VALUES (@user_num); + +# string +SET @user_text = 'Bergsbrunna'; +INSERT INTO tstmt(text) VALUES (@user_text); +SET @user_text = 'Centrum'; +INSERT INTO tstmt(text) VALUES (@user_text); + + +--echo ==== Insert variables from a stored procedure ==== + +DELIMITER |; +CREATE PROCEDURE proc() +BEGIN + + # GLOBAL + + # boolean + SET @@global.relay_log_purge = ON; + INSERT INTO tproc(truth) VALUES (@@global.relay_log_purge); + SET @@global.relay_log_purge = OFF; + INSERT INTO tproc(truth) VALUES (@@global.relay_log_purge); + + # numeric + SET @@global.sync_binlog = 2000000; + INSERT INTO tproc(num) VALUES (@@global.sync_binlog); + SET @@global.sync_binlog = 3000000; + INSERT INTO tproc(num) VALUES (@@global.sync_binlog); + + # string + SET @@global.init_slave = 'SELECT 2'; + INSERT INTO tproc(text) VALUES (@@global.init_slave); + SET @@global.init_slave = 'SELECT 3'; + INSERT INTO tproc(text) VALUES (@@global.init_slave); + + # enumeration + SET @@global.slave_exec_mode = 'IDEMPOTENT'; + INSERT INTO tproc(text) VALUES (@@global.slave_exec_mode); + SET @@global.slave_exec_mode = 'STRICT'; + INSERT INTO tproc(text) VALUES (@@global.slave_exec_mode); + + # SESSION + + # boolean + SET @@sql_big_selects = ON; + INSERT INTO tproc(truth) VALUES (@@sql_big_selects); + SET @@sql_big_selects = OFF; + INSERT INTO tproc(truth) VALUES (@@sql_big_selects); + + # numeric + SET @@last_insert_id = 20; + INSERT INTO tproc(num) VALUES (@@last_insert_id); + SET @@last_insert_id = 30; + INSERT INTO tproc(num) VALUES (@@last_insert_id); + + # BOTH + + # boolean + SET @@global.low_priority_updates = ON; + SET @@local.low_priority_updates = OFF; + INSERT INTO tproc(truth) VALUES (@@global.low_priority_updates); + INSERT INTO tproc(truth) VALUES (@@local.low_priority_updates); + SET @@global.low_priority_updates = OFF; + SET @@local.low_priority_updates = ON; + INSERT INTO tproc(truth) VALUES (@@global.low_priority_updates); + INSERT INTO tproc(truth) VALUES (@@local.low_priority_updates); + + # numeric + SET @@global.default_week_format = 3; + SET @@local.default_week_format = 4; + INSERT INTO tproc(num) VALUES (@@global.default_week_format); + INSERT INTO tproc(num) VALUES (@@local.default_week_format); + SET @@global.default_week_format = 5; + SET @@local.default_week_format = 6; + INSERT INTO tproc(num) VALUES (@@global.default_week_format); + INSERT INTO tproc(num) VALUES (@@local.default_week_format); + + # text + SET @@global.lc_time_names = 'sv_SE'; + SET @@local.lc_time_names = 'sv_FI'; + INSERT INTO tproc(text) VALUES (@@global.lc_time_names); + INSERT INTO tproc(text) VALUES (@@local.lc_time_names); + SET @@global.lc_time_names = 'ar_TN'; + SET @@local.lc_time_names = 'ar_IQ'; + INSERT INTO tproc(text) VALUES (@@global.lc_time_names); + INSERT INTO tproc(text) VALUES (@@local.lc_time_names); + + # enum + SET @@global.sql_mode = ''; + SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER'; + INSERT INTO tproc(text) VALUES (@@global.sql_mode); + INSERT INTO tproc(text) VALUES (@@local.sql_mode); + SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION'; + SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS'; + INSERT INTO tproc(text) VALUES (@@global.sql_mode); + INSERT INTO tproc(text) VALUES (@@local.sql_mode); + + # USER + + # numeric + SET @user_num = 20; + INSERT INTO tproc(num) VALUES (@user_num); + SET @user_num = 30; + INSERT INTO tproc(num) VALUES (@user_num); + + # string + SET @user_text = 'Bergsbrunna'; + INSERT INTO tproc(text) VALUES (@user_text); + SET @user_text = 'Centrum'; + INSERT INTO tproc(text) VALUES (@user_text); + +END| +DELIMITER ;| + +CALL proc(); + + +--echo ==== Insert variables from a stored function ==== + +DELIMITER |; +CREATE FUNCTION func() +RETURNS INT +BEGIN + + # GLOBAL + + # boolean + SET @@global.relay_log_purge = ON; + INSERT INTO tfunc(truth) VALUES (@@global.relay_log_purge); + SET @@global.relay_log_purge = OFF; + INSERT INTO tfunc(truth) VALUES (@@global.relay_log_purge); + + # numeric + SET @@global.sync_binlog = 2000000; + INSERT INTO tfunc(num) VALUES (@@global.sync_binlog); + SET @@global.sync_binlog = 3000000; + INSERT INTO tfunc(num) VALUES (@@global.sync_binlog); + + # string + SET @@global.init_slave = 'SELECT 2'; + INSERT INTO tfunc(text) VALUES (@@global.init_slave); + SET @@global.init_slave = 'SELECT 3'; + INSERT INTO tfunc(text) VALUES (@@global.init_slave); + + # enumeration + SET @@global.slave_exec_mode = 'IDEMPOTENT'; + INSERT INTO tfunc(text) VALUES (@@global.slave_exec_mode); + SET @@global.slave_exec_mode = 'STRICT'; + INSERT INTO tfunc(text) VALUES (@@global.slave_exec_mode); + + # SESSION + + # boolean + SET @@sql_big_selects = ON; + INSERT INTO tfunc(truth) VALUES (@@sql_big_selects); + SET @@sql_big_selects = OFF; + INSERT INTO tfunc(truth) VALUES (@@sql_big_selects); + + # numeric + SET @@last_insert_id = 20; + INSERT INTO tfunc(num) VALUES (@@last_insert_id); + SET @@last_insert_id = 30; + INSERT INTO tfunc(num) VALUES (@@last_insert_id); + + # BOTH + + # boolean + SET @@global.low_priority_updates = ON; + SET @@local.low_priority_updates = OFF; + INSERT INTO tfunc(truth) VALUES (@@global.low_priority_updates); + INSERT INTO tfunc(truth) VALUES (@@local.low_priority_updates); + SET @@global.low_priority_updates = OFF; + SET @@local.low_priority_updates = ON; + INSERT INTO tfunc(truth) VALUES (@@global.low_priority_updates); + INSERT INTO tfunc(truth) VALUES (@@local.low_priority_updates); + + # numeric + SET @@global.default_week_format = 3; + SET @@local.default_week_format = 4; + INSERT INTO tfunc(num) VALUES (@@global.default_week_format); + INSERT INTO tfunc(num) VALUES (@@local.default_week_format); + SET @@global.default_week_format = 5; + SET @@local.default_week_format = 6; + INSERT INTO tfunc(num) VALUES (@@global.default_week_format); + INSERT INTO tfunc(num) VALUES (@@local.default_week_format); + + # text + SET @@global.lc_time_names = 'sv_SE'; + SET @@local.lc_time_names = 'sv_FI'; + INSERT INTO tfunc(text) VALUES (@@global.lc_time_names); + INSERT INTO tfunc(text) VALUES (@@local.lc_time_names); + SET @@global.lc_time_names = 'ar_TN'; + SET @@local.lc_time_names = 'ar_IQ'; + INSERT INTO tfunc(text) VALUES (@@global.lc_time_names); + INSERT INTO tfunc(text) VALUES (@@local.lc_time_names); + + # enum + SET @@global.sql_mode = ''; + SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER'; + INSERT INTO tfunc(text) VALUES (@@global.sql_mode); + INSERT INTO tfunc(text) VALUES (@@local.sql_mode); + SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION'; + SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS'; + INSERT INTO tfunc(text) VALUES (@@global.sql_mode); + INSERT INTO tfunc(text) VALUES (@@local.sql_mode); + + # USER + + # numeric + SET @user_num = 20; + INSERT INTO tfunc(num) VALUES (@user_num); + SET @user_num = 30; + INSERT INTO tfunc(num) VALUES (@user_num); + + # string + SET @user_text = 'Bergsbrunna'; + INSERT INTO tfunc(text) VALUES (@user_text); + SET @user_text = 'Centrum'; + INSERT INTO tfunc(text) VALUES (@user_text); + + RETURN 0; +END| +DELIMITER ;| + +SELECT func(); + + +--echo ==== Insert variables from a trigger ==== + +DELIMITER |; +CREATE TRIGGER trig +BEFORE INSERT ON trigger_table +FOR EACH ROW +BEGIN + + # GLOBAL + + # boolean + SET @@global.relay_log_purge = ON; + INSERT INTO ttrig(truth) VALUES (@@global.relay_log_purge); + SET @@global.relay_log_purge = OFF; + INSERT INTO ttrig(truth) VALUES (@@global.relay_log_purge); + + # numeric + SET @@global.sync_binlog = 2000000; + INSERT INTO ttrig(num) VALUES (@@global.sync_binlog); + SET @@global.sync_binlog = 3000000; + INSERT INTO ttrig(num) VALUES (@@global.sync_binlog); + + # string + SET @@global.init_slave = 'SELECT 2'; + INSERT INTO ttrig(text) VALUES (@@global.init_slave); + SET @@global.init_slave = 'SELECT 3'; + INSERT INTO ttrig(text) VALUES (@@global.init_slave); + + # enumeration + SET @@global.slave_exec_mode = 'IDEMPOTENT'; + INSERT INTO ttrig(text) VALUES (@@global.slave_exec_mode); + SET @@global.slave_exec_mode = 'STRICT'; + INSERT INTO ttrig(text) VALUES (@@global.slave_exec_mode); + + # SESSION + + # boolean + SET @@sql_big_selects = ON; + INSERT INTO ttrig(truth) VALUES (@@sql_big_selects); + SET @@sql_big_selects = OFF; + INSERT INTO ttrig(truth) VALUES (@@sql_big_selects); + + # numeric + SET @@last_insert_id = 20; + INSERT INTO ttrig(num) VALUES (@@last_insert_id); + SET @@last_insert_id = 30; + INSERT INTO ttrig(num) VALUES (@@last_insert_id); + + # BOTH + + # boolean + SET @@global.low_priority_updates = ON; + SET @@local.low_priority_updates = OFF; + INSERT INTO ttrig(truth) VALUES (@@global.low_priority_updates); + INSERT INTO ttrig(truth) VALUES (@@local.low_priority_updates); + SET @@global.low_priority_updates = OFF; + SET @@local.low_priority_updates = ON; + INSERT INTO ttrig(truth) VALUES (@@global.low_priority_updates); + INSERT INTO ttrig(truth) VALUES (@@local.low_priority_updates); + + # numeric + SET @@global.default_week_format = 3; + SET @@local.default_week_format = 4; + INSERT INTO ttrig(num) VALUES (@@global.default_week_format); + INSERT INTO ttrig(num) VALUES (@@local.default_week_format); + SET @@global.default_week_format = 5; + SET @@local.default_week_format = 6; + INSERT INTO ttrig(num) VALUES (@@global.default_week_format); + INSERT INTO ttrig(num) VALUES (@@local.default_week_format); + + # text + SET @@global.lc_time_names = 'sv_SE'; + SET @@local.lc_time_names = 'sv_FI'; + INSERT INTO ttrig(text) VALUES (@@global.lc_time_names); + INSERT INTO ttrig(text) VALUES (@@local.lc_time_names); + SET @@global.lc_time_names = 'ar_TN'; + SET @@local.lc_time_names = 'ar_IQ'; + INSERT INTO ttrig(text) VALUES (@@global.lc_time_names); + INSERT INTO ttrig(text) VALUES (@@local.lc_time_names); + + # enum + SET @@global.sql_mode = ''; + SET @@local.sql_mode = 'IGNORE_SPACE,NO_AUTO_CREATE_USER'; + INSERT INTO ttrig(text) VALUES (@@global.sql_mode); + INSERT INTO ttrig(text) VALUES (@@local.sql_mode); + SET @@global.sql_mode = 'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION'; + SET @@local.sql_mode = 'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS'; + INSERT INTO ttrig(text) VALUES (@@global.sql_mode); + INSERT INTO ttrig(text) VALUES (@@local.sql_mode); + + # USER + + # numeric + SET @user_num = 20; + INSERT INTO ttrig(num) VALUES (@user_num); + SET @user_num = 30; + INSERT INTO ttrig(num) VALUES (@user_num); + + # string + SET @user_text = 'Bergsbrunna'; + INSERT INTO ttrig(text) VALUES (@user_text); + SET @user_text = 'Centrum'; + INSERT INTO ttrig(text) VALUES (@user_text); +END| +DELIMITER ;| + +INSERT INTO trigger_table VALUES ('bye.'); + + +--echo ==== Insert variables from a prepared statement ==== + +# GLOBAL + +# boolean +PREPARE p1 FROM 'SET @@global.relay_log_purge = ON'; +PREPARE p2 FROM 'INSERT INTO tprep(truth) VALUES (@@global.relay_log_purge)'; +PREPARE p3 FROM 'SET @@global.relay_log_purge = OFF'; +PREPARE p4 FROM 'INSERT INTO tprep(truth) VALUES (@@global.relay_log_purge)'; + +# numeric +PREPARE p5 FROM 'SET @@global.sync_binlog = 2000000'; +PREPARE p6 FROM 'INSERT INTO tprep(num) VALUES (@@global.sync_binlog)'; +PREPARE p7 FROM 'SET @@global.sync_binlog = 3000000'; +PREPARE p8 FROM 'INSERT INTO tprep(num) VALUES (@@global.sync_binlog)'; + +# string +PREPARE p9 FROM 'SET @@global.init_slave = \'SELECT 2\''; +PREPARE p10 FROM 'INSERT INTO tprep(text) VALUES (@@global.init_slave)'; +PREPARE p11 FROM 'SET @@global.init_slave = \'SELECT 3\''; +PREPARE p12 FROM 'INSERT INTO tprep(text) VALUES (@@global.init_slave)'; + +# enumeration +PREPARE p13 FROM 'SET @@global.slave_exec_mode = \'IDEMPOTENT\''; +PREPARE p14 FROM 'INSERT INTO tprep(text) VALUES (@@global.slave_exec_mode)'; +PREPARE p15 FROM 'SET @@global.slave_exec_mode = \'STRICT\''; +PREPARE p16 FROM 'INSERT INTO tprep(text) VALUES (@@global.slave_exec_mode)'; + +# SESSION + +# boolean +PREPARE p17 FROM 'SET @@sql_big_selects = ON'; +PREPARE p18 FROM 'INSERT INTO tprep(truth) VALUES (@@sql_big_selects)'; +PREPARE p19 FROM 'SET @@sql_big_selects = OFF'; +PREPARE p20 FROM 'INSERT INTO tprep(truth) VALUES (@@sql_big_selects)'; + +# numeric +PREPARE p21 FROM 'SET @@last_insert_id = 20'; +PREPARE p22 FROM 'INSERT INTO tprep(num) VALUES (@@last_insert_id)'; +PREPARE p23 FROM 'SET @@last_insert_id = 30'; +PREPARE p24 FROM 'INSERT INTO tprep(num) VALUES (@@last_insert_id)'; + +# BOTH + +# boolean +PREPARE p25 FROM 'SET @@global.low_priority_updates = ON'; +PREPARE p26 FROM 'SET @@local.low_priority_updates = OFF'; +PREPARE p27 FROM 'INSERT INTO tprep(truth) VALUES (@@global.low_priority_updates)'; +PREPARE p28 FROM 'INSERT INTO tprep(truth) VALUES (@@local.low_priority_updates)'; +PREPARE p29 FROM 'SET @@global.low_priority_updates = OFF'; +PREPARE p30 FROM 'SET @@local.low_priority_updates = ON'; +PREPARE p31 FROM 'INSERT INTO tprep(truth) VALUES (@@global.low_priority_updates)'; +PREPARE p32 FROM 'INSERT INTO tprep(truth) VALUES (@@local.low_priority_updates)'; + +# numeric +PREPARE p33 FROM 'SET @@global.default_week_format = 3'; +PREPARE p34 FROM 'SET @@local.default_week_format = 4'; +PREPARE p35 FROM 'INSERT INTO tprep(num) VALUES (@@global.default_week_format)'; +PREPARE p36 FROM 'INSERT INTO tprep(num) VALUES (@@local.default_week_format)'; +PREPARE p37 FROM 'SET @@global.default_week_format = 5'; +PREPARE p38 FROM 'SET @@local.default_week_format = 6'; +PREPARE p39 FROM 'INSERT INTO tprep(num) VALUES (@@global.default_week_format)'; +PREPARE p40 FROM 'INSERT INTO tprep(num) VALUES (@@local.default_week_format)'; + +# text +PREPARE p41 FROM 'SET @@global.lc_time_names = \'sv_SE\''; +PREPARE p42 FROM 'SET @@local.lc_time_names = \'sv_FI\''; +PREPARE p43 FROM 'INSERT INTO tprep(text) VALUES (@@global.lc_time_names)'; +PREPARE p44 FROM 'INSERT INTO tprep(text) VALUES (@@local.lc_time_names)'; +PREPARE p45 FROM 'SET @@global.lc_time_names = \'ar_TN\''; +PREPARE p46 FROM 'SET @@local.lc_time_names = \'ar_IQ\''; +PREPARE p47 FROM 'INSERT INTO tprep(text) VALUES (@@global.lc_time_names)'; +PREPARE p48 FROM 'INSERT INTO tprep(text) VALUES (@@local.lc_time_names)'; + +# enum +PREPARE p49 FROM 'SET @@global.sql_mode = \'\''; +PREPARE p50 FROM 'SET @@local.sql_mode = \'IGNORE_SPACE,NO_AUTO_CREATE_USER\''; +PREPARE p51 FROM 'INSERT INTO tprep(text) VALUES (@@global.sql_mode)'; +PREPARE p52 FROM 'INSERT INTO tprep(text) VALUES (@@local.sql_mode)'; +PREPARE p53 FROM 'SET @@global.sql_mode = \'NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION\''; +PREPARE p54 FROM 'SET @@local.sql_mode = \'NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS\''; +PREPARE p55 FROM 'INSERT INTO tprep(text) VALUES (@@global.sql_mode)'; +PREPARE p56 FROM 'INSERT INTO tprep(text) VALUES (@@local.sql_mode)'; + +# USER + +# numeric +PREPARE p57 FROM 'SET @user_num = 20'; +PREPARE p58 FROM 'INSERT INTO tprep(num) VALUES (@user_num)'; +PREPARE p59 FROM 'SET @user_num = 30'; +PREPARE p60 FROM 'INSERT INTO tprep(num) VALUES (@user_num)'; + +# string +PREPARE p61 FROM 'SET @user_text = \'Bergsbrunna\''; +PREPARE p62 FROM 'INSERT INTO tprep(text) VALUES (@user_text)'; +PREPARE p63 FROM 'SET @user_text = \'Centrum\''; +PREPARE p64 FROM 'INSERT INTO tprep(text) VALUES (@user_text)'; + +EXECUTE p1; EXECUTE p2; EXECUTE p3; EXECUTE p4; EXECUTE p5; EXECUTE p6; +EXECUTE p7; EXECUTE p8; EXECUTE p9; EXECUTE p10; EXECUTE p11; EXECUTE p12; +EXECUTE p13; EXECUTE p14; EXECUTE p15; EXECUTE p16; EXECUTE p17; EXECUTE p18; +EXECUTE p19; EXECUTE p20; EXECUTE p21; EXECUTE p22; EXECUTE p23; EXECUTE p24; +EXECUTE p25; EXECUTE p26; EXECUTE p27; EXECUTE p28; EXECUTE p29; EXECUTE p30; +EXECUTE p31; EXECUTE p32; EXECUTE p33; EXECUTE p34; EXECUTE p35; EXECUTE p36; +EXECUTE p37; EXECUTE p38; EXECUTE p39; EXECUTE p40; EXECUTE p41; EXECUTE p42; +EXECUTE p43; EXECUTE p44; EXECUTE p45; EXECUTE p46; EXECUTE p47; EXECUTE p48; +EXECUTE p49; EXECUTE p50; EXECUTE p51; EXECUTE p52; EXECUTE p53; EXECUTE p54; +EXECUTE p55; EXECUTE p56; EXECUTE p57; EXECUTE p58; EXECUTE p59; EXECUTE p60; +EXECUTE p61; EXECUTE p62; EXECUTE p63; EXECUTE p64; + +--sync_slave_with_master +--connection master + + +--echo ==== Results ==== + +# Show the result in table test.tstmt on master... +SELECT * FROM tstmt ORDER BY id; + +--sync_slave_with_master + +# ... then compare test.tstmt on master to the other tables on master and slave. +let $diff_tables= master:tstmt, master:tproc, master:tfunc, master:ttrig, master:tprep, slave:tstmt, slave:tproc, slave:tfunc, slave:ttrig, slave:tprep; +source include/diff_tables.inc; + + +--echo ==== Clean up ==== + +connection master; +DROP PROCEDURE proc; +DROP FUNCTION func; +DROP TRIGGER trig; +DROP TABLE tstmt, tproc, tfunc, ttrig, tprep, trigger_table; + +SET @@global.default_week_format= @m_default_week_format; +SET @@global.init_slave= @m_init_slave; +SET @@global.lc_time_names= @m_lc_time_names; +SET @@global.low_priority_updates= @m_low_priority_updates; +SET @@global.relay_log_purge= @m_relay_log_purge; +SET @@global.slave_exec_mode= @m_slave_exec_mode; +SET @@global.sql_mode= @m_sql_mode; +SET @@global.sync_binlog= @m_sync_binlog; + +connection slave; +SET @@global.default_week_format= @s_default_week_format; +SET @@global.init_slave= @s_init_slave; +SET @@global.lc_time_names= @s_lc_time_names; +SET @@global.low_priority_updates= @s_low_priority_updates; +SET @@global.relay_log_purge= @s_relay_log_purge; +SET @@global.slave_exec_mode= @s_slave_exec_mode; +SET @@global.sql_mode= @s_sql_mode; +SET @@global.sync_binlog= @s_sync_binlog; + +connection master; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_variables_stm.test b/mysql-test/suite/rpl/t/rpl_variables_stm.test new file mode 100644 index 00000000..1cc3cde3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_variables_stm.test @@ -0,0 +1,616 @@ +# ==== Purpose ==== +# +# In general, queries referencing @@system_variables are not +# considered safe to write to the binlog in statement-based logging +# mode. However, a few special cases are supported. +# +# This test verifies that queries referencing these specially +# supported variables are replicated correctly in statement mode. +# +# +# ==== Method ==== +# +# The test simply does a lot of "INSERT INTO t1 VALUES (@@variable)" +# and checks the result on the slave. +# +# Statements referencing a variable only replicate correctly in mixed +# and row mode: in row mode, the values inserted are replicated. In +# mixed mode, statements referencing a variable are marked as unsafe, +# meaning they will be replicated by row. In statement mode, the +# slave's value will be used and replication will break. (Except in a +# small number of special cases: random seeds, insert_id, and +# auto_increment are replicated). +# +# We test all replicated variables, from each of the following +# contexts: +# - directly +# - from a stored procedure +# - from a stored function +# - from a trigger +# - from a prepared statement +# +# For all variables where it is possible, we set the variable to one +# value on slave, and insert it on the master with two distinct +# values. +# +# The same insertions are made in four different tables using direct +# insert, stored procedure, stored function, or trigger. Then all +# eight resulting tables on master and slave are compared. +# +# +# ==== Related bugs ==== +# +# BUG#31168: @@hostname does not replicate +# +# +# ==== Related test cases ==== +# +# binlog.binlog_unsafe tests that a warning is issued if system +# variables are replicated in statement mode. +# +# rpl.rpl_variables verifies that variables which cannot be replicated +# safely in statement mode are replicated correctly in mixed or row +# mode. + +source include/have_binlog_format_mixed_or_statement.inc; +source include/master-slave.inc; + +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +--echo ==== Initialization ==== + +# Backup the values of global variables so that they can be restored +# later. + +connection master; +SET @m_auto_increment_increment= @@global.auto_increment_increment; +SET @m_auto_increment_offset= @@global.auto_increment_offset; +SET @m_character_set_client= @@global.character_set_client; +SET @m_collation_connection= @@global.collation_connection; +SET @m_collation_server= @@global.collation_server; +SET @m_time_zone= @@global.time_zone; +SET @m_lc_time_names= @@global.lc_time_names; +SET @m_collation_database= @@global.collation_database; + +connection slave; +SET @s_auto_increment_increment= @@global.auto_increment_increment; +SET @s_auto_increment_offset= @@global.auto_increment_offset; +SET @s_character_set_client= @@global.character_set_client; +SET @s_collation_connection= @@global.collation_connection; +SET @s_collation_server= @@global.collation_server; +SET @s_time_zone= @@global.time_zone; +SET @s_lc_time_names= @@global.lc_time_names; +SET @s_collation_database= @@global.collation_database; + +SET @@global.auto_increment_increment=19; +SET @@global.auto_increment_offset=4; +SET @@global.character_set_client='latin2'; +SET @@global.collation_connection='latin2_bin'; +SET @@global.collation_server='geostd8_general_ci'; +SET @@global.time_zone='Japan'; +SET @@global.lc_time_names='sv_SE'; +SET @@global.collation_database='geostd8_bin'; + +connection master; + +# Tables where everything happens. +CREATE TABLE tstmt (id INT AUTO_INCREMENT PRIMARY KEY, + num INT, + text VARCHAR(100)); +CREATE TABLE tproc LIKE tstmt; +CREATE TABLE tfunc LIKE tstmt; +CREATE TABLE ttrig LIKE tstmt; +CREATE TABLE tprep LIKE tstmt; + +# Table on which we put a trigger. +CREATE TABLE trigger_table (text CHAR(4)); + + +--echo ==== Insert variables directly ==== + +SET @@pseudo_thread_id= 4712; +INSERT INTO tstmt(num) VALUES (@@session.pseudo_thread_id); +SET @@pseudo_thread_id= 4713; +INSERT INTO tstmt(num) VALUES (@@session.pseudo_thread_id); + +SET @@foreign_key_checks= 0; +INSERT INTO tstmt(num) VALUES (@@session.foreign_key_checks); +SET @@foreign_key_checks= 1; +INSERT INTO tstmt(num) VALUES (@@session.foreign_key_checks); + +SET @@sql_auto_is_null= 0; +INSERT INTO tstmt(num) VALUES (@@session.sql_auto_is_null); +SET @@sql_auto_is_null= 1; +INSERT INTO tstmt(num) VALUES (@@session.sql_auto_is_null); + +SET @@unique_checks= 0; +INSERT INTO tstmt(num) VALUES (@@session.unique_checks); +SET @@unique_checks= 1; +INSERT INTO tstmt(num) VALUES (@@session.unique_checks); + +SET @@auto_increment_increment= 11; +INSERT INTO tstmt(num) VALUES (@@session.auto_increment_increment); +SET @@auto_increment_increment= 19; +INSERT INTO tstmt(num) VALUES (@@session.auto_increment_increment); + +SET @@auto_increment_offset= 13; +INSERT INTO tstmt(num) VALUES (@@session.auto_increment_offset); +SET @@auto_increment_offset= 17; +INSERT INTO tstmt(num) VALUES (@@session.auto_increment_offset); + +# reset these as they affect the index column +SET @@auto_increment_increment= 1; +SET @@auto_increment_offset= 1; + +SET @@character_set_client= 'cp1257'; +INSERT INTO tstmt(text) VALUES (@@session.character_set_client); +SET @@character_set_client= 'cp1256'; +INSERT INTO tstmt(text) VALUES (@@session.character_set_client); + +SET @@collation_connection= 'cp1251_ukrainian_ci'; +INSERT INTO tstmt(text) VALUES (@@session.collation_connection); +INSERT INTO tstmt(text) VALUES (@@session.character_set_connection); +SET @@collation_connection= 'cp1251_bulgarian_ci'; +INSERT INTO tstmt(text) VALUES (@@session.collation_connection); +INSERT INTO tstmt(text) VALUES (@@session.character_set_connection); + +SET @@collation_server= 'latin7_bin'; +INSERT INTO tstmt(text) VALUES (@@session.collation_server); +INSERT INTO tstmt(text) VALUES (@@session.character_set_server); +SET @@collation_server= 'latin7_general_cs'; +INSERT INTO tstmt(text) VALUES (@@session.collation_server); +INSERT INTO tstmt(text) VALUES (@@session.character_set_server); + +SET @@time_zone= 'Europe/Moscow'; +INSERT INTO tstmt(text) VALUES (@@session.time_zone); +SET @@time_zone= 'Universal'; +INSERT INTO tstmt(text) VALUES (@@session.time_zone); + +SET @@lc_time_names= 'sv_FI'; +INSERT INTO tstmt(text) VALUES (@@session.lc_time_names); +SET @@lc_time_names= 'no_NO'; +INSERT INTO tstmt(text) VALUES (@@session.lc_time_names); + +SET @@collation_database= 'latin7_general_ci'; +INSERT INTO tstmt(text) VALUES (@@session.collation_database); +INSERT INTO tstmt(text) VALUES (@@session.character_set_database); +SET @@collation_database= 'latin7_estonian_cs'; +INSERT INTO tstmt(text) VALUES (@@session.collation_database); +INSERT INTO tstmt(text) VALUES (@@session.character_set_database); + +SET @@timestamp= 47114711; +INSERT INTO tstmt(text) VALUES (@@session.timestamp); +SET @@timestamp= 47124712; +INSERT INTO tstmt(text) VALUES (@@session.timestamp); + +SET @@last_insert_id= 1616; +INSERT INTO tstmt(text) VALUES (@@session.last_insert_id); +SET @@last_insert_id= 1717; +INSERT INTO tstmt(text) VALUES (@@session.last_insert_id); + + +--echo ==== Insert variables from a stored procedure ==== + +DELIMITER |; +CREATE PROCEDURE proc() +BEGIN + + SET @@pseudo_thread_id= 4712; + INSERT INTO tproc(num) VALUES (@@session.pseudo_thread_id); + SET @@pseudo_thread_id= 4713; + INSERT INTO tproc(num) VALUES (@@session.pseudo_thread_id); + + SET @@foreign_key_checks= 0; + INSERT INTO tproc(num) VALUES (@@session.foreign_key_checks); + SET @@foreign_key_checks= 1; + INSERT INTO tproc(num) VALUES (@@session.foreign_key_checks); + + SET @@sql_auto_is_null= 0; + INSERT INTO tproc(num) VALUES (@@session.sql_auto_is_null); + SET @@sql_auto_is_null= 1; + INSERT INTO tproc(num) VALUES (@@session.sql_auto_is_null); + + SET @@unique_checks= 0; + INSERT INTO tproc(num) VALUES (@@session.unique_checks); + SET @@unique_checks= 1; + INSERT INTO tproc(num) VALUES (@@session.unique_checks); + + SET @@auto_increment_increment= 11; + INSERT INTO tproc(num) VALUES (@@session.auto_increment_increment); + SET @@auto_increment_increment= 19; + INSERT INTO tproc(num) VALUES (@@session.auto_increment_increment); + + SET @@auto_increment_offset= 13; + INSERT INTO tproc(num) VALUES (@@session.auto_increment_offset); + SET @@auto_increment_offset= 17; + INSERT INTO tproc(num) VALUES (@@session.auto_increment_offset); + + # reset these as they affect the index column + SET @@auto_increment_increment= 1; + SET @@auto_increment_offset= 1; + + SET @@character_set_client= 'cp1257'; + INSERT INTO tproc(text) VALUES (@@session.character_set_client); + SET @@character_set_client= 'cp1256'; + INSERT INTO tproc(text) VALUES (@@session.character_set_client); + + SET @@collation_connection= 'cp1251_ukrainian_ci'; + INSERT INTO tproc(text) VALUES (@@session.collation_connection); + INSERT INTO tproc(text) VALUES (@@session.character_set_connection); + SET @@collation_connection= 'cp1251_bulgarian_ci'; + INSERT INTO tproc(text) VALUES (@@session.collation_connection); + INSERT INTO tproc(text) VALUES (@@session.character_set_connection); + + SET @@collation_server= 'latin7_bin'; + INSERT INTO tproc(text) VALUES (@@session.collation_server); + INSERT INTO tproc(text) VALUES (@@session.character_set_server); + SET @@collation_server= 'latin7_general_cs'; + INSERT INTO tproc(text) VALUES (@@session.collation_server); + INSERT INTO tproc(text) VALUES (@@session.character_set_server); + + SET @@time_zone= 'Europe/Moscow'; + INSERT INTO tproc(text) VALUES (@@session.time_zone); + SET @@time_zone= 'Universal'; + INSERT INTO tproc(text) VALUES (@@session.time_zone); + + SET @@lc_time_names= 'sv_FI'; + INSERT INTO tproc(text) VALUES (@@session.lc_time_names); + SET @@lc_time_names= 'no_NO'; + INSERT INTO tproc(text) VALUES (@@session.lc_time_names); + + SET @@collation_database= 'latin7_general_ci'; + INSERT INTO tproc(text) VALUES (@@session.collation_database); + INSERT INTO tproc(text) VALUES (@@session.character_set_database); + SET @@collation_database= 'latin7_estonian_cs'; + INSERT INTO tproc(text) VALUES (@@session.collation_database); + INSERT INTO tproc(text) VALUES (@@session.character_set_database); + + SET @@timestamp= 47114711; + INSERT INTO tproc(text) VALUES (@@session.timestamp); + SET @@timestamp= 47124712; + INSERT INTO tproc(text) VALUES (@@session.timestamp); + + SET @@last_insert_id= 1616; + INSERT INTO tproc(text) VALUES (@@session.last_insert_id); + SET @@last_insert_id= 1717; + INSERT INTO tproc(text) VALUES (@@session.last_insert_id); + +END| +DELIMITER ;| + +CALL proc(); + + +--echo ==== Insert variables from a stored function ==== + +DELIMITER |; +CREATE FUNCTION func() +RETURNS INT +BEGIN + + SET @@pseudo_thread_id= 4712; + INSERT INTO tfunc(num) VALUES (@@session.pseudo_thread_id); + SET @@pseudo_thread_id= 4713; + INSERT INTO tfunc(num) VALUES (@@session.pseudo_thread_id); + + SET @@foreign_key_checks= 0; + INSERT INTO tfunc(num) VALUES (@@session.foreign_key_checks); + SET @@foreign_key_checks= 1; + INSERT INTO tfunc(num) VALUES (@@session.foreign_key_checks); + + SET @@sql_auto_is_null= 0; + INSERT INTO tfunc(num) VALUES (@@session.sql_auto_is_null); + SET @@sql_auto_is_null= 1; + INSERT INTO tfunc(num) VALUES (@@session.sql_auto_is_null); + + SET @@unique_checks= 0; + INSERT INTO tfunc(num) VALUES (@@session.unique_checks); + SET @@unique_checks= 1; + INSERT INTO tfunc(num) VALUES (@@session.unique_checks); + + SET @@auto_increment_increment= 11; + INSERT INTO tfunc(num) VALUES (@@session.auto_increment_increment); + SET @@auto_increment_increment= 19; + INSERT INTO tfunc(num) VALUES (@@session.auto_increment_increment); + + SET @@auto_increment_offset= 13; + INSERT INTO tfunc(num) VALUES (@@session.auto_increment_offset); + SET @@auto_increment_offset= 17; + INSERT INTO tfunc(num) VALUES (@@session.auto_increment_offset); + + # reset these as they affect the index column + SET @@auto_increment_increment= 1; + SET @@auto_increment_offset= 1; + + SET @@character_set_client= 'cp1257'; + INSERT INTO tfunc(text) VALUES (@@session.character_set_client); + SET @@character_set_client= 'cp1256'; + INSERT INTO tfunc(text) VALUES (@@session.character_set_client); + + SET @@collation_connection= 'cp1251_ukrainian_ci'; + INSERT INTO tfunc(text) VALUES (@@session.collation_connection); + INSERT INTO tfunc(text) VALUES (@@session.character_set_connection); + SET @@collation_connection= 'cp1251_bulgarian_ci'; + INSERT INTO tfunc(text) VALUES (@@session.collation_connection); + INSERT INTO tfunc(text) VALUES (@@session.character_set_connection); + + SET @@collation_server= 'latin7_bin'; + INSERT INTO tfunc(text) VALUES (@@session.collation_server); + INSERT INTO tfunc(text) VALUES (@@session.character_set_server); + SET @@collation_server= 'latin7_general_cs'; + INSERT INTO tfunc(text) VALUES (@@session.collation_server); + INSERT INTO tfunc(text) VALUES (@@session.character_set_server); + + SET @@time_zone= 'Europe/Moscow'; + INSERT INTO tfunc(text) VALUES (@@session.time_zone); + SET @@time_zone= 'Universal'; + INSERT INTO tfunc(text) VALUES (@@session.time_zone); + + SET @@lc_time_names= 'sv_FI'; + INSERT INTO tfunc(text) VALUES (@@session.lc_time_names); + SET @@lc_time_names= 'no_NO'; + INSERT INTO tfunc(text) VALUES (@@session.lc_time_names); + + SET @@collation_database= 'latin7_general_ci'; + INSERT INTO tfunc(text) VALUES (@@session.collation_database); + INSERT INTO tfunc(text) VALUES (@@session.character_set_database); + SET @@collation_database= 'latin7_estonian_cs'; + INSERT INTO tfunc(text) VALUES (@@session.collation_database); + INSERT INTO tfunc(text) VALUES (@@session.character_set_database); + + SET @@timestamp= 47114711; + INSERT INTO tfunc(text) VALUES (@@session.timestamp); + SET @@timestamp= 47124712; + INSERT INTO tfunc(text) VALUES (@@session.timestamp); + + SET @@last_insert_id= 1616; + INSERT INTO tfunc(text) VALUES (@@session.last_insert_id); + SET @@last_insert_id= 1717; + INSERT INTO tfunc(text) VALUES (@@session.last_insert_id); + + RETURN 0; +END| +DELIMITER ;| + +--disable_warnings +SELECT func(); +--enable_warnings + +--echo ==== Insert variables from a trigger ==== + +DELIMITER |; +CREATE TRIGGER trig +BEFORE INSERT ON trigger_table +FOR EACH ROW +BEGIN + + SET @@pseudo_thread_id= 4712; + INSERT INTO ttrig(num) VALUES (@@session.pseudo_thread_id); + SET @@pseudo_thread_id= 4713; + INSERT INTO ttrig(num) VALUES (@@session.pseudo_thread_id); + + SET @@foreign_key_checks= 0; + INSERT INTO ttrig(num) VALUES (@@session.foreign_key_checks); + SET @@foreign_key_checks= 1; + INSERT INTO ttrig(num) VALUES (@@session.foreign_key_checks); + + SET @@sql_auto_is_null= 0; + INSERT INTO ttrig(num) VALUES (@@session.sql_auto_is_null); + SET @@sql_auto_is_null= 1; + INSERT INTO ttrig(num) VALUES (@@session.sql_auto_is_null); + + SET @@unique_checks= 0; + INSERT INTO ttrig(num) VALUES (@@session.unique_checks); + SET @@unique_checks= 1; + INSERT INTO ttrig(num) VALUES (@@session.unique_checks); + + SET @@auto_increment_increment= 11; + INSERT INTO ttrig(num) VALUES (@@session.auto_increment_increment); + SET @@auto_increment_increment= 19; + INSERT INTO ttrig(num) VALUES (@@session.auto_increment_increment); + + SET @@auto_increment_offset= 13; + INSERT INTO ttrig(num) VALUES (@@session.auto_increment_offset); + SET @@auto_increment_offset= 17; + INSERT INTO ttrig(num) VALUES (@@session.auto_increment_offset); + + # reset these as they affect the index column + SET @@auto_increment_increment= 1; + SET @@auto_increment_offset= 1; + + SET @@character_set_client= 'cp1257'; + INSERT INTO ttrig(text) VALUES (@@session.character_set_client); + SET @@character_set_client= 'cp1256'; + INSERT INTO ttrig(text) VALUES (@@session.character_set_client); + + SET @@collation_connection= 'cp1251_ukrainian_ci'; + INSERT INTO ttrig(text) VALUES (@@session.collation_connection); + INSERT INTO ttrig(text) VALUES (@@session.character_set_connection); + SET @@collation_connection= 'cp1251_bulgarian_ci'; + INSERT INTO ttrig(text) VALUES (@@session.collation_connection); + INSERT INTO ttrig(text) VALUES (@@session.character_set_connection); + + SET @@collation_server= 'latin7_bin'; + INSERT INTO ttrig(text) VALUES (@@session.collation_server); + INSERT INTO ttrig(text) VALUES (@@session.character_set_server); + SET @@collation_server= 'latin7_general_cs'; + INSERT INTO ttrig(text) VALUES (@@session.collation_server); + INSERT INTO ttrig(text) VALUES (@@session.character_set_server); + + SET @@time_zone= 'Europe/Moscow'; + INSERT INTO ttrig(text) VALUES (@@session.time_zone); + SET @@time_zone= 'Universal'; + INSERT INTO ttrig(text) VALUES (@@session.time_zone); + + SET @@lc_time_names= 'sv_FI'; + INSERT INTO ttrig(text) VALUES (@@session.lc_time_names); + SET @@lc_time_names= 'no_NO'; + INSERT INTO ttrig(text) VALUES (@@session.lc_time_names); + + SET @@collation_database= 'latin7_general_ci'; + INSERT INTO ttrig(text) VALUES (@@session.collation_database); + INSERT INTO ttrig(text) VALUES (@@session.character_set_database); + SET @@collation_database= 'latin7_estonian_cs'; + INSERT INTO ttrig(text) VALUES (@@session.collation_database); + INSERT INTO ttrig(text) VALUES (@@session.character_set_database); + + SET @@timestamp= 47114711; + INSERT INTO ttrig(text) VALUES (@@session.timestamp); + SET @@timestamp= 47124712; + INSERT INTO ttrig(text) VALUES (@@session.timestamp); + + SET @@last_insert_id= 1616; + INSERT INTO ttrig(text) VALUES (@@session.last_insert_id); + SET @@last_insert_id= 1717; + INSERT INTO ttrig(text) VALUES (@@session.last_insert_id); + +END| +DELIMITER ;| + +--disable_warnings +INSERT INTO trigger_table VALUES ('bye.'); +--enable_warnings + + +--echo ==== Insert variables from a prepared statement ==== + +# GLOBAL + +PREPARE p1 FROM 'SET @@pseudo_thread_id= 4712'; +PREPARE p2 FROM 'INSERT INTO tprep(num) VALUES (@@session.pseudo_thread_id)'; +PREPARE p3 FROM 'SET @@pseudo_thread_id= 4713'; +PREPARE p4 FROM 'INSERT INTO tprep(num) VALUES (@@session.pseudo_thread_id)'; + +PREPARE p5 FROM 'SET @@foreign_key_checks= 0'; +PREPARE p6 FROM 'INSERT INTO tprep(num) VALUES (@@session.foreign_key_checks)'; +PREPARE p7 FROM 'SET @@foreign_key_checks= 1'; +PREPARE p8 FROM 'INSERT INTO tprep(num) VALUES (@@session.foreign_key_checks)'; + +PREPARE p9 FROM 'SET @@sql_auto_is_null= 0'; +PREPARE p10 FROM 'INSERT INTO tprep(num) VALUES (@@session.sql_auto_is_null)'; +PREPARE p11 FROM 'SET @@sql_auto_is_null= 1'; +PREPARE p12 FROM 'INSERT INTO tprep(num) VALUES (@@session.sql_auto_is_null)'; + +PREPARE p13 FROM 'SET @@unique_checks= 0'; +PREPARE p14 FROM 'INSERT INTO tprep(num) VALUES (@@session.unique_checks)'; +PREPARE p15 FROM 'SET @@unique_checks= 1'; +PREPARE p16 FROM 'INSERT INTO tprep(num) VALUES (@@session.unique_checks)'; + +PREPARE p17 FROM 'SET @@auto_increment_increment= 11'; +PREPARE p18 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_increment)'; +PREPARE p19 FROM 'SET @@auto_increment_increment= 19'; +PREPARE p20 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_increment)'; + +PREPARE p21 FROM 'SET @@auto_increment_offset= 13'; +PREPARE p22 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_offset)'; +PREPARE p23 FROM 'SET @@auto_increment_offset= 17'; +PREPARE p24 FROM 'INSERT INTO tprep(num) VALUES (@@session.auto_increment_offset)'; + +# reset these as they affect the index column +PREPARE p25 FROM 'SET @@auto_increment_increment= 1'; +PREPARE p26 FROM 'SET @@auto_increment_offset= 1'; + +PREPARE p27 FROM 'SET @@character_set_client= \'cp1257\''; +PREPARE p28 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_client)'; +PREPARE p29 FROM 'SET @@character_set_client= \'cp1256\''; +PREPARE p30 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_client)'; + +PREPARE p31 FROM 'SET @@collation_connection= \'cp1251_ukrainian_ci\''; +PREPARE p32 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_connection)'; +PREPARE p33 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_connection)'; +PREPARE p34 FROM 'SET @@collation_connection= \'cp1251_bulgarian_ci\''; +PREPARE p35 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_connection)'; +PREPARE p36 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_connection)'; + +PREPARE p37 FROM 'SET @@collation_server= \'latin7_bin\''; +PREPARE p38 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_server)'; +PREPARE p39 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_server)'; +PREPARE p40 FROM 'SET @@collation_server= \'latin7_general_cs\''; +PREPARE p41 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_server)'; +PREPARE p42 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_server)'; + +PREPARE p43 FROM 'SET @@time_zone= \'Europe/Moscow\''; +PREPARE p44 FROM 'INSERT INTO tprep(text) VALUES (@@session.time_zone)'; +PREPARE p45 FROM 'SET @@time_zone= \'Universal\''; +PREPARE p46 FROM 'INSERT INTO tprep(text) VALUES (@@session.time_zone)'; + +PREPARE p47 FROM 'SET @@lc_time_names= \'sv_FI\''; +PREPARE p48 FROM 'INSERT INTO tprep(text) VALUES (@@session.lc_time_names)'; +PREPARE p49 FROM 'SET @@lc_time_names= \'no_NO\''; +PREPARE p50 FROM 'INSERT INTO tprep(text) VALUES (@@session.lc_time_names)'; + +PREPARE p51 FROM 'SET @@collation_database= \'latin7_general_ci\''; +PREPARE p52 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_database)'; +PREPARE p53 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_database)'; +PREPARE p54 FROM 'SET @@collation_database= \'latin7_estonian_cs\''; +PREPARE p55 FROM 'INSERT INTO tprep(text) VALUES (@@session.collation_database)'; +PREPARE p56 FROM 'INSERT INTO tprep(text) VALUES (@@session.character_set_database)'; + +PREPARE p57 FROM 'SET @@timestamp= 47114711'; +PREPARE p58 FROM 'INSERT INTO tprep(text) VALUES (@@session.timestamp)'; +PREPARE p59 FROM 'SET @@timestamp= 47124712'; +PREPARE p60 FROM 'INSERT INTO tprep(text) VALUES (@@session.timestamp)'; + +PREPARE p61 FROM 'SET @@last_insert_id= 1616'; +PREPARE p62 FROM 'INSERT INTO tprep(text) VALUES (@@session.last_insert_id)'; +PREPARE p63 FROM 'SET @@last_insert_id= 1717'; +PREPARE p64 FROM 'INSERT INTO tprep(text) VALUES (@@session.last_insert_id)'; + +EXECUTE p1; EXECUTE p2; EXECUTE p3; EXECUTE p4; EXECUTE p5; EXECUTE p6; +EXECUTE p7; EXECUTE p8; EXECUTE p9; EXECUTE p10; EXECUTE p11; EXECUTE p12; +EXECUTE p13; EXECUTE p14; EXECUTE p15; EXECUTE p16; EXECUTE p17; EXECUTE p18; +EXECUTE p19; EXECUTE p20; EXECUTE p21; EXECUTE p22; EXECUTE p23; EXECUTE p24; +EXECUTE p25; EXECUTE p26; EXECUTE p27; EXECUTE p28; EXECUTE p29; EXECUTE p30; +EXECUTE p31; EXECUTE p32; EXECUTE p33; EXECUTE p34; EXECUTE p35; EXECUTE p36; +EXECUTE p37; EXECUTE p38; EXECUTE p39; EXECUTE p40; EXECUTE p41; EXECUTE p42; +EXECUTE p43; EXECUTE p44; EXECUTE p45; EXECUTE p46; EXECUTE p47; EXECUTE p48; +EXECUTE p49; EXECUTE p50; EXECUTE p51; EXECUTE p52; EXECUTE p53; EXECUTE p54; +EXECUTE p55; EXECUTE p56; EXECUTE p57; EXECUTE p58; EXECUTE p59; EXECUTE p60; +EXECUTE p61; EXECUTE p62; EXECUTE p63; EXECUTE p64; + +--sync_slave_with_master +--connection master + + +--echo ==== Results ==== + +# Show the result in table test.tstmt on master... +SELECT * FROM tstmt ORDER BY id; + +--sync_slave_with_master + +# ... then compare test.tstmt on master to the other tables on master and slave. +let $diff_tables= master:tstmt, master:tproc, master:tfunc, master:ttrig, master:tprep, slave:tstmt, slave:tproc, slave:tfunc, slave:ttrig, slave:tprep; +source include/diff_tables.inc; + + +--echo ==== Clean up ==== + +connection master; +DROP PROCEDURE proc; +DROP FUNCTION func; +DROP TRIGGER trig; +DROP TABLE tstmt, tproc, tfunc, ttrig, tprep, trigger_table; + +SET @@global.auto_increment_increment= @m_auto_increment_increment; +SET @@global.auto_increment_offset= @m_auto_increment_offset; +SET @@global.character_set_client= @m_character_set_client; +SET @@global.collation_connection= @m_collation_connection; +SET @@global.collation_server= @m_collation_server; +SET @@global.time_zone= @m_time_zone; +SET @@global.lc_time_names= @m_lc_time_names; +SET @@global.collation_database= @m_collation_database; + +connection slave; +SET @@global.auto_increment_increment= @s_auto_increment_increment; +SET @@global.auto_increment_offset= @s_auto_increment_offset; +SET @@global.character_set_client= @s_character_set_client; +SET @@global.collation_connection= @s_collation_connection; +SET @@global.collation_server= @s_collation_server; +SET @@global.time_zone= @s_time_zone; +SET @@global.lc_time_names= @s_lc_time_names; +SET @@global.collation_database= @s_collation_database; + +connection master; +sync_slave_with_master; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_view.test b/mysql-test/suite/rpl/t/rpl_view.test new file mode 100644 index 00000000..987b93a1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_view.test @@ -0,0 +1,171 @@ +# NYI - row-based cannot use CREATE ... SELECT + +source include/master-slave.inc; +--disable_warnings +drop table if exists t1,v1; +drop view if exists t1,v1; +sync_slave_with_master; +reset master; +--enable_warnings + +# +# Check that creation drop of view is replicated, also check replication of +# updating of view +# +connection master; +create table t1 (a int); +insert into t1 values (1); +create view v1 as select a from t1; +insert into v1 values (2); +select * from v1 order by a; +sync_slave_with_master; +# view already have to be on slave +select * from v1 order by a; +connection master; +update v1 set a=3 where a=1; +select * from v1 order by a; +sync_slave_with_master; +select * from v1 order by a; +connection master; +delete from v1 where a=2; +select * from v1 order by a; +sync_slave_with_master; +select * from v1 order by a; +connection master; +# 'alter view' internally maped to creation, but still check that it works +alter view v1 as select a as b from t1; +sync_slave_with_master; +select * from v1 order by 1; +connection master; +drop view v1; +sync_slave_with_master; +#error, because view have to be removed from slave +-- error 1146 +select * from v1 order by a; +connection master; +drop table t1; +sync_slave_with_master; +# Change Author: JBM +# Change Date: 2005-12-22 +# Change: Commented out binlog events to work with SBR and RBR +#--replace_column 2 # 5 # +# show binlog events limit 1,100; + +# +# BUG#20438: CREATE statements for views, stored routines and triggers can be +# not replicable. +# + +--echo +--echo ---> Test for BUG#20438 + +# Prepare environment. + +--echo +--echo ---> Preparing environment... +--connection master + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP VIEW IF EXISTS v1; +--enable_warnings + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +--echo +--connection master + +# Test. + +--echo +--echo ---> Creating objects... + +CREATE TABLE t1(c INT); + +/*!50003 CREATE VIEW v1 AS SELECT * FROM t1 */; + +--echo +--echo ---> Inserting value... + +INSERT INTO t1 VALUES(1); + +--echo +--echo ---> Checking on master... + +SELECT * FROM t1; + +--echo +--echo ---> Synchronizing slave with master... + +--sync_slave_with_master + +SELECT * FROM t1; + +# Cleanup. + +--connection master + +--echo +--echo ---> Cleaning up... + +DROP VIEW v1; +DROP TABLE t1; + +--sync_slave_with_master +--connection master + +# +# BUG#19419: "VIEW: View that the column name is different +# by master and slave is made". +# +connection master; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; + +sync_slave_with_master; +explain v1; +show create table v1; +select * from v1; + +connection master; +drop table t1; +drop view v1; + +sync_slave_with_master; + +# +# BUG#28244 CREATE VIEW breaks replication when view exists +# +connection master; +CREATE TABLE t1(a INT); +CREATE VIEW v1 AS SELECT * FROM t1; +--error ER_TABLE_EXISTS_ERROR +CREATE VIEW v1 AS SELECT * FROM t1; +DROP VIEW v1; +DROP TABLE t1; +sync_slave_with_master; + +# +# Bug#32575 Parse error of stmt with extended comments on slave side +# Verify that 'CREATE VIEW' with comments is properly logged to binlog +connection master; +CREATE TABLE t1 (a INT); +--echo # create view as output from mysqldump 10.11 (5.0.62) +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ +/*!50001 VIEW `v1` AS select `t1`.`a` AS `a` from `t1` where (`t1`.`a` < 3) */ +/*!50002 WITH CASCADED CHECK OPTION */; +SHOW CREATE VIEW v1; +sync_slave_with_master; +SHOW CREATE VIEW v1; +connection master; +DROP VIEW v1; +DROP TABLE t1; +sync_slave_with_master; + +--echo End of 5.0 tests +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_view_debug.test b/mysql-test/suite/rpl/t/rpl_view_debug.test new file mode 100644 index 00000000..08036924 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_view_debug.test @@ -0,0 +1,35 @@ +--source include/have_debug.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-6409 CREATE VIEW replication problem if error occurs in mysql_register_view +--echo # +--echo # Check the bug where if an error occurs in mysql_register_view the view +--echo # is still replicated to the slave +--echo # +connection master; +create table t1 (a int); +insert into t1 values (1); +create view v1 as select a from t1; +insert into v1 values (2); +select * from v1 order by a; +sync_slave_with_master; + +# view already has to be on slave +show tables; +connection master; +SET @saved_dbug = @@SESSION.debug_dbug; +set @@debug_dbug="d,simulate_register_view_failure"; + +--error ER_OUT_OF_RESOURCES +CREATE VIEW v2 as SELECT * FROM t1; + +show tables; +sync_slave_with_master; +show tables; + +connection master; +DROP VIEW IF EXISTS v1; +DROP TABLE t1; +SET debug_dbug= @saved_dbug; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_view_multi.test b/mysql-test/suite/rpl/t/rpl_view_multi.test new file mode 100644 index 00000000..c8af44bf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_view_multi.test @@ -0,0 +1,131 @@ +# +# This file contains test cases for bugs which involve views, several +# concurren connections and manifest themselves as wrong binary log +# sequence which results in broken replication. In principle we are +# mostly interested in SBR here but this test will also work with RBR. +# +--source include/master-slave.inc + +--echo # +--echo # Bug #25144 "replication / binlog with view breaks". +--echo # Statements that used views didn't ensure that view were not modified +--echo # during their execution. Indeed this led to incorrect binary log with +--echo # statement based logging and as result to broken replication. +--echo # +# +# Suppress "unsafe" warnings. +# +disable_query_log; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +enable_query_log; + + +--disable_warnings +drop tables if exists t1, t2; +drop view if exists v1; +--enable_warnings +--echo # Syncing slave with master +--sync_slave_with_master + +connect (master2,127.0.0.1,root,,test,$MASTER_MYPORT,); + +connection master; +create table t1 (i int); +create table t2 (i int); +create view v1 as select * from t1; + +--echo # First we try to concurrently execute statement that uses view +--echo # and statement that drops it. We use "user" locks as means to +--echo # suspend execution of first statement once it opens our view. +select get_lock("lock_bg25144", 1); + +connection master1; +--send insert into v1 values (get_lock("lock_bg25144", 100)) + +connection master2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "User lock" and info like "insert into v1 %lock_bg25144%"; +--source include/wait_condition.inc +--send drop view v1 + +connection master; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock" and info = "drop view v1"; +--source include/wait_condition.inc + +select release_lock("lock_bg25144"); + +connection master1; +--disable_warnings +--reap +--enable_warnings +select release_lock("lock_bg25144"); + +connection master2; +--reap + +connection master; +--echo # Check that insertion through view did happen. +select * from t1; +--echo # Syncing slave with master +--sync_slave_with_master +--echo # Check that slave was able to replicate this sequence +--echo # which means that we got correct binlog order. +select * from t1; + +connection master; +--echo # Now we will repeat the test by trying concurrently execute +--echo # statement that uses a view and statement that alters it. +create view v1 as select * from t1; + +select get_lock("lock_bg25144", 1); + +connection master1; +--send insert into v1 values (get_lock("lock_bg25144", 100)) + +connection master2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "User lock" and info like "insert into v1 %lock_bg25144%"; +--source include/wait_condition.inc +--send alter view v1 as select * from t2 + +connection master; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock" and + info = "alter view v1 as select * from t2"; +--source include/wait_condition.inc + +select release_lock("lock_bg25144"); + +connection master1; +--disable_warnings +--reap +--enable_warnings +select release_lock("lock_bg25144"); + +connection master2; +--reap + +connection master; + +--echo # Second insertion should go to t1 as well. +select * from t1; +select * from t2; + +--echo # Syncing slave with master +--sync_slave_with_master +--echo # Now let us check that statements were logged in proper order +--echo # So we have same result on slave. +select * from t1; +select * from t2; + +connection master; +drop table t1, t2; +drop view v1; +--echo # Syncing slave with master +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa-master.opt b/mysql-test/suite/rpl/t/rpl_xa-master.opt new file mode 100644 index 00000000..6794216d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa-master.opt @@ -0,0 +1 @@ +--binlog-ignore-db=test_ign diff --git a/mysql-test/suite/rpl/t/rpl_xa.inc b/mysql-test/suite/rpl/t/rpl_xa.inc new file mode 100644 index 00000000..38344da5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa.inc @@ -0,0 +1,355 @@ +# +# This "body" file checks general properties of XA transaction replication +# as of MDEV-7974. +# Parameters: +# --let rpl_xa_check= SELECT ... +# +connection master; +create table t1 (a int, b int) engine=InnoDB; +insert into t1 values(0, 0); +xa start 't'; +insert into t1 values(1, 2); +xa end 't'; +xa prepare 't'; +xa commit 't'; + +sync_slave_with_master; +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; + +connection master; + +xa start 't'; +insert into t1 values(3, 4); +xa end 't'; +xa prepare 't'; +xa rollback 't'; + +sync_slave_with_master; +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; + +connection master; +--disable_warnings +SET pseudo_slave_mode=1; +--enable_warnings +create table t2 (a int) engine=InnoDB; +xa start 't'; +insert into t1 values (5, 6); +xa end 't'; +xa prepare 't'; +xa start 's'; +insert into t2 values (0); +xa end 's'; +xa prepare 's'; +--source include/save_master_gtid.inc + +connection slave; +source include/sync_with_master_gtid.inc; +if ($rpl_xa_check) +{ + --eval $rpl_xa_check + if ($rpl_xa_verbose) + { + --eval SELECT $rpl_xa_check_lhs + --eval SELECT $rpl_xa_check_rhs + } +} +sorted_result; +xa recover; + +connection master; +xa commit 't'; +xa commit 's'; +--disable_warnings +SET pseudo_slave_mode=0; +--enable_warnings +sync_slave_with_master; +let $diff_tables= master:t1, slave:t1; +source include/diff_tables.inc; +let $diff_tables= master:t2, slave:t2; +source include/diff_tables.inc; + +# +# Read-only XA remains prepared after disconnect and must rollback at XA-complete +# after recoonect. To the read-only also belongs non-transactional engine XA. +# +--connection master + +--echo *** At the start of read-only section gtid list is: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + + +set @query1="select 1"; +set @query2="select count(*) into @s2 from t1"; +--let $ro_cases=2 +--let $db=test + +# No disconnect +--let $p_trx=$ro_cases +while ($p_trx) +{ +--connection master + --let $xid=ro_$p_trx + --let $query=`SELECT @query$p_trx` + --source rpl_create_xa_prepared.inc + --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` + --error 0 + --disable_query_log + --disable_result_log + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log + + --disconnect master_$xid + --source include/wait_until_disconnected.inc + + --dec $p_trx +} + + +--let $p_trx=$ro_cases +# With diconnect +while ($p_trx) +{ +--connection master + --let $xid=ro_$p_trx + --let $query=`SELECT @query$p_trx` + --source rpl_create_xa_prepared.inc + + --disconnect master_$xid + --source include/wait_until_disconnected.inc + + --dec $p_trx +} + +--echo *** $ro_cases prepared xa:s must be in the list: +--connection master +sorted_result; +xa recover; + +--let $p_trx=$ro_cases +while ($p_trx) +{ + --let $xid=ro_$p_trx + --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` + --disable_query_log + --disable_result_log + --error ER_XA_RBROLLBACK + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log + + --dec $p_trx +} +--echo *** Zero prepared xa:s must be in the list: +xa recover; + +--echo *** At the end of read-only section gtid list has 0 more compare with previous check: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + + +# +# XA logging cases while some of XA resources are read-only +# +# A1. Binlog filter + + +--let $db=test_ign +--eval create database $db +set @@sql_log_bin = 0; +--eval create table $db.t (a int) engine=InnoDB +set @@sql_log_bin = 1; + +--let $xid=rw_no_binlog +--let $query=insert into $db.t set a=1 +--source rpl_create_xa_prepared.inc +--disconnect master_$xid +--source include/wait_until_disconnected.inc + +--echo *** $xid must be in the list: +--connection master +xa recover; + +--let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` +--error 0 +--disable_query_log +--disable_result_log +--eval xa $complete '$xid' +--enable_result_log +--enable_query_log + +--echo *** Zero must be in the list: +--connection master +xa recover; +# restore for the following tests +--let $db=test + +--echo *** At the end of --binlog-ignore-db section gtid list has 2 more: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + +# +# A2. Opposite to A1, ineffective execution in Engine may create a +# binlog transaction +# +connection master; +create table t3 (a int) engine=innodb; + +--echo *** the disconnected prepare case +--let $xid=rw_binlog_only +--let $query=delete from t3 +--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,) + set @@binlog_format=statement; + # --source rpl_create_xa_prepared.inc + --eval xa start '$xid' + --eval $query + --eval xa end '$xid' + --eval xa prepare '$xid' + + --disconnect master_$xid + --source include/wait_until_disconnected.inc + +connection master; +--echo *** $xid must be in the list: +xa recover; + + --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` + --disable_query_log + --disable_result_log + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log + +--echo *** Zero must be in the list: +xa recover; + +--echo *** the same connection complete case. +connection master; + --let $xid=rw_binlog_only + --let $query=delete from t3 +--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,) + set @@binlog_format=statement; + # --source rpl_create_xa_prepared.inc + --eval xa start '$xid' + --eval $query + --eval xa end '$xid' + --eval xa prepare '$xid' + +--echo *** $xid must be in the list: +xa recover; + +--disable_query_log + --disable_result_log + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log +--disconnect master_$xid +--source include/wait_until_disconnected.inc + +--echo *** Zero must be in the list: +--connection master +xa recover; + +--echo *** At the end of ineffective in engine section gtid list has 5 more: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + +# +# A3 MyISAM "xa" logs empty XA-prepare group, followed by +# an XA-complete event +create table tm (a int) engine=myisam; + +# No disconnect +--connection master + --let $xid=rw_myisam + --let $query=insert into tm set a=1 + --source rpl_create_xa_prepared.inc + --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` + --error 0 + --disable_query_log + --disable_result_log + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log + + --disconnect master_$xid + --source include/wait_until_disconnected.inc + +# With diconnect +--connection master + --source rpl_create_xa_prepared.inc + --disconnect master_$xid + --source include/wait_until_disconnected.inc + +--echo *** $xid prepared must be in the list: +--connection master +xa recover; + + --let $complete=`select if(floor(rand()*10)%2,'COMMIT','ROLLBACK')` + --disable_query_log + --disable_result_log + --eval xa $complete '$xid' + --enable_result_log + --enable_query_log + +--echo *** Zero prepared xa:s must be in the list: +xa recover; + +--echo *** At the end of MyISAM "xa" section gtid list has 7 more compare with previous check: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + + +# B. Session binlog disable does not log even empty XA-prepare +# Therefore XA-complete should be also run in sql_log_bin-OFF environment. + +--let $db=test +--let $xid=skip_binlog +--let $query=insert into t2 values(1) +--connect (master_$xid, 127.0.0.1,root,,$db,$MASTER_MYPORT,) +set @@session.sql_log_bin = OFF; +--eval xa start '$xid' + --eval $query +--eval xa end '$xid' +--eval xa prepare '$xid' + +--disconnect master_$xid +--source include/wait_until_disconnected.inc + +--echo *** $xid must be in the list: +--connection master +xa recover; + +# now commit it carefully to avoid binlogging as the prepare part did +set @@session.sql_log_bin = OFF; +--eval xa rollback '$xid' +set @@session.sql_log_bin = ON; +--source include/save_master_gtid.inc + +--echo *** Zero must be in the list: +--connection master +xa recover; + +--echo *** At the end of skip_log_binb section gtid list has 0 more: +flush logs; +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--source include/show_gtid_list.inc + +# +# sync slave successfully to prove its consistency +# +--connection slave +source include/sync_with_master_gtid.inc; + + +connection master; +--eval drop database test_ign +drop table t1, t2, t3, tm; diff --git a/mysql-test/suite/rpl/t/rpl_xa.test b/mysql-test/suite/rpl/t/rpl_xa.test new file mode 100644 index 00000000..05a1abe5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa.test @@ -0,0 +1,5 @@ +source include/have_innodb.inc; +source include/master-slave.inc; + +source rpl_xa.inc; +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt b/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt new file mode 100644 index 00000000..4602a43c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_gap_lock-slave.opt @@ -0,0 +1 @@ +--transaction-isolation=READ-COMMITTED diff --git a/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test b/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test new file mode 100644 index 00000000..9c48891b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_gap_lock.test @@ -0,0 +1,137 @@ +# ==== Purpose ==== +# +# This test will generate two XA transactions on the master in a way that +# they will block each other on the slave if the transaction isolation level +# used by the slave applier is more restrictive than the READ COMMITTED one. +# +# Consider: +# E=execute, P=prepare, C=commit; +# 1=first transaction, 2=second transaction; +# +# Master does: E1, E2, P2, P1, C1, C2 +# Slave does: E2, P2, E1, P1, C1, C2 +# +# The transactions are designed so that, if the applier transaction isolation +# level is more restrictive than the READ COMMITTED, E1 will be blocked on +# the slave waiting for gap locks to be released. +# +# Step 1 +# +# The test will verify that the transactions don't block each other because +# the applier thread automatically changed the isolation level. +# +# Step 2 +# +# The test will verify that applying master's binary log dump in slave doesn't +# block because mysqlbinlog is informing the isolation level to be used. +# +# ==== Related Bugs and Worklogs ==== +# +# BUG#25040331: INTERLEAVED XA TRANSACTIONS MAY DEADLOCK SLAVE APPLIER WITH +# REPEATABLE READ +# +--source include/have_debug.inc +--source include/have_innodb.inc +# The test case only make sense for RBR +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--connection slave +# To hit the issue, we need to split the data in two pages. +# This global variable will help us. +SET @saved_innodb_limit_optimistic_insert_debug = @@GLOBAL.innodb_limit_optimistic_insert_debug; +SET @@GLOBAL.innodb_limit_optimistic_insert_debug = 2; + +# +# Step 1 - Using async replication +# + +# Let's generate the workload on the master +--connection master +CREATE TABLE t1 ( + c1 INT NOT NULL, + KEY(c1) +) ENGINE=InnoDB; + +CREATE TABLE t2 ( + c1 INT NOT NULL, + FOREIGN KEY(c1) REFERENCES t1(c1) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1), (3), (4); + +--connection master1 +XA START 'XA1'; +INSERT INTO t1 values(2); +XA END 'XA1'; + +# This transaction will reference the gap where XA1 +# was inserted, and will be prepared and committed +# before XA1, so the slave will prepare it (but will +# not commit it) before preparing XA1. +--connection master +XA START 'XA2'; +INSERT INTO t2 values(3); +XA END 'XA2'; + +# The XA2 prepare should be binary logged first +XA PREPARE 'XA2'; + +# The XA1 prepare should be binary logged +# after XA2 prepare and before XA2 commit. +--connection master1 +XA PREPARE 'XA1'; + +# The commit order doesn't matter much for the issue being tested. +XA COMMIT 'XA1'; +--connection master +XA COMMIT 'XA2'; + +# Everything is fine if the slave can sync with the master. +--source include/sync_slave_sql_with_master.inc + +# +# Step 2 - Using mysqlbinlog dump to restore the salve +# +--source include/stop_slave.inc +DROP TABLE t2, t1; +RESET SLAVE; +RESET MASTER; + +--connection master +--let $master_data_dir= `SELECT @@datadir` +--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1) +--let $mysql_server= $MYSQL --defaults-group-suffix=.2 +--echo Restore binary log from the master into the slave +--exec $MYSQL_BINLOG --force-if-open $master_data_dir/$master_log_file | $mysql_server + +--let $diff_tables= master:test.t1, slave:test.t1 +--source include/diff_tables.inc +--let $diff_tables= master:test.t2, slave:test.t2 +--source include/diff_tables.inc + +# +# Cleanup +# +--let $master_file= query_get_value(SHOW MASTER STATUS, File, 1) +--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +DROP TABLE t2, t1; + +## When GTID_MODE=OFF, we need to skip already applied transactions +--connection slave +#--let $gtid_mode= `SELECT @@GTID_MODE` +#if ($gtid_mode == OFF) +#{ +# --disable_query_log +# --disable_result_log +# --eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos +# --enable_result_log +# --enable_query_log +#} +--replace_result $master_file LOG_FILE $master_pos LOG_POS +--eval CHANGE MASTER TO MASTER_LOG_FILE='$master_file', MASTER_LOG_POS=$master_pos + +SET @@GLOBAL.innodb_limit_optimistic_insert_debug = @saved_innodb_limit_optimistic_insert_debug; +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt new file mode 100644 index 00000000..6794216d --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine-master.opt @@ -0,0 +1 @@ +--binlog-ignore-db=test_ign diff --git a/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test new file mode 100644 index 00000000..b8349376 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_gtid_pos_auto_engine.test @@ -0,0 +1,29 @@ +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +call mtr.add_suppression("The automatically created table.*name may not be entirely in lowercase"); + +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid=slave_pos; + +SET @@global.gtid_pos_auto_engines="innodb"; +--source include/start_slave.inc +--let $rpl_xa_check_lhs= @@global.gtid_slave_pos +--let $rpl_xa_check_rhs= CONCAT(domain_id,"-",server_id,"-",seq_no) FROM mysql.gtid_slave_pos WHERE seq_no = (SELECT DISTINCT max(seq_no) FROM mysql.gtid_slave_pos) +--let $rpl_xa_check=SELECT $rpl_xa_check_lhs = $rpl_xa_check_rhs +--source rpl_xa.inc + +--connection slave +--source include/stop_slave.inc +SET @@global.gtid_pos_auto_engines=""; +SET @@session.sql_log_bin=0; +DROP TABLE mysql.gtid_slave_pos_InnoDB; +if (`SHOW COUNT(*) WARNINGS`) +{ + show tables in mysql like 'gtid_slave_pos%'; +} +SET @@session.sql_log_bin=1; +--source include/start_slave.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test new file mode 100644 index 00000000..28d18936 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect.test @@ -0,0 +1,297 @@ +# BUG #12161 Xa recovery and client disconnection +# the test verifies that +# a. disconnection does not lose a prepared transaction +# so it can be committed from another connection +# c. the prepared transaction is logged +# d. interleaved prepared transactions are correctly applied on the slave. + +# +# Both replication format are checked through explict +# set @@binlog_format in the test. +# +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +# +# Prepared XA can't get available to an external connection +# until a connection, that either leaves actively or is killed, +# has completed a necessary part of its cleanup. +# Selecting from P_S.threads provides a method to learn that. +# +--source include/have_perfschema.inc +--source include/master-slave.inc + +--connection master +call mtr.add_suppression("Found 2 prepared XA transactions"); +CREATE VIEW v_processlist as SELECT * FROM performance_schema.threads where type = 'FOREGROUND'; + +CREATE DATABASE d1; +CREATE DATABASE d2; + +CREATE TABLE d1.t (a INT) ENGINE=innodb; +CREATE TABLE d2.t (a INT) ENGINE=innodb; + +connect (master_conn1, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--let $conn_id=`SELECT connection_id()` +SET @@session.binlog_format= statement; +XA START '1-stmt'; +INSERT INTO d1.t VALUES (1); +XA END '1-stmt'; +XA PREPARE '1-stmt'; + +--disconnect master_conn1 + +--connection master + +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +connect (master_conn2, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--let $conn_id=`SELECT connection_id()` +SET @@session.binlog_format= row; +XA START '1-row'; +INSERT INTO d2.t VALUES (1); +XA END '1-row'; +XA PREPARE '1-row'; + +--disconnect master_conn2 + +--connection master +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +XA START '2'; +INSERT INTO d1.t VALUES (2); +XA END '2'; +XA PREPARE '2'; +XA COMMIT '2'; + +XA COMMIT '1-row'; +XA COMMIT '1-stmt'; +source include/show_binlog_events.inc; + +# the proof: slave is in sync with the table updated by the prepared transactions. +--source include/sync_slave_sql_with_master.inc + +--source include/stop_slave.inc + +# +# Recover with Master server restart +# +--connection master + +connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--connection master2 +SET @@session.binlog_format= statement; +XA START '3-stmt'; +INSERT INTO d1.t VALUES (3); +XA END '3-stmt'; +XA PREPARE '3-stmt'; +--disconnect master2 + +connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--connection master2 +SET @@session.binlog_format= row; +XA START '3-row'; +INSERT INTO d2.t VALUES (4); +XA END '3-row'; +XA PREPARE '3-row'; +--disconnect master2 + +--connection master + +# +# Testing read-only +# +connect (master2, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--connection master2 +XA START '4'; +SELECT * FROM d1.t; +XA END '4'; +XA PREPARE '4'; +--disconnect master2 + +# +# Logging few disconnected XA:s for replication. +# +--let $bulk_trx_num=10 +--let $i = $bulk_trx_num + +while($i > 0) +{ + --connect (master_bulk_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,) + --let $conn_id=`SELECT connection_id()` + + --eval XA START 'bulk_trx_$i' + --eval INSERT INTO d1.t VALUES ($i) + --eval INSERT INTO d2.t VALUES ($i) + --eval XA END 'bulk_trx_$i' + --eval XA PREPARE 'bulk_trx_$i' + + --disconnect master_bulk_conn$i + + --connection master + --let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id + --source include/wait_condition.inc + + --dec $i +} + +# +# Prove the slave applier is capable to resume the prepared XA:s +# upon its restart. +# +--connection slave +--source include/start_slave.inc +--connection master +--source include/sync_slave_sql_with_master.inc +--source include/stop_slave.inc + +--connection master +--let $i = $bulk_trx_num +while($i > 0) +{ + --let $command=COMMIT + if (`SELECT $i % 2`) + { + --let $command=ROLLBACK + } + --eval XA $command 'bulk_trx_$i' + --dec $i +} + +--let $rpl_server_number= 1 +--source include/rpl_restart_server.inc + +--connection slave +--source include/start_slave.inc + +--connection master +--echo *** '3-stmt','3-row' xa-transactions must be in the list *** +XA RECOVER; +XA COMMIT '3-stmt'; +XA ROLLBACK '3-row'; + +--source include/sync_slave_sql_with_master.inc + +# +# Testing replication with marginal XID values and in two formats. +# + +--connection master +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +# Max size XID incl max value of formatID +--let $formatid_range=`SELECT (1<<31)` +--let $max_formatid=`SELECT (1<<31) - 1` + +connect (master_conn2, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--let $conn_id=`SELECT connection_id()` + +--let $gtrid=0123456789012345678901234567890123456789012345678901234567890124 +--let $bqual=0123456789012345678901234567890123456789012345678901234567890124 +--eval XA START '$gtrid','$bqual',$max_formatid + INSERT INTO d1.t VALUES (64); +--eval XA END '$gtrid','$bqual',$max_formatid +--eval XA PREPARE '$gtrid','$bqual',$max_formatid + +--disconnect master_conn2 + +--connection master +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +# Max size XID with non-ascii chars +connect (master_conn3, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--let $conn_id=`SELECT connection_id()` + +--let $gtrid_hex=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +--let $bqual_hex=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +--eval XA START X'$gtrid_hex',X'$bqual_hex',0 + INSERT INTO d1.t VALUES (0); +--eval XA END X'$gtrid_hex',X'$bqual_hex',0 +--eval XA PREPARE X'$gtrid_hex',X'$bqual_hex',0 + +--disconnect master_conn3 + +--connection master +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +# Random XID +--disable_query_log + +connect (master_conn4, 127.0.0.1,root,,test,$MASTER_MYPORT,); +--let $conn_id=`SELECT connection_id()` + +--let $gtridlen=`SELECT 2*(1 + round(rand()*100) % 31)` +--let $bquallen=`SELECT 2*(1 + round(rand()*100) % 31)` +--let $gtrid_rand=`SELECT substring(concat(MD5(rand()), MD5(rand())), 1, $gtridlen)` +--let $bqual_rand=`SELECT substring(concat(MD5(rand()), MD5(rand())), 1, $bquallen)` +--let $formt_rand=`SELECT floor((rand()*10000000000) % $formatid_range)` +--eval XA START X'$gtrid_rand',X'$bqual_rand',$formt_rand + INSERT INTO d1.t VALUES (0); +--eval XA END X'$gtrid_rand',X'$bqual_rand',$formt_rand +--eval XA PREPARE X'$gtrid_rand',X'$bqual_rand',$formt_rand + +--enable_query_log + +--disconnect master_conn4 + +--connection master +--let $wait_condition= SELECT count(*) = 0 FROM v_processlist WHERE PROCESSLIST_ID = $conn_id +--source include/wait_condition.inc + +--eval XA COMMIT '$gtrid','$bqual',$max_formatid +--eval XA COMMIT X'$gtrid_hex',X'$bqual_hex',0 +--disable_query_log +--echo XA COMMIT 'RANDOM XID' +--eval XA COMMIT X'$gtrid_rand',X'$bqual_rand',$formt_rand +--enable_query_log + +--source include/sync_slave_sql_with_master.inc + +# +# Testing ONE PHASE +# +--let $onephase_trx_num=10 +--let $i = $onephase_trx_num +while($i > 0) +{ + --connect (master_bulk_conn$i, 127.0.0.1,root,,test,$MASTER_MYPORT,) + + --connection master_bulk_conn$i + --eval XA START 'one_phase_$i' + --eval INSERT INTO d1.t VALUES ($i) + --eval INSERT INTO d2.t VALUES ($i) + --eval XA END 'one_phase_$i' + --eval XA COMMIT 'one_phase_$i' ONE PHASE + + --disconnect master_bulk_conn$i + --dec $i +} +--connection master +--source include/sync_slave_sql_with_master.inc + +# +# Overall consistency check +# +--let $diff_tables= master:d1.t, slave:d1.t +--source include/diff_tables.inc +--let $diff_tables= master:d2.t, slave:d2.t +--source include/diff_tables.inc +# +# cleanup +# +--connection master + +DELETE FROM d1.t; +DELETE FROM d2.t; +DROP TABLE d1.t, d2.t; +DROP DATABASE d1; +DROP DATABASE d2; +DROP VIEW v_processlist; + +--source include/sync_slave_sql_with_master.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt new file mode 100644 index 00000000..94c36500 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off-slave.opt @@ -0,0 +1,2 @@ +--log-slave-updates=off + diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test new file mode 100644 index 00000000..df3811df --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_lsu_off.test @@ -0,0 +1,8 @@ +# ==== Purpose ==== +# 'rpl_xa_survive_disconnect_lsu_off' verifies the same properties as the sourced file +# in conditions of the slave does not log own updates +# (lsu in the name stands for log_slave_updates). +# Specifically this mode aims at proving correct operations on the slave +# mysql.gtid_executed. + +--source ./rpl_xa_survive_disconnect.test diff --git a/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test new file mode 100644 index 00000000..f52a9630 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_xa_survive_disconnect_mixed_engines.test @@ -0,0 +1,68 @@ +# BUG#12161 Xa recovery and client disconnection +# +# The test verifies correct XA transaction two phase logging and its applying +# in a case the transaction updates transactional and non-transactional tables. +# Transactions are terminated according to specfied parameters to +# a sourced inc-file. + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection master +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + +--let $command=setup +--source include/rpl_xa_mixed_engines.inc + +--echo === COMMIT === +--let $command=run +--let $xa_terminate=XA COMMIT +--let $xa_prepare_opt=1 +--source include/rpl_xa_mixed_engines.inc + +--source include/sync_slave_sql_with_master.inc +--connection master + +--echo === COMMIT ONE PHASE === + +--let $command=run +--let $xa_terminate=XA COMMIT +--let $one_phase=ONE PHASE +--let $xa_prepare_opt= +--source include/rpl_xa_mixed_engines.inc +--let $one_phase= +--source include/sync_slave_sql_with_master.inc +--connection master + +--echo === ROLLBACK with PREPARE === + +--let $command=run +--let $xa_terminate=xa rollback +--let $xa_prepare_opt=1 +--source include/rpl_xa_mixed_engines.inc + +--source include/sync_slave_sql_with_master.inc +--connection master + +--echo === ROLLBACK with no PREPARE === + +--let $command=run +--let $xa_terminate=xa rollback +--let $xa_prepare_opt= +--source include/rpl_xa_mixed_engines.inc +--let $xa_rollback_only= + +--source include/sync_slave_sql_with_master.inc + +--let $diff_tables= master:tm, slave:tm +--source include/diff_tables.inc + +# Cleanup + +--connection master +--let $command=cleanup +--source include/rpl_xa_mixed_engines.inc + +--source include/sync_slave_sql_with_master.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/sec_behind_master-5114.test b/mysql-test/suite/rpl/t/sec_behind_master-5114.test new file mode 100644 index 00000000..d1d21bfa --- /dev/null +++ b/mysql-test/suite/rpl/t/sec_behind_master-5114.test @@ -0,0 +1,63 @@ +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +call mtr.add_suppression("Unsafe statement written to the binary log"); + + +# Make sure that the start time of the first event is certainly different +# from the next event +--let $timestamp= `SELECT @@timestamp` +--disable_query_log +eval SET TIMESTAMP= $timestamp-100; +--enable_query_log +CREATE TABLE t1 (a int); + +# Make sure that the slave is done with the first event, and all checks +# that we'll perform later will be really against the second event +sync_slave_with_master; + +connection master; + +# Restore the timestamp now. It doesn't matter that it's not precise, +# it just needs to be very different from the earlier event +--disable_query_log +eval SET TIMESTAMP= $timestamp; +--enable_query_log + +send INSERT INTO t1 VALUES(SLEEP(2)); + +connection slave; + +# When the slave starts executing the event, Seconds_Behind_Master +# should start growing steadilly. The bugfix ensures that they are +# calculated based on the start time of the current event, rather +# than the start time of the previous event. To check it, we only need +# the first non-zero value + +let $run = 20; +while ($run) +{ + dec $run; + let $sbm=query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1); + # for debugging uncomment echo and remove the if() +# echo Seconds_Behind_Master: $sbm; + if ($sbm) + { + let $run = 0; + } + sleep 0.5; +} + +# Normally the first non-zero value should be 1. However, due to race +# conditions on slow servers, sometimes the check might miss the value 1, +# and only catch a higher one. It does not matter, we just need to make +# sure it didn't start with 100+, as it would have with bug MDEV-5114 + +--disable_query_log +eval SELECT $sbm > 0 and $sbm < 99 AS Seconds_Behind_Master_is_less_than_100; +--enable_query_log + +connection master; +reap; +drop table t1; +source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test new file mode 100644 index 00000000..866041d2 --- /dev/null +++ b/mysql-test/suite/rpl/t/semisync_future-7591.test @@ -0,0 +1,32 @@ +--source include/master-slave.inc + +call mtr.add_suppression("Timeout waiting for reply of binlog*"); +create table t1 (i int); + +set global rpl_semi_sync_master_enabled = ON; + +--connection slave +--source include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = ON; +change master to master_log_file='master-bin.000002', master_log_pos = 320; + +start slave; +--let $slave_io_errno=1236 +--source include/wait_for_slave_io_error.inc + +--connection master +insert into t1 values (1); +reset master; + +--connection slave +--source include/stop_slave.inc +reset slave; +--source include/start_slave.inc + +set global rpl_semi_sync_slave_enabled = OFF; +--connection master +drop table t1; +--sync_slave_with_master +--connection master +set global rpl_semi_sync_master_enabled = OFF; +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/semisync_memleak_4066.test b/mysql-test/suite/rpl/t/semisync_memleak_4066.test new file mode 100644 index 00000000..e88e2335 --- /dev/null +++ b/mysql-test/suite/rpl/t/semisync_memleak_4066.test @@ -0,0 +1,14 @@ +# +# MDEV-4066 semisync_master + temporary tables causes memory leaks +# +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +connection master; + +--connect (con1,localhost,root,,) +CREATE TEMPORARY TABLE tmp (i INT); +--disconnect con1 + +source include/rpl_end.inc; + diff --git a/mysql-test/suite/rpl/t/sequence.cnf b/mysql-test/suite/rpl/t/sequence.cnf new file mode 100644 index 00000000..58b605ad --- /dev/null +++ b/mysql-test/suite/rpl/t/sequence.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.3] +log-slave-updates + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/sequence.test b/mysql-test/suite/rpl/t/sequence.test new file mode 100644 index 00000000..436a0b1c --- /dev/null +++ b/mysql-test/suite/rpl/t/sequence.test @@ -0,0 +1,52 @@ +# +# Testing sequences with replication +# + +--source include/have_binlog_format_row.inc +--source include/have_aria.inc +--source include/have_sequence.inc + +--let $rpl_topology= 1->2->3 +--source include/rpl_init.inc + +--let $rpl_connection_name= master +--let $rpl_server_number= 1 +--source include/rpl_connect.inc + +--let $rpl_connection_name= slave +--let $rpl_server_number= 2 +--source include/rpl_connect.inc + +--let $rpl_connection_name= slave2 +--let $rpl_server_number= 3 +--source include/rpl_connect.inc + +--connection master + +set @@default_storage_engine="aria"; + +CREATE SEQUENCE s1 cache=10; +create table t1 select * from s1; +select NEXT VALUE for s1,seq from seq_1_to_20; +insert into t1 select * from s1; +do setval(s1,5, 1, 0); +insert into t1 select * from s1; +do setval(s1, 5000, 1 ,0); +insert into t1 select * from s1; +alter sequence s1 minvalue=-1 start=-1 restart=-1; +insert into t1 select * from s1; +insert into s1 values(-100,-1000,9223372036854775806,1,1,1000,0,0); +insert into t1 select * from s1; +select * from t1; +--sync_slave_with_master +select * from t1; +--sync_slave_with_master slave2 +select * from t1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; + +connection master; +drop table s1,t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test new file mode 100644 index 00000000..12794dbd --- /dev/null +++ b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test @@ -0,0 +1,22 @@ +# +# MDEV-7126 replication slave - deadlock in terminate_slave_thread with stop slave and show variables of replication filters and show global status +# +--source include/master-slave.inc + +call mtr.add_suppression("Master is configured to log replication events"); + +--connection slave + + +# If everything is okay, the test will end in several seconds; maybe a minute. +# If the problem shows up, it will hang until testcase timeout is exceeded. +--exec $MYSQL_SLAP --silent --host=127.0.0.1 -P $SLAVE_MYPORT -q "START SLAVE; STOP SLAVE; SHOW GLOBAL STATUS" -c 2 --number-of-queries=100 --create-schema=test + +# All done. + +--connection slave +--source include/wait_for_slave_to_stop.inc +start slave; + +--connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/temporal_row-9560-master.opt b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt new file mode 100644 index 00000000..07c4494e --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt @@ -0,0 +1 @@ +--disable-mysql56-temporal-format diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.combinations b/mysql-test/suite/rpl/t/temporal_row-9560.combinations new file mode 100644 index 00000000..b1c360f8 --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560.combinations @@ -0,0 +1,6 @@ +[old2old] +--disable-mysql56-temporal-format + +[old2new] +--enable-mysql56-temporal-format + diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.test b/mysql-test/suite/rpl/t/temporal_row-9560.test new file mode 100644 index 00000000..00fb59bc --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560.test @@ -0,0 +1,20 @@ +# +# MDEV-9560 Mariadb 10.1 Crashes when replicating from 10.0 +# +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +select @@mysql56_temporal_format; +create table t1 (ts timestamp(3), t time(3), dt datetime(3)); +insert into t1 values ('2016-02-15 12:50:06.123', '12:50:06.123', '2016-02-15 12:50:06.123'); + +sync_slave_with_master; + +select @@mysql56_temporal_format; +select * from t1; + +connection master; +drop table t1; + +source include/rpl_end.inc; + |