diff --git a/system-test/CMakeLists.txt b/system-test/CMakeLists.txt index a8f622955..131584b85 100644 --- a/system-test/CMakeLists.txt +++ b/system-test/CMakeLists.txt @@ -938,6 +938,9 @@ add_test_executable(mxs2919_broken_slaves.cpp mxs2919_broken_slaves mxs2919_brok # MXS-2972: Caching of shards must take servers into notice add_test_executable(mxs2972_shard_caching.cc mxs2972_shard_caching mxs2972_shard_caching LABELS REPL_BACKEND schemarouter) +# MXS-3220: Crash on master reconnection with session command +add_test_executable(mxs3220_reconnect_crash.cc mxs3220_reconnect_crash mxs3220_reconnect_crash LABELS REPL_BACKEND readwritesplit) + ############################################ # END: Normal tests # ############################################ diff --git a/system-test/cnf/maxscale.cnf.template.mxs3220_reconnect_crash b/system-test/cnf/maxscale.cnf.template.mxs3220_reconnect_crash new file mode 100644 index 000000000..837908b43 --- /dev/null +++ b/system-test/cnf/maxscale.cnf.template.mxs3220_reconnect_crash @@ -0,0 +1,31 @@ +[maxscale] +threads=###threads### + +[MySQL-Monitor] +type=monitor +module=mysqlmon +servers=###server_line### +user=maxskysql +password=skysql +monitor_interval=1000 + +[RW-Split-Router] +type=service +router=readwritesplit +servers=server1 +user=maxskysql +password=skysql +master_reconnection=true +master_failure_mode=fail_on_write +delayed_retry=true +transaction_replay=true +prune_sescmd_history=true +use_sql_variables_in=master + +[RW-Split-Listener] +type=listener +service=RW-Split-Router +protocol=MySQLClient +port=4006 + +###server### diff --git a/system-test/mxs3220_reconnect_crash.cc b/system-test/mxs3220_reconnect_crash.cc new file mode 100644 index 000000000..350148b40 --- /dev/null +++ b/system-test/mxs3220_reconnect_crash.cc @@ -0,0 +1,50 @@ +/** + * MXS-3220: Crash when session command history execution fails + */ + +#include + +int main(int argc, char** argv) +{ + TestConnections test(argc, argv); + + auto conn = test.maxscales->rwsplit(); + conn.connect(); + conn.query("CREATE USER 'bob' IDENTIFIED BY 'bob'"); + conn.query("GRANT ALL ON *.* TO 'bob'"); + conn.disconnect(); + + conn.set_credentials("bob", "bob"); + conn.connect(); + conn.query("SET @a = (SELECT SLEEP(10))"); + + auto master = test.repl->get_connection(0); + master.connect(); + + // Kill the current master connection. With master_failure_mode=fail_on_write this will not + // close the connection. + master.query("SET @id = (SELECT id FROM information_schema.processlist WHERE user = 'bob')"); + master.query("KILL @id"); + + + // Start a thread that kills the master connection again in five seconds. This should give enough time for + // the reconnection and history replay to start. + std::thread thr([&]() { + sleep(5); + master.query( + "SET @id = (SELECT id FROM information_schema.processlist WHERE user = 'bob')"); + master.query("KILL @id"); + }); + + // This triggers a reconnection and the execution of the session command history + test.expect(conn.query("SET @b = 1"), "Interrupted query should work: %s", conn.error()); + auto res = conn.field("SELECT @b"); + test.expect(!res.empty(), "User variable @b should not be empty"); + + thr.join(); + + conn.connect(); + conn.query("DROP USER 'bob'"); + + return test.global_result; +}