Skip to content

Commit 934709e

Browse files
committed
MySQL: Trace session-specific system variables changes
- Configure `session_track_system_variables` and `session_track_state_change` in all backend connections. - 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. Signed-off-by: Wazir Ahmed <[email protected]>
1 parent a71c863 commit 934709e

File tree

5 files changed

+104
-0
lines changed

5 files changed

+104
-0
lines changed

include/MySQL_Session.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,15 @@ class MySQL_Session: public Base_Session<MySQL_Session, MySQL_Data_Stream, MySQL
224224
bool handler_again___verify_ldap_user_variable();
225225
bool handler_again___verify_backend_autocommit();
226226
bool handler_again___verify_backend_session_track_gtids();
227+
bool handler_again___verify_backend_session_track_variables();
227228
bool handler_again___verify_backend_multi_statement();
228229
bool handler_again___verify_backend_user_schema();
229230
bool handler_again___verify_multiple_variables(MySQL_Connection *);
230231
bool handler_again___status_SETTING_INIT_CONNECT(int *);
231232
bool handler_again___status_SETTING_LDAP_USER_VARIABLE(int *);
232233
bool handler_again___status_SETTING_SQL_MODE(int *);
233234
bool handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *);
235+
bool handler_again___status_SETTING_SESSION_TRACK_VARIABLES(int *);
234236
bool handler_again___status_CHANGING_CHARSET(int *_rc);
235237
bool handler_again___status_CHANGING_SCHEMA(int *);
236238
bool handler_again___status_CONNECTING_SERVER(int *);
@@ -279,6 +281,7 @@ class MySQL_Session: public Base_Session<MySQL_Session, MySQL_Data_Stream, MySQL
279281
int RunQuery(MySQL_Data_Stream *myds, MySQL_Connection *myconn);
280282
void handler___status_WAITING_CLIENT_DATA();
281283
void handler_rc0_Process_GTID(MySQL_Connection *myconn);
284+
void handler_rc0_Process_Variables(MySQL_Connection *myconn);
282285
void handler_rc0_RefreshActiveTransactions(MySQL_Connection* myconn);
283286
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_INIT_DB_replace_CLICKHOUSE(PtrSize_t& pkt);
284287
void handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_COM_QUERY___not_mysql(PtrSize_t& pkt);

include/mysql_connection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ 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;
9293
bool ldap_user_variable_sent;
9394
uint8_t protocol_version;
9495
int8_t last_set_autocommit;
@@ -262,6 +263,7 @@ class MySQL_Connection {
262263
void reset();
263264

264265
bool get_gtid(char *buff, uint64_t *trx_id);
266+
bool get_variables(std::unordered_map<std::string, std::string>&);
265267
void reduce_auto_increment_delay_token() { if (auto_increment_delay_token) auto_increment_delay_token--; };
266268

267269
bool match_ff_req_options(const MySQL_Connection *c);

include/proxysql_structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ enum session_status {
310310
SETTING_NEXT_TRANSACTION_READ,
311311
PROCESSING_EXTENDED_QUERY_SYNC,
312312
RESYNCHRONIZING_CONNECTION,
313+
SETTING_SESSION_TRACK_VARIABLES,
313314
session_status___NONE // special marker
314315
};
315316

lib/MySQL_Session.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1923,6 +1923,16 @@ bool MySQL_Session::handler_again___verify_backend_session_track_gtids() {
19231923
return ret;
19241924
}
19251925

1926+
bool MySQL_Session::handler_again___verify_backend_session_track_variables() {
1927+
if (mybe->server_myds->myconn->options.session_track_variables_sent == false) {
1928+
mybe->server_myds->myconn->options.session_track_variables_sent = true;
1929+
set_previous_status_mode3();
1930+
NEXT_IMMEDIATE_NEW(SETTING_SESSION_TRACK_VARIABLES);
1931+
}
1932+
1933+
return false;
1934+
}
1935+
19261936

19271937
bool MySQL_Session::handler_again___verify_multiple_variables(MySQL_Connection* myconn) {
19281938
for (auto i = 0; i < SQL_NAME_LAST_LOW_WM; i++) {
@@ -2535,6 +2545,12 @@ bool MySQL_Session::handler_again___status_SETTING_GENERIC_VARIABLE(int *_rc, co
25352545
free(query);
25362546
query=NULL;
25372547
}
2548+
2549+
if (rc == 0 && strncasecmp(var_name, "session_track_system_variables", strlen("session_track_system_variables")) == 0) {
2550+
char *q = (char *)"SET session_track_state_change=ON";
2551+
rc = myconn->async_send_simple_command(myds->revents, q, strlen(q));
2552+
}
2553+
25382554
if (rc==0) {
25392555
myds->revents|=POLLOUT; // we also set again POLLOUT to send a query immediately!
25402556
myds->DSS = STATE_MARIADB_GENERIC;
@@ -2723,6 +2739,13 @@ bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_GTIDS(int *_rc)
27232739
return ret;
27242740
}
27252741

2742+
bool MySQL_Session::handler_again___status_SETTING_SESSION_TRACK_VARIABLES(int *_rc) {
2743+
bool ret=false;
2744+
assert(mybe->server_myds->myconn);
2745+
ret = handler_again___status_SETTING_GENERIC_VARIABLE(_rc, (char *)"session_track_system_variables", "*", false);
2746+
return ret;
2747+
}
2748+
27262749
bool MySQL_Session::handler_again___status_CHANGING_SCHEMA(int *_rc) {
27272750
bool ret=false;
27282751
//fprintf(stderr,"CHANGING_SCHEMA\n");
@@ -4829,6 +4852,28 @@ void MySQL_Session::handler_rc0_Process_GTID(MySQL_Connection *myconn) {
48294852
}
48304853
}
48314854

4855+
void MySQL_Session::handler_rc0_Process_Variables(MySQL_Connection *myconn) {
4856+
std::unordered_map<string, string> var_map;
4857+
4858+
if(myconn->get_variables(var_map)) {
4859+
const char *variable = nullptr;
4860+
const char *value = nullptr;
4861+
4862+
for (int idx = 0 ; idx < SQL_NAME_LAST_HIGH_WM ; idx++) {
4863+
variable = mysql_tracked_variables[idx].set_variable_name;
4864+
4865+
auto itr = var_map.find(variable);
4866+
if(itr != var_map.end()) {
4867+
value = itr->second.c_str();
4868+
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, value);
4869+
4870+
mysql_variables.client_set_value(this, idx, value);
4871+
mysql_variables.server_set_value(this, idx, value);
4872+
}
4873+
}
4874+
}
4875+
}
4876+
48324877
void MySQL_Session::handler_KillConnectionIfNeeded() {
48334878
if ( // two conditions
48344879
// 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
@@ -5026,6 +5071,10 @@ int MySQL_Session::handler() {
50265071
goto handler_again;
50275072
}
50285073

5074+
if (handler_again___verify_backend_session_track_variables()) {
5075+
goto handler_again;
5076+
}
5077+
50295078
// Optimize network traffic when we can use 'SET NAMES'
50305079
if (verify_set_names(this)) {
50315080
goto handler_again;
@@ -5106,6 +5155,8 @@ int MySQL_Session::handler() {
51065155

51075156
handler_rc0_Process_GTID(myconn);
51085157

5158+
handler_rc0_Process_Variables(myconn);
5159+
51095160
// if we are locked on hostgroup, the value of autocommit is copied from the backend connection
51105161
// see bug #3549
51115162
if (locked_on_hostgroup >= 0) {
@@ -5402,6 +5453,9 @@ bool MySQL_Session::handler_again___multiple_statuses(int *rc) {
54025453
case SETTING_SESSION_TRACK_GTIDS:
54035454
ret = handler_again___status_SETTING_SESSION_TRACK_GTIDS(rc);
54045455
break;
5456+
case SETTING_SESSION_TRACK_VARIABLES:
5457+
ret = handler_again___status_SETTING_SESSION_TRACK_VARIABLES(rc);
5458+
break;
54055459
case SETTING_SET_NAMES:
54065460
ret = handler_again___status_CHANGING_CHARSET(rc);
54075461
break;

lib/mysql_connection.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ 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;
455456
options.ldap_user_variable=NULL;
456457
options.ldap_user_variable_value=NULL;
457458
options.ldap_user_variable_sent=false;
@@ -3082,6 +3083,7 @@ void MySQL_Connection::reset() {
30823083
options.session_track_gtids = NULL;
30833084
options.session_track_gtids_sent = false;
30843085
}
3086+
options.session_track_variables_sent = false;
30853087
}
30863088

30873089
bool MySQL_Connection::get_gtid(char *buff, uint64_t *trx_id) {
@@ -3116,6 +3118,48 @@ bool MySQL_Connection::get_gtid(char *buff, uint64_t *trx_id) {
31163118
return ret;
31173119
}
31183120

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

0 commit comments

Comments
 (0)