summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/rpl/include/rpl_conflicts.test
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/rpl/include/rpl_conflicts.test')
-rw-r--r--mysql-test/suite/rpl/include/rpl_conflicts.test170
1 files changed, 170 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/include/rpl_conflicts.test b/mysql-test/suite/rpl/include/rpl_conflicts.test
new file mode 100644
index 00000000..a8c796af
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_conflicts.test
@@ -0,0 +1,170 @@
+# ==== Purpose ====
+#
+# Test that slave behaves well in some conflict situations. The
+# following are tested:
+#
+# - The slave SQL thread sees an 'INSERT' of a row with a key that
+# already exists in the table;
+#
+# - The slave SQL thread sees a 'DELETE' of a row that does not
+# exist in the table.
+#
+# In statement-logging mode, the first conflict type causes the slave
+# to stop with an error and the second conflict is ignored.
+#
+# In row-logging mode, the slave behavior depends the value of
+# @@slave_exec_mode on the slave: if @@slave_exec_mode is IDEMPOTENT,
+# the slave should ignore the conflicting statement and continue
+# normally. If @@slave_exec_mode is STRICT, the slave should stop
+# with an error.
+#
+# This test was previously named rpl_stm_mystery22/rpl_row_mystery22.
+#
+#
+# ==== Method ====
+#
+# Create a table on master and slave, insert a row on slave, and
+# insert the same row on master.
+#
+# Create a table on master and slave, insert a row on master with
+# binlogging turned off, and remove the row on master with binlogging
+# turned on.
+#
+#
+# ==== Related bugs ====
+#
+# BUG#31552: Replication breaks when deleting rows from out-of-sync table without PK
+# BUG#31609: Not all RBR slave errors reported as errors
+#
+# Bug in this test case:
+# BUG#37718: rpl.rpl_stm_mystery22 fails sporadically on pushbuild
+#
+#
+# ==== Usage ====
+#
+# This file assumes the following:
+#
+# - The test language variable $slave_is_idempotent is set to 1 if the
+# slave is expected to stop on duplicate key errors (i.e., if the
+# binlog is in statement mode or
+# @@global.slave_exec_mode=STRICT). It is set to 0 otherwise.
+#
+# - Replication has been initialized by include/master-slave.inc
+#
+# - The test adds a suppression for the following warning:
+# Slave: Can't find record in 't1' error.* 1032
+
+
+--echo ==== Initialize ====
+
+connection master;
+CREATE TABLE t1(a INT PRIMARY KEY);
+sync_slave_with_master;
+
+
+--echo ==== Test: SQL thread sees 'INSERT' of existing key ====
+
+--echo ---- Prepare slave so that it will get duplicate key error ----
+# This row will be in the way of the row inserted by master.
+INSERT INTO t1 VALUES (1);
+
+--echo ---- Insert rows on master ----
+connection master;
+# Insert the same row on master
+INSERT INTO t1 VALUES (1);
+save_master_pos;
+SELECT * FROM t1;
+
+connection slave;
+
+# If we are statement-logging or if slave_exec_mode=STRICT, we now
+# expect to see an error on the slave. Otherwise (i.e., we are
+# row-logging and slave_exec_mode=IDEMPOTENT), we expect that the
+# duplicate row is ignored by the slave and replication continues.
+if (`SELECT @@global.binlog_format != 'ROW' OR @@global.slave_exec_mode = 'STRICT'`) {
+ --echo ---- Wait until slave stops with an error ----
+ # Wait until the slave tries to run the query, fails with duplicate
+ # key error, and stops the SQL thread.
+ let $slave_sql_errno= 1062; # ER_DUP_ENTRY
+ source include/wait_for_slave_sql_error.inc;
+
+ --let $err= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1)
+ --replace_regex /end_log_pos [0-9]+/end_log_pos END_LOG_POS/
+ --disable_query_log
+ --eval SELECT "$err" as 'Last_SQL_Error (expected "duplicate key" error)'
+ --enable_query_log
+ call mtr.add_suppression("Slave SQL.*Duplicate entry .1. for key .PRIMARY.* error.* 1062");
+
+ SELECT * FROM t1;
+
+ --echo ---- Resolve the conflict on the slave and restart SQL thread ----
+ DELETE FROM t1 WHERE a = 1;
+ START SLAVE SQL_THREAD;
+ source include/wait_for_slave_sql_to_start.inc;
+}
+
+--echo ---- Sync slave and verify that there is no error ----
+sync_with_master;
+let $err= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+--echo Last_SQL_Error = '$err' (expected no error)
+SELECT * FROM t1;
+
+
+--echo ==== Test: SQL thread sees 'DELETE' of non-existing row ====
+
+--echo ---- On master, insert two rows, the second with binlogging off ----
+connection master;
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1);
+
+sync_slave_with_master;
+DELETE FROM t1 WHERE a = 1;
+
+--echo ---- On master, remove the row that does not exist on slave ----
+connection master;
+DELETE FROM t1 WHERE a = 1;
+SELECT * FROM t1;
+save_master_pos;
+
+connection slave;
+
+# If we are row-logging and slave_exec_mode is STRICT, we now expect
+# an error since the row to delete does not exist on slave. Otherwise
+# (i.e., either we are statement-logging or slave_exec_mode is
+# IDEMPOTENT), the absence of the row to delete is ignored and
+# replication continues.
+if (`SELECT @@global.binlog_format = 'ROW' AND @@global.slave_exec_mode = 'STRICT'`) {
+ --echo ---- Wait until slave stops with an error ----
+ call mtr.add_suppression("Slave SQL.*Can.t find record in .t1., error.* 1032");
+ let $slave_sql_errno= 1032; # ER_KEY_NOT_FOUND
+ source include/wait_for_slave_sql_error.inc;
+
+ --let $err= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1)
+ --replace_regex /end_log_pos [0-9]+/end_log_pos END_LOG_POS/
+ --disable_query_log
+ --eval SELECT "$err" as 'Last_SQL_Error (expected "duplicate key" error)'
+ --enable_query_log
+
+ SELECT * FROM t1;
+
+ --echo ---- Resolve the conflict on the slave and restart SQL thread ----
+ INSERT INTO t1 VALUES (1);
+ START SLAVE SQL_THREAD;
+ source include/wait_for_slave_sql_to_start.inc;
+}
+
+--echo ---- Sync slave and verify that there is no error ----
+# The slave should sync ok, and SHOW SLAVE STATUS should give no
+# error.
+sync_with_master;
+let $err= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+--echo Last_SQL_Error = $err (expected no error)
+SELECT * FROM t1;
+
+
+--echo ==== Clean up ====
+
+connection master;
+DROP TABLE t1;
+
+--sync_slave_with_master