MXS-2939: Fix reconnection with session commands
Session commands did not trigger a reconnection process which caused sessions to be closed in cases where recovery was possible. Added a test case that verifies the patch fixes the problem.
This commit is contained in:
@ -1015,6 +1015,9 @@ add_test_executable(mxs2631_ignore_system_tables.cpp mxs2631_ignore_system_table
|
|||||||
# MXS-2878: Verify that TLS is required
|
# MXS-2878: Verify that TLS is required
|
||||||
add_test_executable(mxs2878_monitor_ssl.cpp mxs2878_monitor_ssl mxs2878_monitor_ssl LABELS REPL_BACKEND)
|
add_test_executable(mxs2878_monitor_ssl.cpp mxs2878_monitor_ssl mxs2878_monitor_ssl LABELS REPL_BACKEND)
|
||||||
|
|
||||||
|
# MXS-2939: Test that session commands trigger a reconnection
|
||||||
|
add_test_executable(mxs2939_sescmd_reconnect.cpp mxs2939_sescmd_reconnect mxs2939_sescmd_reconnect LABELS REPL_BACKEND readwritesplit)
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# END: Normal tests #
|
# END: Normal tests #
|
||||||
############################################
|
############################################
|
||||||
|
26
maxscale-system-test/cnf/maxscale.cnf.template.mxs2939_sescmd_reconnect
Executable file
26
maxscale-system-test/cnf/maxscale.cnf.template.mxs2939_sescmd_reconnect
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
[maxscale]
|
||||||
|
threads=###threads###
|
||||||
|
|
||||||
|
###server###
|
||||||
|
|
||||||
|
[MySQL-Monitor]
|
||||||
|
type=monitor
|
||||||
|
module=mysqlmon
|
||||||
|
servers=###server_line###
|
||||||
|
user=maxskysql
|
||||||
|
password=skysql
|
||||||
|
monitor_interval=1000
|
||||||
|
|
||||||
|
[RW-Split-Router]
|
||||||
|
type=service
|
||||||
|
router=readwritesplit
|
||||||
|
servers=###server_line###
|
||||||
|
user=maxskysql
|
||||||
|
password=skysql
|
||||||
|
transaction_replay=true
|
||||||
|
|
||||||
|
[RW-Split-Listener]
|
||||||
|
type=listener
|
||||||
|
service=RW-Split-Router
|
||||||
|
protocol=MySQLClient
|
||||||
|
port=4006
|
33
maxscale-system-test/mxs2939_sescmd_reconnect.cpp
Normal file
33
maxscale-system-test/mxs2939_sescmd_reconnect.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* MXS-2939: Test that session commands trigger a reconnection
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "testconnections.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
TestConnections test(argc, argv);
|
||||||
|
|
||||||
|
test.maxscales->connect_rwsplit();
|
||||||
|
|
||||||
|
// Make sure we have at least one fully opened connection
|
||||||
|
test.try_query(test.maxscales->conn_rwsplit[0], "select 1");
|
||||||
|
|
||||||
|
// Block and unblock all nodes to sever all connections
|
||||||
|
for (int i = 0; i < test.repl->N; i++)
|
||||||
|
{
|
||||||
|
test.repl->block_node(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.maxscales->wait_for_monitor();
|
||||||
|
|
||||||
|
test.repl->unblock_all_nodes();
|
||||||
|
test.maxscales->wait_for_monitor();
|
||||||
|
|
||||||
|
// Make sure that session commands trigger a reconnection if there are no open connections
|
||||||
|
test.set_timeout(20);
|
||||||
|
test.try_query(test.maxscales->conn_rwsplit[0], "set @a = 1");
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
|
||||||
|
return test.global_result;
|
||||||
|
}
|
@ -105,22 +105,25 @@ bool RWSplitSession::prepare_target(RWBackend* target, route_target_t route_targ
|
|||||||
|
|
||||||
bool RWSplitSession::create_one_connection()
|
bool RWSplitSession::create_one_connection()
|
||||||
{
|
{
|
||||||
mxb_assert(m_config.lazy_connect);
|
mxb_assert(can_recover_servers());
|
||||||
|
|
||||||
// Try to first find a master
|
// Try to first find a master if we are allowed to connect to one
|
||||||
for (auto backend : m_raw_backends)
|
if (m_config.lazy_connect || m_config.master_reconnection)
|
||||||
{
|
{
|
||||||
if (backend->can_connect() && backend->is_master())
|
for (auto backend : m_raw_backends)
|
||||||
{
|
{
|
||||||
if (prepare_target(backend, TARGET_MASTER))
|
if (backend->can_connect() && backend->is_master())
|
||||||
{
|
{
|
||||||
if (!m_current_master)
|
if (prepare_target(backend, TARGET_MASTER))
|
||||||
{
|
{
|
||||||
MXS_INFO("Chose '%s' as master due to session write", backend->name());
|
if (!m_current_master)
|
||||||
m_current_master = backend;
|
{
|
||||||
}
|
MXS_INFO("Chose '%s' as master due to session write", backend->name());
|
||||||
|
m_current_master = backend;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -598,8 +601,10 @@ bool RWSplitSession::route_session_write(GWBUF* querybuf, uint8_t command, uint3
|
|||||||
m_sescmd_list.push_back(sescmd);
|
m_sescmd_list.push_back(sescmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_config.lazy_connect && !attempted_write && nsucc == 0)
|
if (!attempted_write && can_recover_servers())
|
||||||
{
|
{
|
||||||
|
mxb_assert(nsucc == 0);
|
||||||
|
|
||||||
// If no connections are open, create one and execute the session command on it
|
// If no connections are open, create one and execute the session command on it
|
||||||
if (create_one_connection())
|
if (create_one_connection())
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user