From 03bf53aec8d05eddf947d03d14c08376a17657c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 6 May 2020 01:37:48 +0200 Subject: [PATCH] Preparing the cluster module to sync variables Added admin variables: * cluster_mysql_variables_save_to_disk * cluster_admin_variables_save_to_disk * cluster_mysql_variables_diffs_before_sync * cluster_admin_variables_diffs_before_sync When flush_admin_variables___database_to_runtime() is executed, flush_admin_variables___runtime_to_database() is also called to update admin variable checksum. When flush_mysql_variables___database_to_runtime() is executed, flush_mysql_variables___runtime_to_database() is also called to update mysql variable checksum. flush_mysql_variables___runtime_to_database() was also modified to avoid locking twice. --- include/ProxySQL_Cluster.hpp | 4 + include/proxysql_admin.h | 8 +- lib/ProxySQL_Admin.cpp | 166 +++++++++++++++++++++++++++++++++-- 3 files changed, 172 insertions(+), 6 deletions(-) diff --git a/include/ProxySQL_Cluster.hpp b/include/ProxySQL_Cluster.hpp index de1bf8517..fc74d82e2 100644 --- a/include/ProxySQL_Cluster.hpp +++ b/include/ProxySQL_Cluster.hpp @@ -133,10 +133,14 @@ class ProxySQL_Cluster { int cluster_mysql_servers_diffs_before_sync; int cluster_mysql_users_diffs_before_sync; int cluster_proxysql_servers_diffs_before_sync; + int cluster_mysql_variables_diffs_before_sync; + int cluster_admin_variables_diffs_before_sync; bool cluster_mysql_query_rules_save_to_disk; bool cluster_mysql_servers_save_to_disk; bool cluster_mysql_users_save_to_disk; bool cluster_proxysql_servers_save_to_disk; + bool cluster_mysql_variables_save_to_disk; + bool cluster_admin_variables_save_to_disk; ProxySQL_Cluster(); ~ProxySQL_Cluster(); void init() {}; diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index f6479ff99..01b5a6198 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -146,10 +146,14 @@ class ProxySQL_Admin { int cluster_mysql_servers_diffs_before_sync; int cluster_mysql_users_diffs_before_sync; int cluster_proxysql_servers_diffs_before_sync; + int cluster_mysql_variables_diffs_before_sync; + int cluster_admin_variables_diffs_before_sync; bool cluster_mysql_query_rules_save_to_disk; bool cluster_mysql_servers_save_to_disk; bool cluster_mysql_users_save_to_disk; bool cluster_proxysql_servers_save_to_disk; + bool cluster_mysql_variables_save_to_disk; + bool cluster_admin_variables_save_to_disk; int stats_mysql_connection_pool; int stats_mysql_connections; int stats_mysql_query_cache; @@ -202,7 +206,7 @@ class ProxySQL_Admin { void __refresh_users(); void __add_active_users_ldap(); - void flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool replace, bool del, bool onlyifempty, bool runtime=false); + void flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool replace, bool del, bool onlyifempty, bool runtime=false, bool use_lock=true); void flush_mysql_variables___database_to_runtime(SQLite3DB *db, bool replace); char **get_variables_list(); @@ -248,6 +252,8 @@ class ProxySQL_Admin { bool checksum_mysql_query_rules; bool checksum_mysql_servers; bool checksum_mysql_users; + bool checksum_mysql_variables; + bool checksum_admin_variables; } checksum_variables; void public_add_active_users(enum cred_username_type usertype, char *user=NULL) { __add_active_users(usertype, user); diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index d4776dd6a..ad8f668f1 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -524,13 +524,19 @@ static char * admin_variables_names[]= { (char *)"cluster_mysql_servers_diffs_before_sync", (char *)"cluster_mysql_users_diffs_before_sync", (char *)"cluster_proxysql_servers_diffs_before_sync", + (char *)"cluster_mysql_variables_diffs_before_sync", + (char *)"cluster_admin_variables_diffs_before_sync", (char *)"cluster_mysql_query_rules_save_to_disk", (char *)"cluster_mysql_servers_save_to_disk", (char *)"cluster_mysql_users_save_to_disk", (char *)"cluster_proxysql_servers_save_to_disk", + (char *)"cluster_mysql_variables_save_to_disk", + (char *)"cluster_admin_variables_save_to_disk", (char *)"checksum_mysql_query_rules", (char *)"checksum_mysql_servers", (char *)"checksum_mysql_users", + (char *)"checksum_mysql_variables", + (char *)"checksum_admin_variables", (char *)"restapi_enabled", (char *)"restapi_port", (char *)"web_enabled", @@ -4999,13 +5005,19 @@ ProxySQL_Admin::ProxySQL_Admin() : variables.cluster_mysql_servers_diffs_before_sync = 3; variables.cluster_mysql_users_diffs_before_sync = 3; variables.cluster_proxysql_servers_diffs_before_sync = 3; + variables.cluster_mysql_variables_diffs_before_sync = 3; + variables.cluster_admin_variables_diffs_before_sync = 3; checksum_variables.checksum_mysql_query_rules = true; checksum_variables.checksum_mysql_servers = true; checksum_variables.checksum_mysql_users = true; + checksum_variables.checksum_mysql_variables = true; + checksum_variables.checksum_admin_variables = true; variables.cluster_mysql_query_rules_save_to_disk = true; variables.cluster_mysql_servers_save_to_disk = true; variables.cluster_mysql_users_save_to_disk = true; variables.cluster_proxysql_servers_save_to_disk = true; + variables.cluster_mysql_variables_save_to_disk = true; + variables.cluster_admin_variables_save_to_disk = true; variables.stats_mysql_connection_pool = 60; variables.stats_mysql_connections = 60; variables.stats_mysql_query_cache = 60; @@ -5599,6 +5611,31 @@ void ProxySQL_Admin::flush_admin_variables___database_to_runtime(SQLite3DB *db, } } //commit(); NOT IMPLEMENTED + if (checksum_variables.checksum_admin_variables) { + pthread_mutex_lock(&GloVars.checksum_mutex); + // generate checksum for cluster + flush_admin_variables___runtime_to_database(admindb, false, false, false, true); + char *error=NULL; + int cols=0; + int affected_rows=0; + SQLite3_result *resultset=NULL; + char *q=(char *)"SELECT variable_name, variable_value FROM runtime_global_variables WHERE variable_name LIKE 'admin-\%' ORDER BY variable_name"; + admindb->execute_statement(q, &error , &cols , &affected_rows , &resultset); + uint64_t hash1 = resultset->raw_checksum(); + uint32_t d32[2]; + char buf[20]; + memcpy(&d32, &hash1, sizeof(hash1)); + sprintf(buf,"0x%0X%0X", d32[0], d32[1]); + GloVars.checksums_values.admin_variables.set_checksum(buf); + GloVars.checksums_values.admin_variables.version++; + time_t t = time(NULL); + GloVars.checksums_values.admin_variables.epoch = t; + GloVars.epoch_version = t; + GloVars.generate_global_checksum(); + GloVars.checksums_values.updates_cnt++; + pthread_mutex_unlock(&GloVars.checksum_mutex); + delete resultset; + } wrunlock(); { std::function(const httpserver::http_request&)> prometheus_callback { @@ -5787,6 +5824,31 @@ void ProxySQL_Admin::flush_mysql_variables___database_to_runtime(SQLite3DB *db, free(collation); GloMTH->commit(); + if (checksum_variables.checksum_mysql_variables) { + pthread_mutex_lock(&GloVars.checksum_mutex); + // generate checksum for cluster + flush_mysql_variables___runtime_to_database(admindb, false, false, false, true, false); + char *error=NULL; + int cols=0; + int affected_rows=0; + SQLite3_result *resultset=NULL; + char *q=(char *)"SELECT variable_name, variable_value FROM runtime_global_variables WHERE variable_name LIKE 'mysql-\%' ORDER BY variable_name"; + admindb->execute_statement(q, &error , &cols , &affected_rows , &resultset); + uint64_t hash1 = resultset->raw_checksum(); + uint32_t d32[2]; + char buf[20]; + memcpy(&d32, &hash1, sizeof(hash1)); + sprintf(buf,"0x%0X%0X", d32[0], d32[1]); + GloVars.checksums_values.mysql_variables.set_checksum(buf); + GloVars.checksums_values.mysql_variables.version++; + time_t t = time(NULL); + GloVars.checksums_values.mysql_variables.epoch = t; + GloVars.epoch_version = t; + GloVars.generate_global_checksum(); + GloVars.checksums_values.updates_cnt++; + pthread_mutex_unlock(&GloVars.checksum_mutex); + delete resultset; + } GloMTH->wrunlock(); } if (resultset) delete resultset; @@ -6276,7 +6338,7 @@ unsigned int ProxySQL_Admin::ProxySQL_Test___GenerateRandom_mysql_query_rules_fa return cnt; } -void ProxySQL_Admin::flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool replace, bool del, bool onlyifempty, bool runtime) { +void ProxySQL_Admin::flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool replace, bool del, bool onlyifempty, bool runtime, bool use_lock) { proxy_debug(PROXY_DEBUG_ADMIN, 4, "Flushing MySQL variables. Replace:%d, Delete:%d, Only_If_Empty:%d\n", replace, del, onlyifempty); if (onlyifempty) { char *error=NULL; @@ -6326,8 +6388,10 @@ void ProxySQL_Admin::flush_mysql_variables___runtime_to_database(SQLite3DB *db, rc=db->prepare_v2(b, &statement2); ASSERT_SQLITE_OK(rc, db); } - GloMTH->wrlock(); - db->execute("BEGIN"); + if (use_lock) { + GloMTH->wrlock(); + db->execute("BEGIN"); + } char **varnames=GloMTH->get_variables_list(); for (int i=0; varnames[i]; i++) { char *val=GloMTH->get_variable(varnames[i]); @@ -6349,8 +6413,10 @@ void ProxySQL_Admin::flush_mysql_variables___runtime_to_database(SQLite3DB *db, free(val); free(qualified_name); } - db->execute("COMMIT"); - GloMTH->wrunlock(); + if (use_lock) { + db->execute("COMMIT"); + GloMTH->wrunlock(); + } sqlite3_finalize(statement1); if (runtime) sqlite3_finalize(statement2); @@ -6563,6 +6629,14 @@ char * ProxySQL_Admin::get_variable(char *name) { sprintf(intbuf,"%d",variables.cluster_proxysql_servers_diffs_before_sync); return strdup(intbuf); } + if (!strcasecmp(name,"cluster_mysql_variables_diffs_before_sync")) { + sprintf(intbuf,"%d",variables.cluster_mysql_variables_diffs_before_sync); + return strdup(intbuf); + } + if (!strcasecmp(name,"cluster_admin_variables_diffs_before_sync")) { + sprintf(intbuf,"%d",variables.cluster_admin_variables_diffs_before_sync); + return strdup(intbuf); + } if (!strcasecmp(name,"cluster_mysql_query_rules_save_to_disk")) { return strdup((variables.cluster_mysql_query_rules_save_to_disk ? "true" : "false")); } @@ -6575,6 +6649,12 @@ char * ProxySQL_Admin::get_variable(char *name) { if (!strcasecmp(name,"cluster_proxysql_servers_save_to_disk")) { return strdup((variables.cluster_proxysql_servers_save_to_disk ? "true" : "false")); } + if (!strcasecmp(name,"cluster_mysql_variables_save_to_disk")) { + return strdup((variables.cluster_mysql_variables_save_to_disk ? "true" : "false")); + } + if (!strcasecmp(name,"cluster_admin_variables_save_to_disk")) { + return strdup((variables.cluster_admin_variables_save_to_disk ? "true" : "false")); + } if (!strcasecmp(name,"refresh_interval")) { sprintf(intbuf,"%d",variables.refresh_interval); return strdup(intbuf); @@ -6597,6 +6677,12 @@ char * ProxySQL_Admin::get_variable(char *name) { if (!strcasecmp(name,"checksum_mysql_users")) { return strdup((checksum_variables.checksum_mysql_users ? "true" : "false")); } + if (!strcasecmp(name,"checksum_mysql_variables")) { + return strdup((checksum_variables.checksum_mysql_variables ? "true" : "false")); + } + if (!strcasecmp(name,"checksum_admin_variables")) { + return strdup((checksum_variables.checksum_admin_variables ? "true" : "false")); + } if (!strcasecmp(name,"restapi_enabled")) { return strdup((variables.restapi_enabled ? "true" : "false")); } @@ -7037,6 +7123,26 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub return false; } } + if (!strcasecmp(name,"cluster_mysql_variables_diffs_before_sync")) { + int intv=atoi(value); + if (intv >= 0 && intv <= 1000) { + variables.cluster_mysql_variables_diffs_before_sync=intv; + __sync_lock_test_and_set(&GloProxyCluster->cluster_mysql_variables_diffs_before_sync, intv); + return true; + } else { + return false; + } + } + if (!strcasecmp(name,"cluster_admin_variables_diffs_before_sync")) { + int intv=atoi(value); + if (intv >= 0 && intv <= 1000) { + variables.cluster_admin_variables_diffs_before_sync=intv; + __sync_lock_test_and_set(&GloProxyCluster->cluster_admin_variables_diffs_before_sync, intv); + return true; + } else { + return false; + } + } if (!strcasecmp(name,"version")) { if (strcasecmp(value,(char *)PROXYSQL_VERSION)==0) { return true; @@ -7166,6 +7272,34 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub } return rt; } + if (!strcasecmp(name,"cluster_mysql_variables_save_to_disk")) { + bool rt = false; + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + variables.cluster_mysql_variables_save_to_disk=true; + rt = __sync_lock_test_and_set(&GloProxyCluster->cluster_mysql_variables_save_to_disk, true); + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + variables.cluster_mysql_variables_save_to_disk=false; + rt = __sync_lock_test_and_set(&GloProxyCluster->cluster_mysql_variables_save_to_disk, false); + return true; + } + return rt; + } + if (!strcasecmp(name,"cluster_admin_variables_save_to_disk")) { + bool rt = false; + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + variables.cluster_admin_variables_save_to_disk=true; + rt = __sync_lock_test_and_set(&GloProxyCluster->cluster_admin_variables_save_to_disk, true); + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + variables.cluster_admin_variables_save_to_disk=false; + rt = __sync_lock_test_and_set(&GloProxyCluster->cluster_admin_variables_save_to_disk, false); + return true; + } + return rt; + } if (!strcasecmp(name,"checksum_mysql_query_rules")) { if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { checksum_variables.checksum_mysql_query_rules=true; @@ -7199,6 +7333,28 @@ bool ProxySQL_Admin::set_variable(char *name, char *value) { // this is the pub } return false; } + if (!strcasecmp(name,"checksum_mysql_variables")) { + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + checksum_variables.checksum_mysql_variables=true; + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + checksum_variables.checksum_mysql_variables=false; + return true; + } + return false; + } + if (!strcasecmp(name,"checksum_admin_variables")) { + if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { + checksum_variables.checksum_admin_variables=true; + return true; + } + if (strcasecmp(value,"false")==0 || strcasecmp(value,"0")==0) { + checksum_variables.checksum_admin_variables=false; + return true; + } + return false; + } if (!strcasecmp(name,"read_only")) { if (strcasecmp(value,"true")==0 || strcasecmp(value,"1")==0) { variables.admin_read_only=true;