MXS-2144: Treat server shutdown as a network error

If the server where a query is being executed is shutting down,
readwritesplit should treat it as an error to make retrying of the query
possible.

By treating server shutdowns as network errors, the same code path that is
used for actual network errors can be taken. This removes the need for any
extra retrying logic for this particular case.
This commit is contained in:
Markus Mäkelä 2018-11-13 17:20:50 +02:00
parent 37d38593d5
commit cab8a4bde8
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
3 changed files with 38 additions and 0 deletions

View File

@ -526,6 +526,15 @@ bool mxs_mysql_is_ok_packet(GWBUF* buffer);
*/
bool mxs_mysql_is_err_packet(GWBUF* buffer);
/**
* Extract the error code from an ERR packet
*
* @param buffer Buffer containing the ERR packet
*
* @return The error code or 0 if the buffer is not an ERR packet
*/
uint16_t mxs_mysql_get_mysql_errno(GWBUF* buffer);
/**
* @brief Check if a buffer contains a result set
*

View File

@ -1171,6 +1171,21 @@ bool mxs_mysql_is_err_packet(GWBUF* buffer)
return cmd == MYSQL_REPLY_ERR;
}
uint16_t mxs_mysql_get_mysql_errno(GWBUF* buffer)
{
uint16_t rval = 0;
if (mxs_mysql_is_err_packet(buffer))
{
uint8_t buf[2];
// First two bytes after the 0xff byte are the error code
gwbuf_copy_data(buffer, MYSQL_HEADER_LEN + 1, 2, buf);
rval = gw_mysql_get_byte2(buf);
}
return rval;
}
bool mxs_mysql_is_result_set(GWBUF* buffer)
{
bool rval = false;

View File

@ -555,6 +555,12 @@ void RWSplitSession::manage_transactions(SRWBackend& backend, GWBUF* writebuf)
}
}
static bool server_is_shutting_down(GWBUF* writebuf)
{
uint64_t err = mxs_mysql_get_mysql_errno(writebuf);
return err == ER_SERVER_SHUTDOWN || err == ER_NORMAL_SHUTDOWN || err == ER_SHUTDOWN_COMPLETE;
}
void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
{
DCB* client_dcb = backend_dcb->session->client_dcb;
@ -578,6 +584,14 @@ void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
}
return;
}
else if (backend->get_reply_state() == REPLY_STATE_START && server_is_shutting_down(writebuf))
{
// The server is shutting down, act as if the network connection failed. This allows
// the query to be retried on another server without the client noticing it.
poll_fake_hangup_event(backend_dcb);
gwbuf_free(writebuf);
return;
}
if ((writebuf = handle_causal_read_reply(writebuf, backend)) == NULL)
{