Fix handling of multi-packet queries in readwritesplit

If a prepared statement sends large amounts of data, the target server
where the data is sent will be tracked. The tracked target was not reset
after a multi-packet query was completed and the target itself was used to
check whether the session was processing a multi-packet query.

Changed the check to use the boolean variable instead of the target and
added a reset of the tracked target after a multi-packet query was
completed.
This commit is contained in:
Markus Mäkelä 2017-09-21 20:40:51 +03:00
parent 845b59ad48
commit fbc1a7d44b
4 changed files with 23 additions and 3 deletions

View File

@ -150,7 +150,11 @@ is_packet_a_query(int packet_type)
void
log_transaction_status(RWSplitSession *rses, GWBUF *querybuf, uint32_t qtype)
{
if (rses->load_data_state == LOAD_DATA_INACTIVE)
if (rses->large_query)
{
MXS_INFO("> Processing large request with more than 2^24 bytes of data");
}
else if (rses->load_data_state == LOAD_DATA_INACTIVE)
{
uint8_t *packet = GWBUF_DATA(querybuf);
unsigned char command = packet[4];

View File

@ -182,7 +182,7 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con
uint8_t command = info.command;
uint32_t qtype = info.type;
route_target_t route_target = info.target;
bool not_locked_to_master = !rses->prev_target &&
bool not_locked_to_master = !rses->large_query &&
(!rses->target_node || rses->target_node != rses->current_master);
if (not_locked_to_master && is_ps_command(command))
@ -1091,7 +1091,12 @@ static inline bool query_creates_reply(uint8_t cmd)
static inline bool is_large_query(GWBUF* buf)
{
uint32_t buflen = gwbuf_length(buf);
// The buffer should contain at most (2^24 - 1) + 4 bytes ...
ss_dassert(buflen <= MYSQL_HEADER_LEN + GW_MYSQL_MAX_PACKET_LEN);
// ... and the payload should be buflen - 4 bytes
ss_dassert(MYSQL_GET_PAYLOAD_LEN(GWBUF_DATA(buf)) == buflen - MYSQL_HEADER_LEN);
return buflen == MYSQL_HEADER_LEN + GW_MYSQL_MAX_PACKET_LEN;
}
@ -1165,11 +1170,16 @@ bool handle_got_target(RWSplit *inst, RWSplitSession *rses,
}
}
/** Store the previous target if we're processing a multi-packet query */
if ((rses->large_query = large_query))
{
/** Store the previous target as we're processing a multi-packet query */
rses->prev_target = target;
}
else
{
/** Otherwise reset it so we know the query is complete */
rses->prev_target.reset();
}
/**
* If a READ ONLY transaction is ending set forced_node to NULL

View File

@ -63,6 +63,7 @@ void process_sescmd_response(RWSplitSession* rses, SRWBackend& backend,
if (command == MXS_COM_STMT_PREPARE)
{
/** Map the returned response to the internal ID */
MXS_INFO("PS ID %u maps to internal ID %lu", resp.id, id);
rses->ps_handles[resp.id] = id;
}
}

View File

@ -108,6 +108,11 @@ uint32_t get_internal_ps_id(RWSplitSession* rses, GWBUF* buffer)
{
rval = it->second;
}
else
{
MXS_WARNING("Client requests unknown prepared statement ID '%u' that "
"does not map to an internal ID", id);
}
return rval;
}