From e949e7a569ac72653a588cf5c354300348666500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 7 Mar 2018 12:26:49 +0100 Subject: [PATCH] Try to get from connection pool and connections cache, a connection with the same schemaname This is ported from 1.4.7 , and modified to work with GTID support in 2.0 --- include/MySQL_HostGroups_Manager.h | 4 +- include/MySQL_Thread.h | 2 +- lib/MySQL_HostGroups_Manager.cpp | 46 ++++++++++++++++++++-- lib/MySQL_Session.cpp | 25 ++---------- lib/MySQL_Thread.cpp | 61 +++++++++++++++++++++++++++--- 5 files changed, 105 insertions(+), 33 deletions(-) diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index db2f8cdb9c..85ca5430c6 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -300,7 +300,7 @@ class MySrvConnList { conns->remove_index_fast((unsigned int)i); } MySQL_Connection *remove(int); - MySQL_Connection * get_random_MyConn(bool ff); + MySQL_Connection * get_random_MyConn(MySQL_Session *sess, bool ff); unsigned int conns_length(); void drop_all_connections(); MySQL_Connection *index(unsigned int); @@ -491,7 +491,7 @@ class MySQL_HostGroups_Manager { void MyConn_add_to_pool(MySQL_Connection *); - MySQL_Connection * get_MyConn_from_pool(unsigned int, bool ff, char * gtid_uuid, uint64_t gtid_trxid); + MySQL_Connection * get_MyConn_from_pool(unsigned int hid, MySQL_Session *sess, bool ff, char * gtid_uuid, uint64_t gtid_trxid); void drop_all_idle_connections(); int get_multiple_idle_connections(int, unsigned long long, MySQL_Connection **, int); diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index 18844f743e..0b3f068bcd 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -261,7 +261,7 @@ class MySQL_Thread void unregister_session_connection_handler(int idx, bool _new=false); void listener_handle_new_connection(MySQL_Data_Stream *myds, unsigned int n); void Get_Memory_Stats(); - MySQL_Connection * get_MyConn_local(unsigned int, MySQL_Data_Stream *client_myds, char *gtid_uuid, uint64_t gtid_trxid); + MySQL_Connection * get_MyConn_local(unsigned int, MySQL_Session *sess, char *gtid_uuid, uint64_t gtid_trxid); void push_MyConn_local(MySQL_Connection *); void return_local_connections(); }; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 13e57f26cb..66f79cd87d 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -2044,7 +2044,7 @@ unsigned int MySrvList::cnt() { MySrvC * MySrvList::idx(unsigned int i) { return (MySrvC *)servers->index(i); } -MySQL_Connection * MySrvConnList::get_random_MyConn(bool ff) { +MySQL_Connection * MySrvConnList::get_random_MyConn(MySQL_Session *sess, bool ff) { MySQL_Connection * conn=NULL; unsigned int i; unsigned int l=conns_length(); @@ -2054,7 +2054,45 @@ MySQL_Connection * MySrvConnList::get_random_MyConn(bool ff) { } else { i=fastrand()%l; } - conn=(MySQL_Connection *)conns->remove_index_fast(i); + if (sess && sess->client_myds && sess->client_myds->myconn && sess->client_myds->myconn->userinfo) { + // try to match schemaname + char *schema = sess->client_myds->myconn->userinfo->schemaname; + bool conn_found = false; + unsigned int k; + for (k = i; conn_found == false && k < l; k++) { + conn = (MySQL_Connection *)conns->index(k); + if (strcmp(conn->userinfo->schemaname,schema)==0) { + conn_found = true; + i = k; + } + } + if (conn_found == false ) { + for (k = 0; conn_found == false && k < i; k++) { + conn = (MySQL_Connection *)conns->index(k); + if (strcmp(conn->userinfo->schemaname,schema)==0) { + conn_found = true; + i = k; + } + } + } + if (conn_found == true) { + conn=(MySQL_Connection *)conns->remove_index_fast(i); + } else { + // we may consider creating a new connection + unsigned int conns_free = mysrvc->ConnectionsFree->conns_length(); + unsigned int conns_used = mysrvc->ConnectionsUsed->conns_length(); + if ((conns_used > conns_free) && (mysrvc->max_connections > (conns_free/2 + conns_used/2)) ) { + conn = new MySQL_Connection(); + conn->parent=mysrvc; + __sync_fetch_and_add(&MyHGM->status.server_connections_created, 1); + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "Returning MySQL Connection %p, server %s:%d\n", conn, conn->parent->address, conn->parent->port); + } else { + conn=(MySQL_Connection *)conns->remove_index_fast(i); + } + } + } else { + conn=(MySQL_Connection *)conns->remove_index_fast(i); + } proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "Returning MySQL Connection %p, server %s:%d\n", conn, conn->parent->address, conn->parent->port); return conn; } else { @@ -2080,14 +2118,14 @@ MySQL_Connection * MySrvConnList::get_random_MyConn(bool ff) { return NULL; // never reach here } -MySQL_Connection * MySQL_HostGroups_Manager::get_MyConn_from_pool(unsigned int _hid, bool ff, char * gtid_uuid, uint64_t gtid_trxid) { +MySQL_Connection * MySQL_HostGroups_Manager::get_MyConn_from_pool(unsigned int _hid, MySQL_Session *sess, bool ff, char * gtid_uuid, uint64_t gtid_trxid) { MySQL_Connection * conn=NULL; wrlock(); status.myconnpoll_get++; MyHGC *myhgc=MyHGC_lookup(_hid); MySrvC *mysrvc=myhgc->get_random_MySrvC(gtid_uuid, gtid_trxid); if (mysrvc) { // a MySrvC exists. If not, we return NULL = no targets - conn=mysrvc->ConnectionsFree->get_random_MyConn(ff); + conn=mysrvc->ConnectionsFree->get_random_MyConn(sess, ff); if (conn) { mysrvc->ConnectionsUsed->add(conn); status.myconnpoll_get_ok++; diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index f119e1815b..a327017b26 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -4006,22 +4006,6 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED MySQL_Backend * _gtid_from_backend = NULL; char uuid[64]; uint64_t trxid = 0; -#ifdef STRESSTEST_POOL - int i=100; - while (i) { - if (mc==NULL) { - mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, session_fast_forward); - } - if (mc) { - mybe->server_myds->attach_connection(mc); - if (i > 1) { - mybe->server_myds->return_MySQL_Connection_To_Pool(); - mc=NULL; - } - } - i--; - } -#else if (session_fast_forward == false) { if (qpo->gtid_from_hostgroup >= 0) { _gtid_from_backend = find_backend(qpo->gtid_from_hostgroup); @@ -4043,16 +4027,16 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED } } uuid[n]='\0'; - mc=thread->get_MyConn_local(mybe->hostgroup_id, NULL, uuid, trxid); + mc=thread->get_MyConn_local(mybe->hostgroup_id, this, uuid, trxid); } else { - mc=thread->get_MyConn_local(mybe->hostgroup_id, NULL, NULL, 0); + mc=thread->get_MyConn_local(mybe->hostgroup_id, this, NULL, 0); } } if (mc==NULL) { if (trxid) { - mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, session_fast_forward, uuid, trxid); + mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, session_fast_forward, uuid, trxid); } else { - mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, session_fast_forward, NULL, 0); + mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, session_fast_forward, NULL, 0); } } else { thread->status_variables.ConnPool_get_conn_immediate++; @@ -4063,7 +4047,6 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED } else { thread->status_variables.ConnPool_get_conn_failure++; } -#endif proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Sess=%p -- server_myds=%p -- MySQL_Connection %p\n", this, mybe->server_myds, mybe->server_myds->myconn); if (mybe->server_myds->myconn==NULL) { // we couldn't get a connection for whatever reason, ex: no backends, or too busy diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 79b07f83b0..672fb5662c 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -4623,14 +4623,18 @@ void MySQL_Thread::Get_Memory_Stats() { } -MySQL_Connection * MySQL_Thread::get_MyConn_local(unsigned int _hid, MySQL_Data_Stream *client_myds, char *gtid_uuid, uint64_t gtid_trxid) { +MySQL_Connection * MySQL_Thread::get_MyConn_local(unsigned int _hid, MySQL_Session *sess, char *gtid_uuid, uint64_t gtid_trxid) { unsigned int i; + unsigned int bc = 0; // best candidate + bool pcf = false; // possible candidate found + unsigned int npc = 0; // number of possible candidates std::vector parents; MySQL_Connection *c=NULL; // MySQL_Connection *_candidate = NULL; // this will be used when we will pass optional parameters for (i=0; ilen; i++) { c=(MySQL_Connection *)cached_connections->index(i); if (c->parent->myhgc->hid==_hid) { + if (gtid_uuid) { // we first check if we already excluded this parent (MySQL Server) MySrvC *mysrvc = c->parent; @@ -4641,8 +4645,27 @@ MySQL_Connection * MySQL_Thread::get_MyConn_local(unsigned int _hid, MySQL_Data_ bool gtid_found = false; gtid_found = MyHGM->gtid_exists(mysrvc, gtid_uuid, gtid_trxid); if (gtid_found) { - c=(MySQL_Connection *)cached_connections->remove_index_fast(i); - return c; + //c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + //return c; + + if (pcf == false) { + bc = i; + pcf = true; + } + //npc++; + if (sess && sess->client_myds && sess->client_myds->myconn && sess->client_myds->myconn->userinfo) { + char *schema = sess->client_myds->myconn->userinfo->schemaname; + if (strcmp(c->userinfo->schemaname,schema)==0) { + c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + return c; + } + } else { + c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + return c; + } + + + } else { parents.push_back(mysrvc); // stop evaluating this server // if (_candidate == NULL) { @@ -4651,14 +4674,42 @@ MySQL_Connection * MySQL_Thread::get_MyConn_local(unsigned int _hid, MySQL_Data_ } } } else { - c=(MySQL_Connection *)cached_connections->remove_index_fast(i); - return c; +// c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + + if (pcf == false) { + bc = i; + pcf = true; + } + npc++; + if (sess && sess->client_myds && sess->client_myds->myconn && sess->client_myds->myconn->userinfo) { + char *schema = sess->client_myds->myconn->userinfo->schemaname; + if (strcmp(c->userinfo->schemaname,schema)==0) { + c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + return c; + } + } else { + c=(MySQL_Connection *)cached_connections->remove_index_fast(i); + return c; + } + + //return c; } } } // if (_candidate) { // return _candidate; // } + if (pcf) { // there was a possible connection, but we skipped trying to find a better one + if (gtid_uuid) { + c=(MySQL_Connection *)cached_connections->remove_index_fast(bc); + return c; + } else { + if (npc > 5) { // more candidates were evaluated + c=(MySQL_Connection *)cached_connections->remove_index_fast(bc); + return c; + } + } + } return NULL; }