summaryrefslogtreecommitdiffstats
path: root/mysql-test/suite/rpl/include/rpl_deadlock.test
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/rpl/include/rpl_deadlock.test')
-rw-r--r--mysql-test/suite/rpl/include/rpl_deadlock.test153
1 files changed, 153 insertions, 0 deletions
diff --git a/mysql-test/suite/rpl/include/rpl_deadlock.test b/mysql-test/suite/rpl/include/rpl_deadlock.test
new file mode 100644
index 00000000..7fcf5cbd
--- /dev/null
+++ b/mysql-test/suite/rpl/include/rpl_deadlock.test
@@ -0,0 +1,153 @@
+# See if slave restarts the transaction after failing on an InnoDB deadlock error.
+
+# Note: testing what happens when too many retries is possible, but
+# needs large waits when running with --debug, so we don't do it.
+# The same way, this test may not test what is expected when run
+# under Valgrind, timings are too short then (with --valgrind I
+# (Guilhem) have seen the test manage to provoke lock wait timeout
+# error but not deadlock error; that is ok as code deals with the two
+# errors in exactly the same way.
+
+--source include/have_perfschema.inc
+--source include/master-slave.inc
+
+# 0) Prepare tables and data
+--echo *** Prepare tables and data ***
+
+connection master;
+eval CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type;
+eval CREATE TABLE t2 (a INT) ENGINE=$engine_type;
+eval CREATE TABLE t3 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type;
+sync_slave_with_master;
+
+SHOW CREATE TABLE t1;
+SHOW CREATE TABLE t2;
+SHOW CREATE TABLE t3;
+SHOW VARIABLES LIKE 'slave_transaction_retries';
+--source include/stop_slave.inc
+
+connection master;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+# We make a long transaction here
+INSERT INTO t2 VALUES (2), (2), (2), (2), (2), (2), (2), (2), (2), (2);
+INSERT INTO t3 VALUES (3);
+COMMIT;
+save_master_pos;
+# Save BEGIN event into variable
+let $master_pos_begin= query_get_value(SHOW BINLOG EVENTS, Pos, 10);
+--echo
+
+# 1) Test deadlock
+# Block slave SQL thread, wait retries of transaction, unlock slave before lock timeout
+--echo *** Test deadlock ***
+
+connection slave;
+BEGIN;
+SELECT * FROM t1 FOR UPDATE;
+# Save variable 'Slave_retried_transactions' before deadlock
+let $slave_retried_transactions= query_get_value(SHOW GLOBAL STATUS LIKE 'Slave_retried_transactions', Value, 1);
+# Run the START SLAVE in a separate connection. Otherwise it terminates
+# the SELECT FOR UPDATE transaction (START SLAVE does implicit COMMIT!).
+connection slave1;
+START SLAVE;
+# Wait until SQL thread blocked: variable 'Slave_retried_transactions' will incremented
+let $status_var= Slave_retried_transactions;
+let $status_var_value= $slave_retried_transactions;
+let $status_type= GLOBAL;
+let $status_var_comparsion= >;
+--source include/wait_for_status_var.inc
+connection slave;
+SELECT COUNT(*) FROM t2;
+COMMIT;
+
+--echo
+--echo # Test that the performance schema coulumn shows > 0 values.
+--echo
+
+--let $assert_text= current number of retries should be more than the value saved before deadlock.
+--let $assert_cond= [SELECT COUNT_TRANSACTIONS_RETRIES FROM performance_schema.replication_applier_status, COUNT_TRANSACTIONS_RETRIES, 1] > "$slave_retried_transactions"
+--source include/assert.inc
+
+source include/check_slave_is_running.inc;
+sync_with_master;
+
+# Check the data
+SELECT * FROM t1;
+SELECT * FROM t3;
+# Check that no error is reported
+source include/check_slave_is_running.inc;
+--echo
+
+# 2) Test lock wait timeout
+# Block slave and wait lock timeout error
+--echo *** Test lock wait timeout ***
+
+connection slave;
+--source include/stop_slave.inc
+DELETE FROM t2;
+# Set slave position to the BEGIN log event
+--replace_result $master_pos_begin <master_pos_begin>
+eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin, MASTER_USE_GTID=NO;
+BEGIN;
+# Hold lock
+SELECT * FROM t1 FOR UPDATE;
+# Wait until slave stopped with error 'Lock wait timeout exceeded'
+connection slave1;
+START SLAVE;
+let $slave_sql_errno= 1205;
+--source include/wait_for_slave_sql_error.inc
+connection slave;
+SELECT COUNT(*) FROM t2;
+COMMIT;
+--source include/start_slave.inc
+sync_with_master;
+# Check data from tables
+SELECT * FROM t1;
+SELECT * FROM t3;
+# Check that no error is reported
+source include/check_slave_is_running.inc;
+--echo
+
+# 3) Test lock wait timeout and purged relay log
+# Set max_relay_log_size=0, block slave and wait lock timeout error.
+# Restart slave and check that no erros appear
+--echo *** Test lock wait timeout and purged relay logs ***
+
+connection slave;
+SET @my_max_relay_log_size= @@global.max_relay_log_size;
+SET global max_relay_log_size=0;
+--source include/stop_slave.inc
+DELETE FROM t2;
+# Set slave position to the BEGIN log event
+--replace_result $master_pos_begin <master_pos_begin>
+eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin, MASTER_USE_GTID=NO;
+BEGIN;
+# Hold lock
+SELECT * FROM t1 FOR UPDATE;
+# Wait until slave stopped with error 'Lock wait timeout exceeded'
+connection slave1;
+START SLAVE;
+let $slave_sql_errno= 1205;
+--source include/wait_for_slave_sql_error.inc
+connection slave;
+SELECT COUNT(*) FROM t2;
+COMMIT;
+--source include/start_slave.inc
+sync_with_master;
+# Check data from tables
+SELECT * FROM t1;
+SELECT * FROM t3;
+# Check that no error is reported
+source include/check_slave_is_running.inc;
+--echo
+
+# Clean up
+--echo *** Clean up ***
+connection master;
+DROP TABLE t1,t2,t3;
+sync_slave_with_master;
+SET global max_relay_log_size= @my_max_relay_log_size;
+
+--echo End of 5.1 tests
+--source include/rpl_end.inc