MXS-1507: Replay read-only transaction

Read-only transactions are now replayed if the node in question fails.
This commit is contained in:
Markus Mäkelä
2018-04-23 11:29:15 +03:00
parent 2848f96945
commit 7de7e7b2fe
2 changed files with 45 additions and 44 deletions

View File

@ -525,8 +525,15 @@ void check_and_log_backend_state(const SRWBackend& backend, DCB* problem_dcb)
} }
} }
void RWSplitSession::start_trx_replay() bool RWSplitSession::start_trx_replay()
{ {
bool rval = false;
if (!m_is_replay_active && m_config.transaction_replay)
{
// Stash any interrupted queries while we replay the transaction
m_interrupted_query.reset(m_current_query.release());
MXS_INFO("Starting transaction replay"); MXS_INFO("Starting transaction replay");
m_is_replay_active = true; m_is_replay_active = true;
@ -541,6 +548,10 @@ void RWSplitSession::start_trx_replay()
// Pop the first statement and start replaying the transaction // Pop the first statement and start replaying the transaction
retry_query(m_replayed_trx.pop_stmt(), 0); retry_query(m_replayed_trx.pop_stmt(), 0);
rval = true;
}
return rval;
} }
/** /**
@ -573,11 +584,11 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
{ {
case ERRACT_NEW_CONNECTION: case ERRACT_NEW_CONNECTION:
{ {
bool can_continue = false;
if (m_current_master && m_current_master->in_use() && m_current_master == backend) if (m_current_master && m_current_master->in_use() && m_current_master == backend)
{ {
/** The connection to the master has failed */ /** The connection to the master has failed */
SERVER *srv = m_current_master->server();
bool can_continue = false;
if (!backend->is_waiting_result()) if (!backend->is_waiting_result())
{ {
@ -615,9 +626,9 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
send_readonly_error(m_client); send_readonly_error(m_client);
} }
if (!can_continue && !SERVER_IS_MASTER(srv) && !srv->master_err_is_logged) if (!can_continue && !backend->is_master() &&
!backend->server()->master_err_is_logged)
{ {
ss_dassert(backend);
MXS_ERROR("Server %s (%s) lost the master status while waiting" MXS_ERROR("Server %s (%s) lost the master status while waiting"
" for a result. Client sessions will be closed.", " for a result. Client sessions will be closed.",
backend->name(), backend->uri()); backend->name(), backend->uri());
@ -625,27 +636,11 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
} }
} }
if (m_is_replay_active) if (session_trx_is_active(session))
{ {
MXS_INFO("Failed to replay transaction. Closing connection."); can_continue = start_trx_replay();
can_continue = false;
}
else if (session_trx_is_active(session))
{
if (m_config.transaction_replay)
{
// Stash any interrupted queries while we replay the transaction
m_interrupted_query.reset(m_current_query.release());
can_continue = true;
start_trx_replay();
}
else
{
can_continue = false;
}
} }
*succp = can_continue;
backend->close(); backend->close();
} }
else else
@ -653,21 +648,21 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
if (m_target_node && m_target_node == backend && if (m_target_node && m_target_node == backend &&
session_trx_is_read_only(problem_dcb->session)) session_trx_is_read_only(problem_dcb->session))
{ {
/** // We're no longer locked to this server as it failed
* We were locked to a single node but the node died. Currently m_target_node.reset();
* this only happens with read-only transactions so the only
* thing we can do is to close the connection. // Try to replay the transaction on another node
*/ can_continue = start_trx_replay();
*succp = false; backend->close();
backend->close(mxs::Backend::CLOSE_FATAL);
} }
else else
{ {
/** Try to replace the failed connection with a new one */ /** Try to replace the failed connection with a new one */
*succp = handle_error_new_connection(problem_dcb, errmsgbuf); can_continue = handle_error_new_connection(problem_dcb, errmsgbuf);
} }
} }
*succp = can_continue;
check_and_log_backend_state(backend, problem_dcb); check_and_log_backend_state(backend, problem_dcb);
break; break;
} }

View File

@ -185,7 +185,13 @@ private:
bool handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg); bool handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg);
void handle_trx_replay(); void handle_trx_replay();
void start_trx_replay();
/**
* Start the replaying of the latest transaction
*
* @return True if the session can continue. False if the session must be closed.
*/
bool start_trx_replay();
private: private:
// QueryClassifier::Handler // QueryClassifier::Handler