MXS-2603: Treat WSREP errors as ignorable errors

When a query returns a WSREP error, most of the time it is not something
the client application is expecting. To prevent this from affecting the
client, it can be treated the same way a transaction rollback is treated:
ignore the error and try again.
This commit is contained in:
Markus Mäkelä 2019-07-28 08:55:48 +03:00
parent 45aa40c10a
commit 9d0c6b908a
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
3 changed files with 52 additions and 8 deletions

View File

@ -88,6 +88,13 @@ public:
return rv;
}
bool is_wsrep_error() const
{
return m_code == 1047
&& m_sql_state == "08S01"
&& m_message == "WSREP has not yet prepared node for application use";
}
bool is_unexpected_error() const
{
switch (m_code)

View File

@ -600,6 +600,48 @@ void RWSplitSession::close_stale_connections()
}
}
bool RWSplitSession::handle_ignorable_error(RWBackend* backend)
{
mxb_assert(session_trx_is_active(m_pSession) || can_retry_query());
mxb_assert(m_expected_responses > 0);
bool ok = false;
m_expected_responses--;
MXS_INFO("%s: %s", backend->error().is_rollback() ?
"Server triggered transaction rollback, replaying transaction" :
"WSREP not ready, retrying query", backend->error().message().c_str());
if (session_trx_is_active(m_pSession))
{
ok = start_trx_replay();
}
else
{
mxb_assert(backend->error().is_wsrep_error());
if (backend == m_current_master)
{
if (can_retry_query())
{
ok = retry_master_query(backend);
}
}
else if (m_config.retry_failed_reads)
{
ok = true;
retry_query(m_current_query.release());
}
}
if (ok)
{
session_reset_server_bookkeeping(m_pSession);
}
return ok;
}
void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
{
DCB* client_dcb = backend_dcb->session->client_dcb;
@ -638,16 +680,10 @@ void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
}
}
if (error && m_config.transaction_replay && error.is_rollback())
if ((error.is_rollback() || error.is_wsrep_error()) && handle_ignorable_error(backend))
{
MXS_INFO("A retryable error: %s", error.message().c_str());
// writebuf was an error that can be handled by replaying the transaction.
m_expected_responses--;
start_trx_replay();
// We can ignore this error and treat it as if the connection to the server was broken.
gwbuf_free(writebuf);
session_reset_server_bookkeeping(m_pSession);
return;
}

View File

@ -229,6 +229,7 @@ private:
bool lock_to_master();
bool is_locked_to_master() const;
bool supports_hint(HINT_TYPE hint_type) const;
bool handle_ignorable_error(mxs::RWBackend* backend);
inline bool can_retry_query() const
{