diff --git a/include/maxscale/session.h b/include/maxscale/session.h index a85b9292a..f55639772 100644 --- a/include/maxscale/session.h +++ b/include/maxscale/session.h @@ -145,6 +145,7 @@ typedef struct session GWBUF *buffer; /**< Buffer containing the statement */ const struct server *target; /**< Where the statement was sent */ } stmt; /**< Current statement being executed */ + bool qualifies_for_pooling; /**< Whether this session qualifies for the connection pool */ skygw_chk_t ses_chk_tail; } MXS_SESSION; @@ -365,4 +366,18 @@ bool session_take_stmt(MXS_SESSION *session, GWBUF **buffer, const struct server */ void session_clear_stmt(MXS_SESSION *session); +/** + * Qualify the session for connection pooling + * + * @param session Session to qualify + */ +void session_qualify_for_pool(MXS_SESSION* session); + +/** + * Check if the session qualifies for connection pooling + * + * @param session + */ +bool session_valid_for_pool(const MXS_SESSION* session); + MXS_END_DECLS diff --git a/server/core/dcb.c b/server/core/dcb.c index adc16afaa..81182ab3b 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -1662,6 +1662,8 @@ dcb_maybe_add_persistent(DCB *dcb) && (dcb->func.established == NULL || dcb->func.established(dcb)) && strlen(dcb->user) && dcb->server + && dcb->session + && session_valid_for_pool(dcb->session) && dcb->server->persistpoolmax && (dcb->server->status & SERVER_RUNNING) && !dcb->dcb_errhandle_called diff --git a/server/core/session.c b/server/core/session.c index fff7f9832..e7da16789 100644 --- a/server/core/session.c +++ b/server/core/session.c @@ -112,6 +112,7 @@ session_alloc(SERVICE *service, DCB *client_dcb) session->stats.connect = time(0); session->stmt.buffer = NULL; session->stmt.target = NULL; + session->qualifies_for_pooling = false; /*< * Associate the session to the client DCB and set the reference count on * the session to indicate that there is a single reference to the @@ -947,3 +948,14 @@ void session_clear_stmt(MXS_SESSION *session) session->stmt.buffer = NULL; session->stmt.target = NULL; } + +void session_qualify_for_pool(MXS_SESSION* session) +{ + session->qualifies_for_pooling = true; +} + +bool session_valid_for_pool(const MXS_SESSION* session) +{ + ss_dassert(session->state != SESSION_STATE_DUMMY); + return session->qualifies_for_pooling; +} diff --git a/server/modules/protocol/MySQL/MySQLClient/mysql_client.c b/server/modules/protocol/MySQL/MySQLClient/mysql_client.c index e19fcc2d6..a25b329d0 100644 --- a/server/modules/protocol/MySQL/MySQLClient/mysql_client.c +++ b/server/modules/protocol/MySQL/MySQLClient/mysql_client.c @@ -991,6 +991,19 @@ gw_read_finish_processing(DCB *dcb, GWBUF *read_buffer, uint64_t capabilities) /** Reset error handler when routing of the new query begins */ dcb->dcb_errhandle_called = false; + if (proto->current_command == MYSQL_COM_QUIT) + { + /** The client is closing the connection. We know that this will be the + * last command the client sends so the backend connections are very likely + * to be in an idle state. + * + * If the client is pipelining the queries (i.e. sending N request as + * a batch and then expecting N responses) then it is possible that + * the backend connections are not idle when the COM_QUIT is received. + * In most cases we can assume that the connections are idle. */ + session_qualify_for_pool(session); + } + if (rcap_type_required(capabilities, RCAP_TYPE_STMT_INPUT)) { /**