MXS-1506: Retry interrupted writes
If a query is interrupted that was sent to the master, it is now retried. This allows all autocommit queries to be transparently retried if the server in question fails.
This commit is contained in:
@ -128,6 +128,14 @@ bool RWSplitSession::prepare_target(SRWBackend& target, route_target_t route_tar
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RWSplitSession::retry_query(GWBUF* querybuf)
|
||||||
|
{
|
||||||
|
// Try to route the query again later
|
||||||
|
MXS_SESSION* session = m_client->session;
|
||||||
|
session_delay_routing(session, router_as_downstream(session), querybuf, 1);
|
||||||
|
++m_retry_duration;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routing function. Find out query type, backend type, and target DCB(s).
|
* Routing function. Find out query type, backend type, and target DCB(s).
|
||||||
* Then route query to found target(s).
|
* Then route query to found target(s).
|
||||||
@ -241,10 +249,7 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf, const RouteInfo& info)
|
|||||||
}
|
}
|
||||||
else if (can_retry_query())
|
else if (can_retry_query())
|
||||||
{
|
{
|
||||||
// Try to route the query again later
|
retry_query(gwbuf_clone(querybuf));
|
||||||
MXS_SESSION* session = m_client->session;
|
|
||||||
session_delay_routing(session, router_as_downstream(session), gwbuf_clone(querybuf), 1);
|
|
||||||
++m_retry_duration;
|
|
||||||
succp = true;
|
succp = true;
|
||||||
|
|
||||||
MXS_INFO("Delaying routing: %s", extract_sql(querybuf).c_str());
|
MXS_INFO("Delaying routing: %s", extract_sql(querybuf).c_str());
|
||||||
|
@ -509,7 +509,12 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
|
|||||||
// We were expecting a response but we aren't going to get one
|
// We were expecting a response but we aren't going to get one
|
||||||
m_expected_responses--;
|
m_expected_responses--;
|
||||||
|
|
||||||
if (m_config.master_failure_mode == RW_ERROR_ON_WRITE)
|
if (can_retry_query())
|
||||||
|
{
|
||||||
|
can_continue = true;
|
||||||
|
retry_query(release_query());
|
||||||
|
}
|
||||||
|
else if (m_config.master_failure_mode == RW_ERROR_ON_WRITE)
|
||||||
{
|
{
|
||||||
/** In error_on_write mode, the session can continue even
|
/** In error_on_write mode, the session can continue even
|
||||||
* if the master is lost. Send a read-only error to
|
* if the master is lost. Send a read-only error to
|
||||||
@ -518,7 +523,7 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
|
|||||||
send_readonly_error(m_client);
|
send_readonly_error(m_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SERVER_IS_MASTER(srv) && !srv->master_err_is_logged)
|
if (!can_continue && !SERVER_IS_MASTER(srv) && !srv->master_err_is_logged)
|
||||||
{
|
{
|
||||||
ss_dassert(backend);
|
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"
|
||||||
|
@ -153,6 +153,7 @@ private:
|
|||||||
bool handle_got_target(GWBUF* querybuf, mxs::SRWBackend& target, bool store);
|
bool handle_got_target(GWBUF* querybuf, mxs::SRWBackend& target, bool store);
|
||||||
void handle_connection_keepalive(mxs::SRWBackend& target);
|
void handle_connection_keepalive(mxs::SRWBackend& target);
|
||||||
bool prepare_target(mxs::SRWBackend& target, route_target_t route_target);
|
bool prepare_target(mxs::SRWBackend& target, route_target_t route_target);
|
||||||
|
void retry_query(GWBUF* querybuf);
|
||||||
|
|
||||||
bool should_replace_master(mxs::SRWBackend& target);
|
bool should_replace_master(mxs::SRWBackend& target);
|
||||||
void replace_master(mxs::SRWBackend& target);
|
void replace_master(mxs::SRWBackend& target);
|
||||||
|
Reference in New Issue
Block a user