From fe12d26fe4cf69cce7c535dd5cceb4375fe9fc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Thu, 5 May 2016 01:15:39 +0000 Subject: [PATCH] Implementation of mysql-connection_max_age_ms If a connection has a lifetime greated than mysql-connection_max_age_ms , it is dropped See #563 --- include/MySQL_Thread.h | 1 + include/mysql_connection.h | 1 + include/proxysql_structs.h | 2 ++ lib/MySQL_HostGroups_Manager.cpp | 15 +++++++++++++++ lib/MySQL_Thread.cpp | 17 +++++++++++++++++ lib/mysql_connection.cpp | 2 ++ lib/mysql_data_stream.cpp | 12 ++++++++---- 7 files changed, 46 insertions(+), 4 deletions(-) diff --git a/include/MySQL_Thread.h b/include/MySQL_Thread.h index e87fe710b..5970f7143 100644 --- a/include/MySQL_Thread.h +++ b/include/MySQL_Thread.h @@ -266,6 +266,7 @@ class MySQL_Threads_Handler int shun_recovery_time_sec; int connect_retries_on_failure; int connect_retries_delay; + int connection_max_age_ms; int connect_timeout_server; int connect_timeout_server_max; int free_connections_pct; diff --git a/include/mysql_connection.h b/include/mysql_connection.h index 22a3cd156..bbbb00e0e 100644 --- a/include/mysql_connection.h +++ b/include/mysql_connection.h @@ -48,6 +48,7 @@ class MySQL_Connection { char *ptr; } query; char scramble_buff[40]; + unsigned long long creation_time; unsigned long long last_time_used; unsigned long long timeout; int fd; diff --git a/include/proxysql_structs.h b/include/proxysql_structs.h index 04326ddbc..8ece2ff48 100644 --- a/include/proxysql_structs.h +++ b/include/proxysql_structs.h @@ -705,6 +705,7 @@ __thread int mysql_thread___shun_on_failures; __thread int mysql_thread___shun_recovery_time_sec; __thread int mysql_thread___connect_retries_on_failure; __thread int mysql_thread___connect_retries_delay; +__thread int mysql_thread___connection_max_age_ms; __thread int mysql_thread___connect_timeout_server; __thread int mysql_thread___connect_timeout_server_max; __thread uint16_t mysql_thread___server_capabilities; @@ -771,6 +772,7 @@ extern __thread int mysql_thread___shun_on_failures; extern __thread int mysql_thread___shun_recovery_time_sec; extern __thread int mysql_thread___connect_retries_on_failure; extern __thread int mysql_thread___connect_retries_delay; +extern __thread int mysql_thread___connection_max_age_ms; extern __thread int mysql_thread___connect_timeout_server; extern __thread int mysql_thread___connect_timeout_server_max; extern __thread uint16_t mysql_thread___server_capabilities; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index c2aa11705..1784117c6 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -855,6 +855,21 @@ void MySQL_HostGroups_Manager::drop_all_idle_connections() { delete mc; //__sync_fetch_and_sub(&status.server_connections_connected, 1); } + + // drop all connections with life exceeding mysql-connection_max_age + if (mysql_thread___connection_max_age_ms) { + unsigned long long curtime=monotonic_time(); + int i=0; + for (i=0; i<(int)pa->len ; i++) { + MySQL_Connection *mc=(MySQL_Connection *)pa->index(i); + if (curtime > mc->creation_time + mysql_thread___connection_max_age_ms * 1000) { + mc=(MySQL_Connection *)pa->remove_index_fast(0); + delete mc; + i--; + } + } + } + } } } diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 7f640605f..0d59895a2 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -139,6 +139,7 @@ static char * mysql_thread_variables_names[]= { (char *)"shun_recovery_time_sec", (char *)"connect_retries_on_failure", (char *)"connect_retries_delay", + (char *)"connection_max_age_ms", (char *)"connect_timeout_server", (char *)"connect_timeout_server_max", (char *)"eventslog_filename", @@ -214,6 +215,7 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() { variables.shun_on_failures=5; variables.shun_recovery_time_sec=10; variables.connect_retries_on_failure=5; + variables.connection_max_age_ms=0; variables.connect_timeout_server=1000; variables.connect_timeout_server_max=10000; variables.free_connections_pct=10; @@ -392,6 +394,7 @@ int MySQL_Threads_Handler::get_variable_int(char *name) { if (!strcasecmp(name,"shun_on_failures")) return (int)variables.shun_on_failures; if (!strcasecmp(name,"shun_recovery_time_sec")) return (int)variables.shun_recovery_time_sec; if (!strcasecmp(name,"connect_retries_on_failure")) return (int)variables.connect_retries_on_failure; + if (!strcasecmp(name,"connection_max_age_ms")) return (int)variables.connection_max_age_ms; if (!strcasecmp(name,"connect_timeout_server")) return (int)variables.connect_timeout_server; if (!strcasecmp(name,"connect_timeout_server_max")) return (int)variables.connect_timeout_server_max; if (!strcasecmp(name,"connect_retries_delay")) return (int)variables.connect_retries_delay; @@ -516,6 +519,10 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f sprintf(intbuf,"%d",variables.connect_retries_on_failure); return strdup(intbuf); } + if (!strcasecmp(name,"connection_max_age_ms")) { + sprintf(intbuf,"%d",variables.connection_max_age_ms); + return strdup(intbuf); + } if (!strcasecmp(name,"connect_timeout_server")) { sprintf(intbuf,"%d",variables.connect_timeout_server); return strdup(intbuf); @@ -936,6 +943,15 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t return false; } } + if (!strcasecmp(name,"connection_max_age_ms")) { + int intv=atoi(value); + if (intv >= 0 && intv <= 3600*24*1000) { + variables.connection_max_age_ms=intv; + return true; + } else { + return false; + } + } if (!strcasecmp(name,"connect_timeout_server")) { int intv=atoi(value); if (intv >= 10 && intv <= 120*1000) { @@ -1792,6 +1808,7 @@ void MySQL_Thread::refresh_variables() { mysql_thread___shun_on_failures=GloMTH->get_variable_int((char *)"shun_on_failures"); mysql_thread___shun_recovery_time_sec=GloMTH->get_variable_int((char *)"shun_recovery_time_sec"); mysql_thread___connect_retries_on_failure=GloMTH->get_variable_int((char *)"connect_retries_on_failure"); + mysql_thread___connection_max_age_ms=GloMTH->get_variable_int((char *)"connection_max_age_ms"); mysql_thread___connect_timeout_server=GloMTH->get_variable_int((char *)"connect_timeout_server"); mysql_thread___connect_timeout_server_max=GloMTH->get_variable_int((char *)"connect_timeout_server_max"); mysql_thread___free_connections_pct=GloMTH->get_variable_int((char *)"free_connections_pct"); diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index fc829fb9c..0929cce08 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -159,6 +159,7 @@ MySQL_Connection::MySQL_Connection() { query.length=0; largest_query_length=0; MyRS=NULL; + creation_time=0; proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "Creating new MySQL_Connection %p\n", this); }; @@ -765,6 +766,7 @@ int MySQL_Connection::async_connect(short event) { if (async_state_machine==ASYNC_CONNECT_SUCCESSFUL) { async_state_machine=ASYNC_IDLE; myds->wait_until=0; + creation_time=myds->sess->thread->curtime; return 0; } handler(event); diff --git a/lib/mysql_data_stream.cpp b/lib/mysql_data_stream.cpp index c646ca02f..d79ad51a6 100644 --- a/lib/mysql_data_stream.cpp +++ b/lib/mysql_data_stream.cpp @@ -939,10 +939,14 @@ void MySQL_Data_Stream::setDSS_STATE_QUERY_SENT_NET() { void MySQL_Data_Stream::return_MySQL_Connection_To_Pool() { MySQL_Connection *mc=myconn; mc->last_time_used=sess->thread->curtime; - detach_connection(); - unplug_backend(); - //mc->async_state_machine=ASYNC_IDLE; - MyHGM->push_MyConn_to_pool(mc); + if ((mysql_thread___connection_max_age_ms) && (mc->last_time_used > mc->creation_time + mysql_thread___connection_max_age_ms * 1000)) { + destroy_MySQL_Connection_From_Pool(true); + } else { + detach_connection(); + unplug_backend(); + //mc->async_state_machine=ASYNC_IDLE; + MyHGM->push_MyConn_to_pool(mc); + } } void MySQL_Data_Stream::free_mysql_real_query() {