diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index aca4a8f20..6350cc5a6 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -540,7 +540,7 @@ class MySQL_HostGroups_Manager { void drop_all_idle_connections(); int get_multiple_idle_connections(int, unsigned long long, MySQL_Connection **, int); - SQLite3_result * SQL3_Connection_Pool(bool _reset); + SQLite3_result * SQL3_Connection_Pool(bool _reset, int *hid = NULL); SQLite3_result * SQL3_Free_Connections(); void push_MyConn_to_pool(MySQL_Connection *, bool _lock=true); diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index c41dff766..6bb0bb1e0 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -277,6 +277,7 @@ class MySQL_Session void unable_to_parse_set_statement(bool *); bool has_any_backend(); void detected_broken_connection(const char *file, unsigned int line, const char *func, const char *action, MySQL_Connection *myconn, int myerr, const char *message, bool verbose=false); + void generate_status_one_hostgroup(int hid, std::string& s); }; #define KILL_QUERY 1 diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 2bfffb2c5..c82ee0a28 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -2779,6 +2779,7 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ MySrvC *mysrvcCandidates_static[32]; MySrvC **mysrvcCandidates = mysrvcCandidates_static; unsigned int num_candidates = 0; + bool max_connections_reached = false; if (l>32) { mysrvcCandidates = (MySrvC **)malloc(sizeof(MySrvC *)*l); } @@ -2814,6 +2815,8 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ } } } + } else { + max_connections_reached = true; } } else { if (mysrvc->status==MYSQL_SERVER_STATUS_SHUNNED) { @@ -2911,7 +2914,9 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ } if (t - last_hg_log > 1) { // log this at most once per second to avoid spamming the logs last_hg_log = time(NULL); - proxy_error("Hostgroup %u has no servers available! Checking servers shunned for more than %u second%s\n", hid, max_wait_sec, max_wait_sec == 1 ? "" : "s"); + proxy_error("Hostgroup %u has no servers available%s! Checking servers shunned for more than %u second%s\n", hid, + (max_connections_reached ? " or max_connections reached for all servers" : ""), + max_wait_sec, max_wait_sec == 1 ? "" : "s"); } for (j=0; jidx(j); @@ -3776,7 +3781,7 @@ void MySQL_HostGroups_Manager::p_update_connection_pool() { wrunlock(); } -SQLite3_result * MySQL_HostGroups_Manager::SQL3_Connection_Pool(bool _reset) { +SQLite3_result * MySQL_HostGroups_Manager::SQL3_Connection_Pool(bool _reset, int *hid) { const int colnum=14; proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 4, "Dumping Connection Pool\n"); SQLite3_result *result=new SQLite3_result(colnum); @@ -3800,17 +3805,23 @@ SQLite3_result * MySQL_HostGroups_Manager::SQL3_Connection_Pool(bool _reset) { MyHGC *myhgc=(MyHGC *)MyHostGroups->index(i); for (j=0; j<(int)myhgc->mysrvs->cnt(); j++) { MySrvC *mysrvc=(MySrvC *)myhgc->mysrvs->servers->index(j); - if (mysrvc->status!=MYSQL_SERVER_STATUS_ONLINE) { - proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 5, "Server %s:%d is not online\n", mysrvc->address, mysrvc->port); - //__sync_fetch_and_sub(&status.server_connections_connected, mysrvc->ConnectionsFree->conns->len); - mysrvc->ConnectionsFree->drop_all_connections(); - } - // drop idle connections if beyond max_connection - while (mysrvc->ConnectionsFree->conns_length() && mysrvc->ConnectionsUsed->conns_length()+mysrvc->ConnectionsFree->conns_length() > mysrvc->max_connections) { - //MySQL_Connection *conn=(MySQL_Connection *)mysrvc->ConnectionsFree->conns->remove_index_fast(0); - MySQL_Connection *conn=mysrvc->ConnectionsFree->remove(0); - delete conn; - //__sync_fetch_and_sub(&status.server_connections_connected, 1); + if (hid == NULL) { + if (mysrvc->status!=MYSQL_SERVER_STATUS_ONLINE) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 5, "Server %s:%d is not online\n", mysrvc->address, mysrvc->port); + //__sync_fetch_and_sub(&status.server_connections_connected, mysrvc->ConnectionsFree->conns->len); + mysrvc->ConnectionsFree->drop_all_connections(); + } + // drop idle connections if beyond max_connection + while (mysrvc->ConnectionsFree->conns_length() && mysrvc->ConnectionsUsed->conns_length()+mysrvc->ConnectionsFree->conns_length() > mysrvc->max_connections) { + //MySQL_Connection *conn=(MySQL_Connection *)mysrvc->ConnectionsFree->conns->remove_index_fast(0); + MySQL_Connection *conn=mysrvc->ConnectionsFree->remove(0); + delete conn; + //__sync_fetch_and_sub(&status.server_connections_connected, 1); + } + } else { + if (*hid != (int)myhgc->hid) { + continue; + } } char buf[1024]; char **pta=(char **)malloc(sizeof(char *)*colnum); diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index c90f2f9a4..5cb49d2f5 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -2564,6 +2564,9 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) { } client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,9001,(char *)"HY000",buf, true); RequestEnd(mybe->server_myds); + std::string errmsg; + generate_status_one_hostgroup(current_hostgroup, errmsg); + proxy_error("%s . HG status: %s\n", buf, errmsg.c_str()); //enum session_status st; while (previous_status.size()) { previous_status.top(); @@ -7095,3 +7098,23 @@ void MySQL_Session::detected_broken_connection(const char *file, unsigned int li proxy_error_inline(file, line, func, "Detected a broken connection while %s on (%d,%s,%d,%lu) , user %s , last_used %llums ago : %d, %s\n", action, myconn->parent->myhgc->hid, myconn->parent->address, myconn->parent->port, myconn->get_mysql_thread_id(), myconn->userinfo->username, last_used, myerr, msg); } } + +void MySQL_Session::generate_status_one_hostgroup(int hid, std::string& s) { + SQLite3_result *resultset = MyHGM->SQL3_Connection_Pool(false, &hid); + json j_res; + if (resultset->rows_count) { + for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { + SQLite3_row *r=*it; + json j; // one json for each row + for (int i=0; icolumns; i++) { + // using the format j["name"] == "value" + j[resultset->column_definition[i]->name] = ( r->fields[i] ? r->fields[i] : "(null)" ); + } + j_res.push_back(j); // the row json is added to the final json + } + } else { + j_res=json::array(); + } + s = j_res.dump(); + delete resultset; +}