Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tracking for session_track_state_change and session_track_system_… #4159

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/MySQL_Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ class MySQL_Threads_Handler
bool enable_server_deprecate_eof;
bool enable_load_data_local_infile;
bool log_mysql_warnings_enabled;
bool enable_session_state_trackers;
} variables;
struct {
unsigned int mirror_sessions_current;
Expand Down
1 change: 1 addition & 0 deletions include/MySQL_Variables.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class MySQL_Variables {
bool update_variable(MySQL_Session* session, session_status status, int &_rc);
bool parse_variable_boolean(MySQL_Session *sess, int idx, std::string &value1, bool* lock_hostgroup);
bool parse_variable_number(MySQL_Session *sess, int idx, std::string &value1, bool* lock_hostgroup);
void enable_session_state_trackers(MySQL_Session *sess);
};

#endif // #ifndef MYSQL_VARIABLES_H
Expand Down
6 changes: 6 additions & 0 deletions include/proxysql_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ enum mysql_variable_name {
SQL_OPTIMIZER_USE_CONDITION_SELECTIVITY,
SQL_PROFILING,
SQL_QUERY_CACHE_TYPE,
SQL_SESSION_TRACK_STATE_CHANGE,
SQL_SESSION_TRACK_SYSTEM_VARIABLES,
SQL_SORT_BUFFER_SIZE,
SQL_SQL_AUTO_IS_NULL,
SQL_SQL_BIG_SELECTS,
Expand Down Expand Up @@ -855,6 +857,7 @@ __thread bool mysql_thread___log_mysql_warnings_enabled;
__thread bool mysql_thread___enable_load_data_local_infile;
__thread int mysql_thread___client_host_cache_size;
__thread int mysql_thread___client_host_error_counts;
__thread bool mysql_thread___enable_session_state_trackers;

/* variables used for Query Cache */
__thread int mysql_thread___query_cache_size_MB;
Expand Down Expand Up @@ -1021,6 +1024,7 @@ extern __thread bool mysql_thread___log_mysql_warnings_enabled;
extern __thread bool mysql_thread___enable_load_data_local_infile;
extern __thread int mysql_thread___client_host_cache_size;
extern __thread int mysql_thread___client_host_error_counts;
extern __thread bool mysql_thread___enable_session_state_trackers;

/* variables used for Query Cache */
extern __thread int mysql_thread___query_cache_size_MB;
Expand Down Expand Up @@ -1163,6 +1167,8 @@ mysql_variable_st mysql_tracked_variables[] {
{ SQL_OPTIMIZER_USE_CONDITION_SELECTIVITY, SETTING_VARIABLE, false, false, true, false, (char*)"optimizer_use_condition_selectivity", NULL, (char*)"" , false} ,
{ SQL_PROFILING, SETTING_VARIABLE, true, false, false, true, ( char *)"profiling", NULL, (char *)"" , false} ,
{ SQL_QUERY_CACHE_TYPE, SETTING_VARIABLE, false, false, true, true, ( char *)"query_cache_type", NULL, (char *)"" , false} , // note that this variable can act both as boolean AND a number. See https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_query_cache_type
{ SQL_SESSION_TRACK_STATE_CHANGE, SETTING_VARIABLE, false, false, false, false, (char *)"session_track_state_change", NULL, (char *)"ON" , false} ,
{ SQL_SESSION_TRACK_SYSTEM_VARIABLES, SETTING_VARIABLE, true, false, false, false, (char *)"session_track_system_variables", NULL, (char *)"*" , false} ,
{ SQL_SORT_BUFFER_SIZE, SETTING_VARIABLE, false, false, true, false, (char *)"sort_buffer_size", NULL, (char *)"18446744073709551615" , false} ,
{ SQL_SQL_AUTO_IS_NULL, SETTING_VARIABLE, true, false, false, true, (char *)"sql_auto_is_null", NULL, (char *)"OFF" , false} ,
{ SQL_SQL_BIG_SELECTS, SETTING_VARIABLE, true, false, false, true, (char *)"sql_big_selects", NULL, (char *)"OFF" , true} ,
Expand Down
2 changes: 2 additions & 0 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6822,6 +6822,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (session_type == PROXYSQL_SESSION_MYSQL || session_type == PROXYSQL_SESSION_SQLITE) {
reset();
init();
mysql_variables.enable_session_state_trackers(this);
if (client_authenticated) {
if (use_ldap_auth == false) {
GloMyAuth->decrease_frontend_user_connections(client_myds->myconn->userinfo->username);
Expand Down Expand Up @@ -6908,6 +6909,7 @@ void MySQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
this->default_hostgroup = default_hostgroup;
this->transaction_persistent = transaction_persistent;
client_myds->myconn->set_charset(default_charset, NAMES);
mysql_variables.enable_session_state_trackers(this);

if (user_attributes != NULL && strlen(user_attributes)) {
nlohmann::json j_user_attributes = nlohmann::json::parse(user_attributes);
Expand Down
7 changes: 7 additions & 0 deletions lib/MySQL_Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ static char * mysql_thread_variables_names[]= {
(char *)"stats_time_backend_query",
(char *)"stats_time_query_processor",
(char *)"query_cache_stores_empty_result",
(char *)"enable_session_state_trackers",
NULL
};

Expand Down Expand Up @@ -1215,6 +1216,7 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() {
variables.enable_server_deprecate_eof=true;
variables.enable_load_data_local_infile=false;
variables.log_mysql_warnings_enabled=false;
variables.enable_session_state_trackers=true;
// status variables
status_variables.mirror_sessions_current=0;
__global_MySQL_Thread_Variables_version=1;
Expand Down Expand Up @@ -2135,6 +2137,7 @@ char ** MySQL_Threads_Handler::get_variables_list() {
VariablesPointers_bool["stats_time_query_processor"] = make_tuple(&variables.stats_time_query_processor, false);
VariablesPointers_bool["use_tcp_keepalive"] = make_tuple(&variables.use_tcp_keepalive, false);
VariablesPointers_bool["verbose_query_error"] = make_tuple(&variables.verbose_query_error, false);
VariablesPointers_bool["enable_session_state_trackers"] = make_tuple(&variables.enable_session_state_trackers, false);
#ifdef IDLE_THREADS
VariablesPointers_bool["session_idle_show_processlist"] = make_tuple(&variables.session_idle_show_processlist, false);
#endif // IDLE_THREADS
Expand Down Expand Up @@ -2897,6 +2900,8 @@ MySQL_Session * MySQL_Thread::create_new_session_and_client_data_stream(int _fd)
}
sess->client_myds->myconn->options.session_track_gtids=strdup(mysql_thread___default_session_track_gtids);

mysql_variables.enable_session_state_trackers(sess);

return sess;
}

Expand Down Expand Up @@ -4148,6 +4153,8 @@ void MySQL_Thread::refresh_variables() {
mysql_thread___log_mysql_warnings_enabled=(bool)GloMTH->get_variable_int((char *)"log_mysql_warnings_enabled");
mysql_thread___client_host_cache_size=GloMTH->get_variable_int((char *)"client_host_cache_size");
mysql_thread___client_host_error_counts=GloMTH->get_variable_int((char *)"client_host_error_counts");
mysql_thread___enable_session_state_trackers=(bool)GloMTH->get_variable_int((char *)"enable_session_state_trackers");

#ifdef DEBUG
mysql_thread___session_debug=(bool)GloMTH->get_variable_int((char *)"session_debug");
#endif /* DEBUG */
Expand Down
15 changes: 15 additions & 0 deletions lib/MySQL_Variables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ MySQL_Variables::MySQL_Variables() {
ignore_vars.push_back("net_buffer_length");
ignore_vars.push_back("read_buffer_size");
ignore_vars.push_back("read_rnd_buffer_size");
ignore_vars.push_back("session_track_state_change");
ignore_vars.push_back("session_track_system_variables");
// NOTE: This variable has been temporarily ignored. Check issues #3442 and #3441.
ignore_vars.push_back("session_track_schema");
variables_regexp = "";
Expand Down Expand Up @@ -616,3 +618,16 @@ bool MySQL_Variables::parse_variable_number(MySQL_Session *sess, int idx, string
return true;
}

void MySQL_Variables::enable_session_state_trackers(MySQL_Session *sess) {
if (mysql_thread___enable_session_state_trackers) {
mysql_variables.client_set_value(
sess, SQL_SESSION_TRACK_STATE_CHANGE,
mysql_tracked_variables[SQL_SESSION_TRACK_STATE_CHANGE].default_value
);
mysql_variables.client_set_value(
sess, SQL_SESSION_TRACK_SYSTEM_VARIABLES,
mysql_tracked_variables[SQL_SESSION_TRACK_SYSTEM_VARIABLES].default_value
);
}
}

167 changes: 167 additions & 0 deletions test/tap/tests/test_enable_session_state_trackers-t.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**
* @file test_enable_session_state_trackers-t.cpp
* @brief This test verifies that 'enable_session_state_trackers' behaves
* properly.
*
* @details It verifies that SESSION_TRACK_STATE_CHANGE and
* SESSION_TRACK_SYSTEM_VARIABLES are configured after connecting, changing user
* and resetting connection when enable_session_state_trackers is enabled and
* the other way around when diabled.
*/

#include "mysql.h"

#include "proxysql_utils.h"
#include "tap.h"
#include "utils.h"

#include <cstdlib>
#include <string>
#include <unistd.h>
#include <iostream>

using std::string;

#include "json.hpp"

using nlohmann::json;

using namespace std;

void parse_result_json_column(MYSQL_RES *result, json& j) {
if(!result) return;
MYSQL_ROW row;

while ((row = mysql_fetch_row(result))) {
j = json::parse(row[0]);
}
}

int check_session_track_variables(MYSQL* proxy, const bool enabled) {
json json_res = {};
MYSQL_RES* myres;

// Values when enable_session_state_trackers is true
std::string session_track_state_change_enabled = "\"ON\"";
std::string session_track_system_variables_enabled = "\"*\"";

MYSQL_QUERY_T(proxy, "PROXYSQL INTERNAL SESSION");
myres = mysql_store_result(proxy);
parse_result_json_column(myres, json_res);
mysql_free_result(myres);

if (enabled) {
std::string session_track_state_change = json_res["conn"]["session_track_state_change"].dump();
std::string session_track_system_variables = json_res["conn"]["session_track_system_variables"].dump();

ok(
session_track_state_change == session_track_state_change_enabled,
"session_track_state_change expected value: %s. Actual value: %s",
session_track_state_change_enabled.c_str(), session_track_state_change.c_str()
);

ok(
session_track_system_variables == session_track_system_variables_enabled,
"session_track_system_variables expected value: %s. Actual value: %s",
session_track_system_variables_enabled.c_str(), session_track_system_variables.c_str()
);
} else {
ok(
!json_res["conn"].contains("session_track_state_change"),
"session_track_state_change should be unsetted"
);

ok(
!json_res["conn"].contains("session_track_system_variables"),
"session_track_system_variables should be unsetted"
);
}

return EXIT_SUCCESS;
}

int test_enable_session_state_trackers(const CommandLine &cl, const bool enabled) {
int err_code = 0;

MYSQL* proxy = mysql_init(NULL);
if (!mysql_real_connect(proxy, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy));
return EXIT_FAILURE;
}

// By default, enable_session_state_trackers is true
err_code = check_session_track_variables(proxy, enabled);
if (err_code != EXIT_SUCCESS) return EXIT_FAILURE;

// Do reset and get the new values
err_code = mysql_reset_connection(proxy);
if (err_code != EXIT_SUCCESS) {
diag(
"'mysql_reset_connection' failed with error: (%d,'%s') at ('%s':'%d')",
mysql_errno(proxy), mysql_error(proxy), __FILE__, __LINE__
);
return EXIT_FAILURE;
}
if (check_session_track_variables(proxy, enabled)) return EXIT_FAILURE;

// Change user and get the new values
std::string username = "sbtest1";
std::string password = "sbtest1";
err_code = mysql_change_user(proxy, username.c_str(), password.c_str(), NULL);
if (err_code != EXIT_SUCCESS) {
diag(
"'mysql_change_user' executed with error: (%d,'%s') at ('%s':'%d')",
mysql_errno(proxy), mysql_error(proxy), __FILE__, __LINE__
);
return EXIT_FAILURE;
}
if (check_session_track_variables(proxy, enabled)) return EXIT_FAILURE;

mysql_close(proxy);

return EXIT_SUCCESS;
}

int main(int, char**) {
int err_code = 0;
CommandLine cl;

if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return EXIT_FAILURE;
}

// 12 tests: check session_track_state_change and
// session_track_system_variables on connect, change user and reset with
// and without enable_session_state_trackers.
plan(12);

err_code = test_enable_session_state_trackers(cl, true);
if (err_code != EXIT_SUCCESS) {
diag("'test_enable_session_state_trackers(true)' failed at ('%s':'%d')", __FILE__, __LINE__);
return EXIT_FAILURE;
}

diag("Configure ProxySQL to disable enable_session_state_trackers");
MYSQL* admin = mysql_init(NULL);
if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
return EXIT_FAILURE;

}
MYSQL_QUERY_T(
admin,
"UPDATE global_variables SET variable_value = false "
"WHERE variable_name = 'mysql-enable_session_state_trackers'"
);
MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME");
mysql_close(admin);

err_code = test_enable_session_state_trackers(cl, false);
if (err_code != EXIT_SUCCESS) {
diag("'test_enable_session_state_trackers(false)' failed at ('%s':'%d')", __FILE__, __LINE__);
return EXIT_FAILURE;
}

return exit_status();
}