MXS-359: Close failed backend if in read-only transaction

If the connection to the backend where a read-only transaction is being
performed fails, the Backend object should be closed for it. This fixes a
debug assertion in readwritesplit.cc:check_and_log_backend_state which
asserts that the failed connection must not be in use after the error
handling is done.

Also reordered the failing assertion and the accompanying error message so
that the error is logged first.
This commit is contained in:
Markus Mäkelä
2018-03-08 13:29:33 +02:00
parent 35b7ef35b7
commit 16f201beed

View File

@ -617,9 +617,9 @@ void check_and_log_backend_state(const SRWBackend& backend, DCB* problem_dcb)
/** This is a valid DCB for a backend ref */ /** This is a valid DCB for a backend ref */
if (backend->in_use() && backend->dcb() == problem_dcb) if (backend->in_use() && backend->dcb() == problem_dcb)
{ {
ss_dassert(false);
MXS_ERROR("Backend '%s' is still in use and points to the problem DCB.", MXS_ERROR("Backend '%s' is still in use and points to the problem DCB.",
backend->name()); backend->name());
ss_dassert(false);
} }
} }
else else
@ -1370,17 +1370,17 @@ static void handleError(MXS_ROUTER *instance,
case ERRACT_NEW_CONNECTION: case ERRACT_NEW_CONNECTION:
{ {
if (rses->current_master && rses->current_master->in_use() && if (rses->current_master && rses->current_master->in_use() &&
rses->current_master->dcb() == problem_dcb) rses->current_master == backend)
{ {
/** The connection to the master has failed */ /** The connection to the master has failed */
SERVER *srv = rses->current_master->server(); SERVER *srv = rses->current_master->server();
bool can_continue = false; bool can_continue = false;
if (rses->rses_config.master_failure_mode != RW_FAIL_INSTANTLY && if (!backend->is_waiting_result())
(!backend || !backend->is_waiting_result()))
{ {
/** The failure of a master is not considered a critical /** The failure of a master is not considered a critical
* failure as partial functionality still remains. Reads * failure as partial functionality still remains. If
* master_failure_mode is not set to fail_instantly, reads
* are allowed as long as slave servers are available * are allowed as long as slave servers are available
* and writes will cause an error to be returned. * and writes will cause an error to be returned.
* *
@ -1392,34 +1392,28 @@ static void handleError(MXS_ROUTER *instance,
} }
else if (!SERVER_IS_MASTER(srv) && !srv->master_err_is_logged) else if (!SERVER_IS_MASTER(srv) && !srv->master_err_is_logged)
{ {
MXS_ERROR("Server %s:%d lost the master status. Readwritesplit " ss_dassert(backend);
"service can't locate the master. Client sessions " MXS_ERROR("Server %s (%s) lost the master status while waiting"
"will be closed.", srv->name, srv->port); " for a result. Client sessions will be closed.",
srv->master_err_is_logged = true; backend->name(), backend->uri());
backend->server()->master_err_is_logged = true;
} }
*succp = can_continue; *succp = can_continue;
if (backend)
{
backend->close(mxs::Backend::CLOSE_FATAL); backend->close(mxs::Backend::CLOSE_FATAL);
} }
else else
{ {
MXS_ERROR("Server %s:%d lost the master status but could not locate the " if (rses->target_node && rses->target_node == backend &&
"corresponding backend ref.", srv->name, srv->port); session_trx_is_read_only(problem_dcb->session))
}
}
else if (backend)
{ {
if (rses->target_node && /**
(rses->target_node->dcb() == problem_dcb && * We were locked to a single node but the node died. Currently
session_trx_is_read_only(problem_dcb->session))) * this only happens with read-only transactions so the only
{ * thing we can do is to close the connection.
/** The problem DCB is the current target of a READ ONLY transaction. */
* Reset the target and close the session. */
rses->target_node.reset();
*succp = false; *succp = false;
backend->close(mxs::Backend::CLOSE_FATAL);
} }
else else
{ {