diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index 2a593d3ce5..c625f9183b 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -305,6 +305,12 @@ class MySQL_Session PtrArray *mybes; MySQL_Data_Stream *client_myds; MySQL_Data_Stream *server_myds; + + // Storage for per-hostgroup backend server hints + std::map sticky_backend_hint; + + int sticky_backend; + /* * @brief Store the hostgroups that hold connections that have been flagged as 'expired' by the * maintenance thread. These values will be used to release the retained connections in the specific diff --git a/include/query_processor.h b/include/query_processor.h index 9d62330291..5082a00f0a 100644 --- a/include/query_processor.h +++ b/include/query_processor.h @@ -131,6 +131,7 @@ class Query_Processor_Output { int timeout; int retries; int delay; + int sticky_backend; char *error_msg; char *OK_msg; int sticky_conn; @@ -170,6 +171,7 @@ class Query_Processor_Output { timeout=-1; retries=-1; delay=-1; + sticky_backend=-1; sticky_conn=-1; multiplex=-1; gtid_from_hostgroup=-1; diff --git a/lib/MyHGC.cpp b/lib/MyHGC.cpp index 8742db240c..017074fad4 100644 --- a/lib/MyHGC.cpp +++ b/lib/MyHGC.cpp @@ -362,6 +362,36 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ k++; New_sum=0; + // This is promoting the stickyness value in the query hint to be a session variable + if (sess->qpo->sticky_backend != -1 && 0 <= sess->qpo->sticky_backend && sess->qpo->sticky_backend <= 2) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "promoting sticky_backend with value %d\n", sess->qpo->sticky_backend); + sess->sticky_backend = sess->qpo->sticky_backend; + } + + if (sess->sticky_backend > 0) { + if (auto my_srv_hint = sess->sticky_backend_hint.find(this->hid); my_srv_hint != sess->sticky_backend_hint.end()) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "found prefered sticky backend\n"); + for (j=0; jsecond) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "matched prefered sticky backend\n"); + return mysrvc; + } + } + + //Abort if we can't find the backend in candidates and we are in strict mode. + if (sess->sticky_backend==2) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "didn't match prefered sticky backend in strict mode\n"); + return NULL; + } + + // We are clearing the server because .insert doesn't replace... + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "clearing prefered sticky backend in strict mode\n"); + sess->sticky_backend_hint.erase(this->hid); + } + } + + for (j=0; jweight; @@ -373,6 +403,14 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_ #ifdef TEST_AURORA array_mysrvc_cands += num_candidates; #endif // TEST_AURORA + if (sess->sticky_backend > 0) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "insert prefered sticky backend\n"); + sess->sticky_backend_hint.insert({this->hid, mysrvc}); + } else { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 7, "erase prefered sticky backend\n"); + sess->sticky_backend_hint.erase(this->hid); + } + return mysrvc; } } diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index ae306e36e4..ef00073deb 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -728,6 +728,12 @@ MySQL_Session::MySQL_Session() { use_ssl = false; change_user_auth_switch = false; + // Session-level status of the sticky_backend + // 0 means non-sticky + // 1 means sticky, fallback to new server in case of server failure + // 2 means strictly sticky, throw an error in case of server failure + sticky_backend=0; + //gtid_trxid = 0; gtid_hid = -1; memset(gtid_buf,0,sizeof(gtid_buf)); diff --git a/lib/Query_Processor.cpp b/lib/Query_Processor.cpp index 2918104821..8618feed83 100644 --- a/lib/Query_Processor.cpp +++ b/lib/Query_Processor.cpp @@ -2600,6 +2600,12 @@ bool Query_Processor::query_parser_first_comment(Query_Processor_Output *qpo, ch remove_spaces(value); if (strlen(key)) { char c=value[0]; + if (!strcasecmp(key,"sticky_backend")) { + if (c >= '0' && c <= '9') { // it is a digit + int t=atoi(value); + qpo->sticky_backend=t; + } + } if (!strcasecmp(key,"cache_ttl")) { if (c >= '0' && c <= '9') { // it is a digit int t=atoi(value);