MXS-2141: Retry query on master if it times out on slave

With causal_reads enabled, the query would return with an error if the
slave was not able to catch up to the master fast enough. By automatically
retrying the query on the master, we're guaranteed that a valid result is
always returned to the client.
This commit is contained in:
Markus Mäkelä
2018-11-06 12:25:57 +02:00
parent c661f5e838
commit e56372b153
4 changed files with 34 additions and 6 deletions

View File

@ -275,7 +275,7 @@ GWBUF* RWSplitSession::discard_master_wait_gtid_result(GWBUF* buffer)
else if (MYSQL_GET_COMMAND(header_and_command) == MYSQL_REPLY_ERR)
{
// The MASTER_WAIT_GTID command failed and no further packets will come
m_wait_gtid = NONE;
m_wait_gtid = RETRYING_ON_MASTER;
}
return buffer;
@ -524,6 +524,10 @@ void RWSplitSession::manage_transactions(SRWBackend& backend, GWBUF* writebuf)
}
}
}
else if (m_wait_gtid == RETRYING_ON_MASTER)
{
// We're retrying the query on the master and we need to keep the current query
}
else
{
/** Normal response, reset the currently active query. This is done before
@ -575,6 +579,23 @@ void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
mxb_assert(backend->get_reply_state() == REPLY_STATE_DONE);
MXS_INFO("Reply complete, last reply from %s", backend->name());
if (m_wait_gtid == RETRYING_ON_MASTER)
{
m_wait_gtid = NONE;
// Discard the error
gwbuf_free(writebuf);
writebuf = NULL;
// Retry the query on the master
GWBUF* buf = m_current_query.release();
buf->hint = hint_create_route(buf->hint, HINT_ROUTE_TO_MASTER, NULL);
retry_query(buf, 0);
// Stop the response processing early
return;
}
ResponseStat& stat = backend->response_stat();
stat.query_ended();
if (stat.is_valid() && (stat.sync_time_reached()