Skip to content

Commit 7709911

Browse files
committed
MySQL: Track session-specific system variables changes
- Add new mysql variable `mysql-session_track_variables`. - Configure `session_track_system_variables` and `session_track_state_change` on backend connections if the mysql variable is enabled. - Utilize notifications from backend servers to capture system variable changes that cannot be handled by `MySQL_Set_Stmt_Parser` - Update both client and server variable maps based on backend responses. - TAP test to verify this patch. Signed-off-by: Wazir Ahmed <[email protected]>
1 parent cce161b commit 7709911

11 files changed

+245
-6
lines changed

include/MySQL_Session.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,16 @@ class MySQL_Session: public Base_Session<MySQL_Session, MySQL_Data_Stream, MySQL
225225
bool handler_again___verify_ldap_user_variable();
226226
bool handler_again___verify_backend_autocommit();
227227
bool handler_again___verify_backend_session_track_gtids();
228+
bool handler_again___verify_backend_session_track_variables();
228229
bool handler_again___verify_backend_multi_statement();
229230
bool handler_again___verify_backend_user_schema();
230231
bool handler_again___verify_multiple_variables(MySQL_Connection *);
231232
bool handler_again___status_SETTING_INIT_CONNECT(int *);
232233
bool handler_again___status_SETTING_LDAP_USER_VARIABLE(int *);
233234
bool handler_again___status_SETTING_SQL_MODE(int *);
234235
bool handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *);
236+
bool handler_again___status_SETTING_SESSION_TRACK_VARIABLES(int *);
237+
bool handler_again___status_SETTING_SESSION_TRACK_STATE(int *);
235238
bool handler_again___status_CHANGING_CHARSET(int *_rc);
236239
bool handler_again___status_CHANGING_SCHEMA(int *);
237240
bool handler_again___status_CONNECTING_SERVER(int *);
@@ -280,6 +283,7 @@ class MySQL_Session: public Base_Session<MySQL_Session, MySQL_Data_Stream, MySQL
280283
int RunQuery(MySQL_Data_Stream *myds, MySQL_Connection *myconn);
281284
void handler___status_WAITING_CLIENT_DATA();
282285
void handler_rc0_Process_GTID(MySQL_Connection *myconn);
286+
void handler_rc0_Process_Variables(MySQL_Connection *myconn);
283287
void handler_rc0_RefreshActiveTransactions(MySQL_Connection* myconn);
284288
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_INIT_DB_replace_CLICKHOUSE(PtrSize_t& pkt);
285289
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY___not_mysql(PtrSize_t& pkt);

include/MySQL_Thread.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,13 @@ struct th_metrics_map_idx {
326326
};
327327
};
328328

329+
struct session_track_variables {
330+
enum mode {
331+
DISABLED = 0,
332+
ENABLED
333+
};
334+
};
335+
329336
/**
330337
* @brief Structure holding the data for a Client_Host_Cache entry.
331338
*/
@@ -579,6 +586,7 @@ class MySQL_Threads_Handler
579586
int processlist_max_query_length;
580587

581588
bool ignore_min_gtid_annotations;
589+
int session_track_variables;
582590
} variables;
583591
struct {
584592
unsigned int mirror_sessions_current;

include/mysql_connection.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class MySQL_Connection {
8989
char *ldap_user_variable;
9090
char *ldap_user_variable_value;
9191
bool session_track_gtids_sent;
92+
bool session_track_variables_sent;
93+
bool session_track_state_sent;
9294
bool ldap_user_variable_sent;
9395
uint8_t protocol_version;
9496
int8_t last_set_autocommit;
@@ -262,6 +264,7 @@ class MySQL_Connection {
262264
void reset();
263265

264266
bool get_gtid(char *buff, uint64_t *trx_id);
267+
bool get_variables(std::unordered_map<std::string, std::string>&);
265268
void reduce_auto_increment_delay_token() { if (auto_increment_delay_token) auto_increment_delay_token--; };
266269

267270
bool match_ff_req_options(const MySQL_Connection *c);

include/proxysql_structs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ enum session_status {
311311
SETTING_NEXT_TRANSACTION_READ,
312312
PROCESSING_EXTENDED_QUERY_SYNC,
313313
RESYNCHRONIZING_CONNECTION,
314+
SETTING_SESSION_TRACK_VARIABLES,
315+
SETTING_SESSION_TRACK_STATE,
314316
session_status___NONE // special marker
315317
};
316318

@@ -1304,6 +1306,7 @@ __thread int mysql_thread___client_host_error_counts;
13041306
__thread int mysql_thread___handle_warnings;
13051307
__thread int mysql_thread___evaluate_replication_lag_on_servers_load;
13061308
__thread bool mysql_thread___ignore_min_gtid_annotations;
1309+
__thread int mysql_thread___session_track_variables;
13071310

13081311
/* variables used for Query Cache */
13091312
__thread int mysql_thread___query_cache_size_MB;
@@ -1607,6 +1610,7 @@ extern __thread int mysql_thread___client_host_error_counts;
16071610
extern __thread int mysql_thread___handle_warnings;
16081611
extern __thread int mysql_thread___evaluate_replication_lag_on_servers_load;
16091612
extern __thread bool mysql_thread___ignore_min_gtid_annotations;
1613+
extern __thread int mysql_thread___session_track_variables;
16101614

16111615
/* variables used for Query Cache */
16121616
extern __thread int mysql_thread___query_cache_size_MB;

lib/MySQL_Session.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,6 +1953,25 @@ bool MySQL_Session::handler_again___verify_backend_session_track_gtids() {
19531953
return ret;
19541954
}
19551955

1956+
bool MySQL_Session::handler_again___verify_backend_session_track_variables() {
1957+
if (mysql_thread___session_track_variables == session_track_variables::DISABLED) {
1958+
return false;
1959+
}
1960+
1961+
if (mybe->server_myds->myconn->options.session_track_variables_sent == false) {
1962+
mybe->server_myds->myconn->options.session_track_variables_sent = true;
1963+
set_previous_status_mode3();
1964+
NEXT_IMMEDIATE_NEW(SETTING_SESSION_TRACK_VARIABLES);
1965+
}
1966+
1967+
if (mybe->server_myds->myconn->options.session_track_state_sent == false) {
1968+
mybe->server_myds->myconn->options.session_track_state_sent = true;
1969+
set_previous_status_mode3();
1970+
NEXT_IMMEDIATE_NEW(SETTING_SESSION_TRACK_STATE);
1971+
}
1972+
1973+
return false;
1974+
}
19561975

19571976
bool MySQL_Session::handler_again___verify_multiple_variables(MySQL_Connection* myconn) {
19581977
for (auto i = 0; i < SQL_NAME_LAST_LOW_WM; i++) {
@@ -2753,6 +2772,20 @@ bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *_rc)
27532772
return ret;
27542773
}
27552774

2775+
bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_VARIABLES(int *_rc) {
2776+
bool ret=false;
2777+
assert(mybe->server_myds->myconn);
2778+
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"session_track_system_variables", "*", false);
2779+
return ret;
2780+
}
2781+
2782+
bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_STATE(int *_rc) {
2783+
bool ret=false;
2784+
assert(mybe->server_myds->myconn);
2785+
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"session_track_state_change", "ON", false);
2786+
return ret;
2787+
}
2788+
27562789
bool MySQL_Session::handler_again___status_CHANGING_SCHEMA(int *_rc) {
27572790
bool ret=false;
27582791
//fprintf(stderr,"CHANGING_SCHEMA\n");
@@ -4862,6 +4895,41 @@ void MySQL_Session::handler_rc0_Process_GTID(MySQL_Connection *myconn) {
48624895
}
48634896
}
48644897

4898+
void MySQL_Session::handler_rc0_Process_Variables(MySQL_Connection *myconn) {
4899+
std::unordered_map<string, string> var_map;
4900+
4901+
if(myconn->get_variables(var_map)) {
4902+
std::string variable;
4903+
std::string value;
4904+
4905+
for (int idx = 0 ; idx < SQL_NAME_LAST_HIGH_WM ; idx++) {
4906+
variable = mysql_tracked_variables[idx].set_variable_name;
4907+
4908+
auto itr = var_map.find(variable);
4909+
if(itr != var_map.end()) {
4910+
value = itr->second;
4911+
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 7, "Session=%p, backend=%p. Notification for session_track_system_variables: variable=%s, value=%s\n", this, this->mybe, variable.c_str(), value.c_str());
4912+
4913+
const MARIADB_CHARSET_INFO *ci = NULL;
4914+
if (variable == "character_set_results" || variable == "character_set_connection" ||
4915+
variable == "character_set_client" || variable == "character_set_database") {
4916+
ci = proxysql_find_charset_name(value.c_str());
4917+
}
4918+
else if (variable == "collation_connection") {
4919+
ci = proxysql_find_charset_collate(value.c_str());
4920+
}
4921+
4922+
if (ci) {
4923+
value = std::to_string(ci->nr);
4924+
}
4925+
4926+
mysql_variables.client_set_value(this, idx, value);
4927+
mysql_variables.server_set_value(this, idx, value.c_str());
4928+
}
4929+
}
4930+
}
4931+
}
4932+
48654933
void MySQL_Session::handler_KillConnectionIfNeeded() {
48664934
if ( // two conditions
48674935
// If the server connection is in a non-idle state (ASYNC_IDLE), and the current time is greater than or equal to mybe->server_myds->wait_until
@@ -5059,6 +5127,10 @@ int MySQL_Session::handler() {
50595127
goto handler_again;
50605128
}
50615129

5130+
if (handler_again___verify_backend_session_track_variables()) {
5131+
goto handler_again;
5132+
}
5133+
50625134
// Optimize network traffic when we can use 'SET NAMES'
50635135
if (verify_set_names(this)) {
50645136
goto handler_again;
@@ -5139,6 +5211,8 @@ int MySQL_Session::handler() {
51395211

51405212
handler_rc0_Process_GTID(myconn);
51415213

5214+
handler_rc0_Process_Variables(myconn);
5215+
51425216
// if we are locked on hostgroup, the value of autocommit is copied from the backend connection
51435217
// see bug #3549
51445218
if (locked_on_hostgroup >= 0) {
@@ -5435,6 +5509,12 @@ bool MySQL_Session::handler_again___multiple_statuses(int *rc) {
54355509
case SETTING_SESSION_TRACK_GTIDS:
54365510
ret = handler_again___status_SETTING_SESSION_TRACK_GTIDS(rc);
54375511
break;
5512+
case SETTING_SESSION_TRACK_VARIABLES:
5513+
ret = handler_again___status_SETTING_SESSION_TRACK_VARIABLES(rc);
5514+
break;
5515+
case SETTING_SESSION_TRACK_STATE:
5516+
ret = handler_again___status_SETTING_SESSION_TRACK_STATE(rc);
5517+
break;
54385518
case SETTING_SET_NAMES:
54395519
ret = handler_again___status_CHANGING_CHARSET(rc);
54405520
break;

lib/MySQL_Thread.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ static char * mysql_thread_variables_names[]= {
511511
(char *)"proxy_protocol_networks",
512512
(char *)"protocol_compression_level",
513513
(char *)"ignore_min_gtid_annotations",
514+
(char *)"session_track_variables",
514515
NULL
515516
};
516517

@@ -1151,6 +1152,8 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() {
11511152
variables.data_packets_history_size=0;
11521153
variables.protocol_compression_level=3;
11531154
variables.ignore_min_gtid_annotations=false;
1155+
variables.session_track_variables=session_track_variables::ENABLED;
1156+
11541157
// status variables
11551158
status_variables.mirror_sessions_current=0;
11561159
__global_MySQL_Thread_Variables_version=1;
@@ -2330,7 +2333,7 @@ char ** MySQL_Threads_Handler::get_variables_list() {
23302333
VariablesPointers_int["eventslog_format"] = make_tuple(&variables.eventslog_format, 0, 0, true);
23312334
VariablesPointers_int["wait_timeout"] = make_tuple(&variables.wait_timeout, 0, 0, true);
23322335
VariablesPointers_int["data_packets_history_size"] = make_tuple(&variables.data_packets_history_size, 0, 0, true);
2333-
2336+
VariablesPointers_int["session_track_variables"] = make_tuple(&variables.session_track_variables, 0, 1, false);
23342337
}
23352338

23362339

@@ -4277,6 +4280,7 @@ void MySQL_Thread::refresh_variables() {
42774280
REFRESH_VARIABLE_INT(handle_warnings);
42784281
REFRESH_VARIABLE_INT(evaluate_replication_lag_on_servers_load);
42794282
REFRESH_VARIABLE_BOOL(ignore_min_gtid_annotations);
4283+
REFRESH_VARIABLE_INT(session_track_variables);
42804284
#ifdef DEBUG
42814285
REFRESH_VARIABLE_BOOL(session_debug);
42824286
#endif /* DEBUG */

lib/mysql_connection.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ MySQL_Connection::MySQL_Connection() {
452452
options.init_connect_sent=false;
453453
options.session_track_gtids = NULL;
454454
options.session_track_gtids_sent = false;
455+
options.session_track_variables_sent = false;
456+
options.session_track_state_sent = false;
455457
options.ldap_user_variable=NULL;
456458
options.ldap_user_variable_value=NULL;
457459
options.ldap_user_variable_sent=false;
@@ -3082,6 +3084,8 @@ void MySQL_Connection::reset() {
30823084
options.session_track_gtids = NULL;
30833085
options.session_track_gtids_sent = false;
30843086
}
3087+
options.session_track_variables_sent = false;
3088+
options.session_track_state_sent = false;
30853089
}
30863090

30873091
bool MySQL_Connection::get_gtid(char *buff, uint64_t *trx_id) {
@@ -3116,6 +3120,48 @@ bool MySQL_Connection::get_gtid(char *buff, uint64_t *trx_id) {
31163120
return ret;
31173121
}
31183122

3123+
bool MySQL_Connection::get_variables(std::unordered_map<string, string>& variables) {
3124+
bool ret = false;
3125+
3126+
if ((mysql != nullptr)
3127+
&& (mysql->net.last_errno == 0)
3128+
&& (mysql->server_status & SERVER_SESSION_STATE_CHANGED)) {
3129+
// when there is no error and status changed
3130+
const char *data;
3131+
size_t length;
3132+
3133+
if (mysql_session_track_get_first(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &length) == 0) {
3134+
string var_name(data, length);
3135+
string val;
3136+
3137+
// get_first() returns a variable_name
3138+
// get_next() will return the value
3139+
bool expect_value = true;
3140+
3141+
while (mysql_session_track_get_next(mysql, SESSION_TRACK_SYSTEM_VARIABLES, &data, &length) == 0) {
3142+
if (expect_value) {
3143+
val = string(data, length);
3144+
variables[var_name] = val;
3145+
// got a value in this iteration
3146+
// in the next iteration, we have to expect a variable_name
3147+
expect_value = false;
3148+
} else {
3149+
var_name = string(data, length);
3150+
// got a variable_name in this iteration
3151+
// in the next iteration, we have to expect the value of this variable
3152+
expect_value = true;
3153+
}
3154+
}
3155+
3156+
// update counters
3157+
// __sync_fetch_and_add(&myds->sess->thread->status_variables.stvar[st_var_gtid_session_collected],1);
3158+
ret = true;
3159+
}
3160+
}
3161+
3162+
return ret;
3163+
}
3164+
31193165
void MySQL_Connection::set_ssl_params(MYSQL *mysql, MySQLServers_SslParams *ssl_params) {
31203166
if (ssl_params == NULL) {
31213167
mysql_ssl_set(mysql,

test/tap/groups/groups.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,5 +229,6 @@
229229
"test_ssl_fast_forward-2_libmysql-t": [ "default-g4", "mysql-auto_increment_delay_multiplex=0-g4", "mysql-multiplexing=false-g4", "mysql-query_digests=0-g4", "mysql-query_digests_keep_comment=1-g4" ],
230230
"test_ssl_fast_forward-3_libmariadb-t": [ "default-g4", "mysql-auto_increment_delay_multiplex=0-g4", "mysql-multiplexing=false-g4", "mysql-query_digests=0-g4", "mysql-query_digests_keep_comment=1-g4" ],
231231
"test_ssl_fast_forward-3_libmysql-t": [ "default-g4", "mysql-auto_increment_delay_multiplex=0-g4", "mysql-multiplexing=false-g4", "mysql-query_digests=0-g4", "mysql-query_digests_keep_comment=1-g4" ],
232-
"test_ignore_min_gtid-t": [ "default-g4", "mysql-auto_increment_delay_multiplex=0-g4", "mysql-multiplexing=false-g4", "mysql-query_digests=0-g4", "mysql-query_digests_keep_comment=1-g4" ]
232+
"test_ignore_min_gtid-t": [ "default-g4", "mysql-auto_increment_delay_multiplex=0-g4", "mysql-multiplexing=false-g4", "mysql-query_digests=0-g4", "mysql-query_digests_keep_comment=1-g4" ],
233+
"mysql-track_system_variables-t" : [ "default-g4","mysql-auto_increment_delay_multiplex=0-g4","mysql-multiplexing=false-g4","mysql-query_digests=0-g4","mysql-query_digests_keep_comment=1-g4" ]
233234
}

0 commit comments

Comments
 (0)