Skip to content

Commit 3f1c89f

Browse files
committed
Enable session tracking based on server capabilities
Signed-off-by: Wazir Ahmed <[email protected]>
1 parent 11cb475 commit 3f1c89f

File tree

8 files changed

+102
-12
lines changed

8 files changed

+102
-12
lines changed

include/MySQL_HostGroups_Manager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ class MySrvC { // MySQL Server Container
227227
bool shunned_and_kill_all_connections; // if a serious failure is detected, this will cause all connections to die even if the server is just shunned
228228
int32_t use_ssl;
229229
char *comment;
230+
231+
// 'server_backoff_time' stores a timestamp that prevents the server from being
232+
// considered for random selection ('MyHGC::get_random_MySrvC') until that time passes.
233+
//
234+
// This is primarily used when `session_track_variables::ENFORCED` mode is active.
235+
// If a server lacks the required capabilities in this mode, it is temporarily
236+
// excluded from selection for a specified duration.
237+
unsigned long long server_backoff_time;
238+
230239
MySrvConnList *ConnectionsUsed;
231240
MySrvConnList *ConnectionsFree;
232241
/**

include/MySQL_Session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ class MySQL_Session: public Base_Session<MySQL_Session, MySQL_Data_Stream, MySQL
554554
void reset_warning_hostgroup_flag_and_release_connection();
555555
void set_previous_status_mode3(bool allow_execute=true);
556556
char* get_current_query(int max_length = -1);
557+
bool handle_session_track_capabilities();
557558

558559
friend void SQLite3_Server_session_handler(MySQL_Session*, void *_pa, PtrSize_t *pkt);
559560

include/MySQL_Thread.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,13 @@ struct th_metrics_map_idx {
361361
*/
362362
struct session_track_variables {
363363
enum mode {
364-
DISABLED = 0, ///< Session variable tracking is disabled (default)
365-
ENABLED ///< Session variable tracking is enabled
364+
// Disabled; default mode
365+
DISABLED = 0,
366+
// Enable session tracking if backend supports it
367+
OPTIONAL,
368+
// Enforce session tracking; connection fails if backend does
369+
// not support CLIENT_DEPRECATE_EOF and CLIENT_SESSION_TRACKING
370+
ENFORCED
366371
};
367372
};
368373

lib/MyHGC.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ MySrvC *MyHGC::get_random_MySrvC(char * gtid_uuid, uint64_t gtid_trxid, int max_
3838
for (j=0; j<l; j++) {
3939
mysrvc=mysrvs->idx(j);
4040
if (mysrvc->get_status() == MYSQL_SERVER_STATUS_ONLINE) { // consider this server only if ONLINE
41+
// skip servers that are in backoff period
42+
if (mysrvc->server_backoff_time > sess->thread->curtime)
43+
continue;
44+
4145
if (mysrvc->myhgc->num_online_servers.load(std::memory_order_relaxed) <= mysrvc->myhgc->attributes.max_num_online_servers) { // number of online servers in HG is within configured range
4246
if (mysrvc->ConnectionsUsed->conns_length() < mysrvc->max_connections) { // consider this server only if didn't reach max_connections
4347
if (mysrvc->current_latency_us < (mysrvc->max_latency_us ? mysrvc->max_latency_us : mysql_thread___default_max_latency_ms*1000)) { // consider the host only if not too far

lib/MySQL_Session.cpp

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,10 +1908,12 @@ bool MySQL_Session::handler_again___verify_backend_session_track_gtids() {
19081908
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Session %p , client: %s , backend: %s\n", this, client_myds->myconn->options.session_track_gtids, mybe->server_myds->myconn->options.session_track_gtids);
19091909
// we first verify that the backend supports it
19101910
// if backend is old (or if it is not mysql) ignore this setting
1911-
if ((mybe->server_myds->myconn->mysql->server_capabilities & CLIENT_SESSION_TRACKING) == 0) {
1912-
// the backend doesn't support CLIENT_SESSION_TRACKING
1913-
return ret; // exit immediately
1911+
if ((mybe->server_myds->myconn->mysql->server_capabilities & CLIENT_SESSION_TRACKING) == 0
1912+
|| (mybe->server_myds->myconn->mysql->server_capabilities & CLIENT_DEPRECATE_EOF) == 0
1913+
|| mysql_thread___enable_server_deprecate_eof == false) {
1914+
return ret;
19141915
}
1916+
19151917
uint32_t b_int = mybe->server_myds->myconn->options.session_track_gtids_int;
19161918
uint32_t f_int = client_myds->myconn->options.session_track_gtids_int;
19171919

@@ -1958,16 +1960,26 @@ bool MySQL_Session::handler_again___verify_backend_session_track_gtids() {
19581960
}
19591961

19601962
bool MySQL_Session::handler_again___verify_backend_session_track_variables() {
1961-
if (mysql_thread___session_track_variables == session_track_variables::DISABLED) {
1963+
int mode = mysql_thread___session_track_variables;
1964+
1965+
// skip enabling session variable tracking in the following cases
1966+
if (mode == session_track_variables::DISABLED) {
1967+
return false;
1968+
}
1969+
if ((mybe->server_myds->myconn->mysql->server_capabilities & CLIENT_SESSION_TRACKING) == 0
1970+
|| (mybe->server_myds->myconn->mysql->server_capabilities & CLIENT_DEPRECATE_EOF) == 0) {
1971+
return false;
1972+
}
1973+
if (!mysql_thread___enable_server_deprecate_eof && mode != session_track_variables::ENFORCED) {
19621974
return false;
19631975
}
19641976

1977+
// enable session tracking
19651978
if (mybe->server_myds->myconn->options.session_track_variables_sent == false) {
19661979
mybe->server_myds->myconn->options.session_track_variables_sent = true;
19671980
set_previous_status_mode3();
19681981
NEXT_IMMEDIATE_NEW(SETTING_SESSION_TRACK_VARIABLES);
19691982
}
1970-
19711983
if (mybe->server_myds->myconn->options.session_track_state_sent == false) {
19721984
mybe->server_myds->myconn->options.session_track_state_sent = true;
19731985
set_previous_status_mode3();
@@ -2937,6 +2949,11 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
29372949
}
29382950
enum session_status st=status;
29392951
if (mybe->server_myds->myconn->async_state_machine==ASYNC_IDLE) {
2952+
if (handle_session_track_capabilities() == false) {
2953+
pause_until = thread->curtime + mysql_thread___connect_retries_delay*1000;
2954+
return false;
2955+
}
2956+
29402957
st=previous_status.top();
29412958
previous_status.pop();
29422959
NEXT_IMMEDIATE_NEW(st);
@@ -2966,6 +2983,12 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
29662983
previous_status.pop();
29672984
myds->wait_until=0;
29682985

2986+
if (handle_session_track_capabilities() == false) {
2987+
pause_until = thread->curtime + mysql_thread___connect_retries_delay*1000;
2988+
set_status(CONNECTING_SERVER);
2989+
return false;
2990+
}
2991+
29692992
// NOTE: Even if a connection has correctly been created, since the CLIENT_DEPRECATE_EOF
29702993
// capability isn't always enforced to match for backend conns (no direct propagation), a
29712994
// mismatch can take place after the creation. Right now this is only true for
@@ -8271,3 +8294,41 @@ char* MySQL_Session::get_current_query(int max_length) {
82718294

82728295
return res;
82738296
}
8297+
8298+
/**
8299+
* @brief Handle session track capabilities validation.
8300+
*
8301+
* This function validates whether the backend connection has capabilities such as 'CLIENT_DEPRECATE_EOF'
8302+
* and 'CLIENT_SESSION_TRACKING' which are required to enable 'session_track_system_variables' in a MySQL session.
8303+
*
8304+
* If the connection lacks the capabilities and ProxySQL configuration is set in 'ENFORCED' mode, it returns the
8305+
* connection to the pool and set a backoff time for the backend server. This backoff time prevents the server from
8306+
* being selected again during connection pooling.
8307+
*
8308+
* @return 'true' if backend connection has required capabilities, otherwise returns 'false'.
8309+
*/
8310+
bool MySQL_Session::handle_session_track_capabilities() {
8311+
if (mysql_thread___session_track_variables != session_track_variables::ENFORCED) {
8312+
return true;
8313+
}
8314+
8315+
// this function should not be called in these states
8316+
if (mybe == NULL
8317+
|| mybe->server_myds == NULL
8318+
|| mybe->server_myds->myconn == NULL
8319+
|| mybe->server_myds->myconn->mysql == NULL) {
8320+
return true;
8321+
}
8322+
8323+
MySQL_Connection *be_conn = mybe->server_myds->myconn;
8324+
unsigned long srv_cap = be_conn->mysql->server_capabilities;
8325+
8326+
if ((srv_cap & CLIENT_DEPRECATE_EOF) == 0 || (srv_cap & CLIENT_SESSION_TRACKING) == 0) {
8327+
// be_conn->parent->server_backoff_time = thread->curtime + (600 * 1000000); // 10 minutes
8328+
be_conn->parent->server_backoff_time = thread->curtime + (30 * 1000000); // 30 seconds
8329+
mybe->server_myds->return_MySQL_Connection_To_Pool();
8330+
return false;
8331+
}
8332+
8333+
return true;
8334+
}

lib/MySQL_Thread.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,7 @@ char ** MySQL_Threads_Handler::get_variables_list() {
23392339
VariablesPointers_int["eventslog_format"] = make_tuple(&variables.eventslog_format, 0, 0, true);
23402340
VariablesPointers_int["wait_timeout"] = make_tuple(&variables.wait_timeout, 0, 0, true);
23412341
VariablesPointers_int["data_packets_history_size"] = make_tuple(&variables.data_packets_history_size, 0, 0, true);
2342-
VariablesPointers_int["session_track_variables"] = make_tuple(&variables.session_track_variables, 0, 1, false);
2342+
VariablesPointers_int["session_track_variables"] = make_tuple(&variables.session_track_variables, 0, 2, false);
23432343
}
23442344

23452345

@@ -5611,7 +5611,11 @@ MySQL_Connection * MySQL_Thread::get_MyConn_local(unsigned int _hid, MySQL_Sessi
56115611
std::vector<MySrvC *> parents; // this is a vector of srvers that needs to be excluded in case gtid_uuid is used
56125612
MySQL_Connection *c=NULL;
56135613
for (i=0; i<cached_connections->len; i++) {
5614-
c=(MySQL_Connection *)cached_connections->index(i);
5614+
c = (MySQL_Connection *) cached_connections->index(i);
5615+
// skip servers that are in backoff period
5616+
if (c->parent->server_backoff_time > curtime)
5617+
continue;
5618+
56155619
if (c->parent->myhgc->hid==_hid && sess->client_myds->myconn->match_tracked_options(c)) { // options are all identical
56165620
if (
56175621
(gtid_uuid == NULL) || // gtid_uuid is not used

lib/MySrvC.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ MySrvC::MySrvC(
3131
bytes_recv=0;
3232
max_connections_used=0;
3333
queries_gtid_sync=0;
34+
server_backoff_time = 0;
3435
time_last_detected_error=0;
3536
connect_ERR_at_time_last_detected_error=0;
3637
shunned_automatic=false;

lib/mysql_connection.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -868,13 +868,18 @@ void MySQL_Connection::connect_start_SetClientFlag(unsigned long& client_flags)
868868
}
869869
}
870870

871-
// set 'CLIENT_DEPRECATE_EOF' flag if explicitly stated by 'mysql-enable_server_deprecate_eof'.
872-
// Capability is disabled by default in 'mariadb_client', so setting this option is not optional
873-
// for having 'CLIENT_DEPRECATE_EOF' in the connection to be stablished.
871+
// 'CLIENT_DEPRECATE_EOF' capability is disabled by default in mariadb_client.
872+
// Based on the value of 'mysql-enable_server_deprecate_eof', enable this
873+
// capability in a new connection.
874874
if (mysql_thread___enable_server_deprecate_eof) {
875875
mysql->options.client_flag |= CLIENT_DEPRECATE_EOF;
876876
}
877877

878+
// override 'mysql-enable_server_deprecate_eof' behavior if 'session_track_variables' is set to 'ENFORCED'
879+
if (mysql_thread___session_track_variables == session_track_variables::ENFORCED) {
880+
mysql->options.client_flag |= CLIENT_DEPRECATE_EOF;
881+
}
882+
878883
if (myds != NULL) {
879884
if (myds->sess != NULL) {
880885
if (myds->sess->session_fast_forward) { // this is a fast_forward connection

0 commit comments

Comments
 (0)