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:
parent
37d38593d5
commit
cab8a4bde8
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user