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:
parent
845b59ad48
commit
fbc1a7d44b
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user