diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index cef659bf5..08ed86497 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -122,6 +122,8 @@ class MySrvList { // MySQL Server List class MyHGC { // MySQL Host Group Container public: unsigned int hid; + unsigned long long current_time_now; + uint32_t new_connections_now; MySrvList *mysrvs; MyHGC(int); ~MyHGC(); @@ -188,6 +190,7 @@ class MySQL_HostGroups_Manager { int client_connections; unsigned long server_connections_aborted; unsigned long server_connections_created; + unsigned long server_connections_delayed; unsigned long server_connections_connected; unsigned long myconnpoll_get; unsigned long myconnpoll_get_ok; diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index c1183ad45..f702d3edc 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -365,6 +365,7 @@ class MySQL_Threads_Handler bool enforce_autocommit_on_reads; bool autocommit_false_not_reusable; int max_allowed_packet; + int throttle_connections_per_sec_to_hostgroup; int max_transaction_time; int threshold_query_length; int threshold_resultset_size; diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 24cad7d1b..8dab9dc1b 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -589,6 +589,7 @@ __thread char *mysql_thread___init_connect; __thread char *mysql_thread___default_sql_mode; __thread char *mysql_thread___default_time_zone; __thread int mysql_thread___max_allowed_packet; +__thread int mysql_thread___throttle_connections_per_sec_to_hostgroup; __thread int mysql_thread___max_transaction_time; __thread int mysql_thread___threshold_query_length; __thread int mysql_thread___threshold_resultset_size; @@ -688,6 +689,7 @@ extern __thread char *mysql_thread___init_connect; extern __thread char *mysql_thread___default_sql_mode; extern __thread char *mysql_thread___default_time_zone; extern __thread int mysql_thread___max_allowed_packet; +extern __thread int mysql_thread___throttle_connections_per_sec_to_hostgroup; extern __thread int mysql_thread___max_transaction_time; extern __thread int mysql_thread___threshold_query_length; extern __thread int mysql_thread___threshold_resultset_size; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 6ce477578..857860478 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -320,6 +320,8 @@ MySrvList::~MySrvList() { MyHGC::MyHGC(int _hid) { hid=_hid; mysrvs=new MySrvList(this); + current_time_now = 0; + new_connections_now = 0; } @@ -1387,11 +1389,24 @@ MySQL_Connection * MySrvConnList::get_random_MyConn(bool ff) { 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 { - 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); - return conn; + unsigned long long curtime = monotonic_time(); + curtime = curtime / 1000 / 1000; // convert to second + MyHGC *_myhgc = mysrvc->myhgc; + if (curtime > _myhgc->current_time_now) { + _myhgc->current_time_now = curtime; + _myhgc->new_connections_now = 0; + } + _myhgc->new_connections_now++; + if (_myhgc->new_connections_now > (unsigned int) mysql_thread___throttle_connections_per_sec_to_hostgroup) { + __sync_fetch_and_add(&MyHGM->status.server_connections_delayed, 1); + return NULL; + } else { + 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); + return conn; + } } return NULL; // never reach here } @@ -1404,8 +1419,10 @@ MySQL_Connection * MySQL_HostGroups_Manager::get_MyConn_from_pool(unsigned int _ MySrvC *mysrvc=myhgc->get_random_MySrvC(); if (mysrvc) { // a MySrvC exists. If not, we return NULL = no targets conn=mysrvc->ConnectionsFree->get_random_MyConn(ff); - mysrvc->ConnectionsUsed->add(conn); - status.myconnpoll_get_ok++; + if (conn) { + mysrvc->ConnectionsUsed->add(conn); + status.myconnpoll_get_ok++; + } } wrunlock(); proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "Returning MySQL Connection %p, server %s:%d\n", conn, (conn ? conn->parent->address : "") , (conn ? conn->parent->port : 0 )); diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 352fcefa4..9b66946b1 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -232,6 +232,7 @@ static char * mysql_thread_variables_names[]= { (char *)"monitor_wait_timeout", (char *)"monitor_writer_is_also_reader", (char *)"max_allowed_packet", + (char *)"throttle_connections_per_sec_to_hostgroup", (char *)"max_transaction_time", (char *)"multiplexing", (char *)"forward_autocommit", @@ -342,6 +343,7 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() { variables.monitor_wait_timeout=true; variables.monitor_writer_is_also_reader=true; variables.max_allowed_packet=4*1024*1024; + variables.throttle_connections_per_sec_to_hostgroup=1000000; variables.max_transaction_time=4*3600*1000; variables.hostgroup_manager_verbose=1; variables.threshold_query_length=512*1024; @@ -596,6 +598,7 @@ int MySQL_Threads_Handler::get_variable_int(char *name) { if (!strcasecmp(name,"connect_retries_delay")) return (int)variables.connect_retries_delay; if (!strcasecmp(name,"eventslog_filesize")) return (int)variables.eventslog_filesize; if (!strcasecmp(name,"max_allowed_packet")) return (int)variables.max_allowed_packet; + if (!strcasecmp(name,"throttle_connections_per_sec_to_hostgroup")) return (int)variables.throttle_connections_per_sec_to_hostgroup; if (!strcasecmp(name,"max_transaction_time")) return (int)variables.max_transaction_time; if (!strcasecmp(name,"hostgroup_manager_verbose")) return (int)variables.hostgroup_manager_verbose; if (!strcasecmp(name,"threshold_query_length")) return (int)variables.threshold_query_length; @@ -848,6 +851,10 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f sprintf(intbuf,"%d",variables.max_allowed_packet); return strdup(intbuf); } + if (!strcasecmp(name,"throttle_connections_per_sec_to_hostgroup")) { + sprintf(intbuf,"%d",variables.throttle_connections_per_sec_to_hostgroup); + return strdup(intbuf); + } if (!strcasecmp(name,"max_transaction_time")) { sprintf(intbuf,"%d",variables.max_transaction_time); return strdup(intbuf); @@ -1220,6 +1227,15 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t return false; } } + if (!strcasecmp(name,"throttle_connections_per_sec_to_hostgroup")) { + int intv=atoi(value); + if (intv >= 1 && intv <= 100*1000*1000) { + variables.throttle_connections_per_sec_to_hostgroup=intv; + return true; + } else { + return false; + } + } if (!strcasecmp(name,"hostgroup_manager_verbose")) { int intv=atoi(value); if (intv >= 0 && intv <= 1) { @@ -3058,6 +3074,7 @@ void MySQL_Thread::refresh_variables() { GloMTH->wrlock(); __thread_MySQL_Thread_Variables_version=__global_MySQL_Thread_Variables_version; mysql_thread___max_allowed_packet=GloMTH->get_variable_int((char *)"max_allowed_packet"); + mysql_thread___throttle_connections_per_sec_to_hostgroup=GloMTH->get_variable_int((char *)"throttle_connections_per_sec_to_hostgroup"); mysql_thread___max_transaction_time=GloMTH->get_variable_int((char *)"max_transaction_time"); mysql_thread___threshold_query_length=GloMTH->get_variable_int((char *)"threshold_query_length"); mysql_thread___threshold_resultset_size=GloMTH->get_variable_int((char *)"threshold_resultset_size"); @@ -3378,6 +3395,13 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_GlobalStatus() { pta[1]=buf; result->add_row(pta); } + { + // Connections delayed + pta[0]=(char *)"Server_Connections_delayed"; + sprintf(buf,"%lu",MyHGM->status.server_connections_delayed); + pta[1]=buf; + result->add_row(pta); + } #ifdef IDLE_THREADS { // Connections non idle pta[0]=(char *)"Client_Connections_non_idle";