Added new variable to limit the number of backend connections per second

Variable name is `mysql-throttle_connections_per_sec_to_hostgroup` .
Curently it is a global variable and limits the number of new connections per
hostgroup, and not per specific node.
For example, if mysql-throttle_connections_per_sec_to_hostgroup=100, no more
than 100 new connections can be created on any hostgroup no matter the number
of servers in that hostgroup.
The default is very high (1000000) thus not changing default behaviour.
Tuning this variable allows to control and throttle connections spikes to the
backend servers.

Added also new status variable `Server_Connections_delayed`.
This is a counter of how many times Hostgroup Manager didn't return a
connection because the limit was reached. It is worth to note that a single
client request could make multiple requests, therefore this variable counts
the number of time a new connection wasn't created and not how many requests
were delayed.
pull/1243/head
René Cannaò 9 years ago
parent 9d4b7e3d4c
commit 18f6826ef7

@ -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;

@ -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;

@ -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;

@ -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 ));

@ -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";

Loading…
Cancel
Save