diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index 5e3e0ee03..d03cfa967 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -54,6 +54,7 @@ "lag_num_checks INT NOT NULL CHECK (lag_num_checks >= 1 AND lag_num_checks <= 16) DEFAULT 1 , comment VARCHAR ," \ "UNIQUE (reader_hostgroup))" +#define MYHGM_GEN_ADMIN_RUNTIME_SERVERS "SELECT hostgroup_id, hostname, port, gtid_port, CASE status WHEN 0 THEN \"ONLINE\" WHEN 1 THEN \"SHUNNED\" WHEN 2 THEN \"OFFLINE_SOFT\" WHEN 3 THEN \"OFFLINE_HARD\" WHEN 4 THEN \"SHUNNED\" END status, weight, compression, max_connections, max_replication_lag, use_ssl, max_latency_ms, comment FROM mysql_servers ORDER BY hostgroup_id, hostname, port" typedef std::unordered_map umap_mysql_errors; @@ -376,19 +377,35 @@ class MySQL_HostGroups_Manager { Galera_Info *get_galera_node_info(int hostgroup); /** - * @brief These resultset holds the latest values for 'incoming_*' tables used promoted servers to runtime. + * @brief This resultset holds the current values for 'runtime_mysql_servers' computed by either latest + * 'commit' or fetched from another Cluster node. It's also used by ProxySQL_Admin to respond to the + * intercepted query 'CLUSTER_QUERY_MYSQL_SERVERS'. + * @details This resultset can't right now just contain the value for 'incoming_mysql_servers' as with the + * rest of the intercepted resultset. This is due to 'runtime_mysql_servers' reconfigurations that can be + * triggered by monitoring actions like 'Galera' currently performs. These actions not only trigger status + * changes in the servers, but also re-generate the servers table via 'commit', thus generating a new + * checksum in the process. Because of this potential mismatch, the fetching server wouldn't be able to + * compute the proper checksum for the fetched 'runtime_mysql_servers' config. + * + * As previously stated, these reconfigurations are monitoring actions, they can't be packed or performed + * in a single action, since monitoring data is required, which may not be already present. This makes + * this a convergent, but iterative process, that can't be compressed into a single action. Using other + * servers 'runtime_mysql_servers' while fetching represents a best effort for avoiding these + * reconfigurations in servers that already holds the same monitoring conditions. If monitoring + * conditions are not the same, circular fetching is still possible due to the previously described + * scenario. + */ + SQLite3_result* runtime_mysql_servers; + /** + * @brief These resultset holds the latest values for 'incoming_*' tables used to promoted servers to runtime. * @details All these resultsets are used by 'Cluster' to fetch and promote the same configuration used in the * node across the whole cluster. For these, the queries: - * - 'CLUSTER_QUERY_MYSQL_SERVERS' * - 'CLUSTER_QUERY_MYSQL_REPLICATION_HOSTGROUPS' * - 'CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS' * - 'CLUSTER_QUERY_MYSQL_GALERA' * - 'CLUSTER_QUERY_MYSQL_AWS_AURORA' - * Issued by 'Cluster' are intercepted by 'ProxySQL_Admin' and return the content of these resultsets. This is - * possible because 'incoming_*' tables represent the actual applied configuration to the node servers before - * reconfiguration ('commit') is triggered, making this process convergent on the supplied config. + * Issued by 'Cluster' are intercepted by 'ProxySQL_Admin' and return the content of these resultsets. */ - SQLite3_result* incoming_mysql_servers; SQLite3_result *incoming_replication_hostgroups; void generate_mysql_group_replication_hostgroups_table(); @@ -552,18 +569,24 @@ class MySQL_HostGroups_Manager { void wrlock(); void wrunlock(); int servers_add(SQLite3_result *resultset); - bool commit(const std::string& checksum = "", const time_t epoch = 0); + bool commit(SQLite3_result* runtime_mysql_servers = nullptr, const std::string& checksum = "", const time_t epoch = 0); /** - * @brief These setters/getter functions store and retrieve the currently hold resultset for the 'incoming_*' - * table set that have been loaded to runtime. Whose hold the config to be propagated by Cluster. + * @brief Store the resultset for the 'runtime_mysql_servers' table set that have been loaded to runtime. + * The store configuration is later used by Cluster to propagate current config. + * @param The resulset to be stored replacing the current one. + */ + void save_runtime_mysql_servers(SQLite3_result *); + /** + * @brief These setters/getter functions store and retrieve the currently hold resultset for the + * 'incoming_*' table set that have been loaded to runtime. The store configuration is later used by + * Cluster to propagate current config. * @param The resulset to be stored replacing the current one. */ - void set_incoming_mysql_servers(SQLite3_result *); - void set_incoming_replication_hostgroups(SQLite3_result *); - void set_incoming_group_replication_hostgroups(SQLite3_result *); - void set_incoming_galera_hostgroups(SQLite3_result *); - void set_incoming_aws_aurora_hostgroups(SQLite3_result *); + void save_incoming_replication_hostgroups(SQLite3_result *); + void save_incoming_group_replication_hostgroups(SQLite3_result *); + void save_incoming_galera_hostgroups(SQLite3_result *); + void save_incoming_aws_aurora_hostgroups(SQLite3_result *); SQLite3_result* get_current_mysql_servers_inner(); SQLite3_result* get_current_mysql_replication_hostgroups_inner(); diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index 56c4264cc..5ba16f335 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -117,7 +117,7 @@ struct admin_metrics_map_idx { extern int admin__web_verbosity; struct incoming_servers_t { - SQLite3_result* incoming_mysql_servers = NULL; + SQLite3_result* runtime_mysql_servers = NULL; SQLite3_result* incoming_replication_hostgroups = NULL; SQLite3_result* incoming_group_replication_hostgroups = NULL; SQLite3_result* incoming_galera_hostgroups = NULL; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 3e919bd9c..c7a0b24d6 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -1410,7 +1410,7 @@ MySQL_HostGroups_Manager::MySQL_HostGroups_Manager() { mydb->execute(MYHGM_MYSQL_AWS_AURORA_HOSTGROUPS); mydb->execute("CREATE INDEX IF NOT EXISTS idx_mysql_servers_hostname_port ON mysql_servers (hostname,port)"); MyHostGroups=new PtrArray(); - incoming_mysql_servers=NULL; + runtime_mysql_servers=NULL; incoming_replication_hostgroups=NULL; incoming_group_replication_hostgroups=NULL; incoming_galera_hostgroups=NULL; @@ -1645,7 +1645,9 @@ SQLite3_result * MySQL_HostGroups_Manager::execute_query(char *query, char **err return resultset; } -bool MySQL_HostGroups_Manager::commit(const std::string& checksum, const time_t epoch) { +bool MySQL_HostGroups_Manager::commit( + SQLite3_result* runtime_mysql_servers, const std::string& checksum, const time_t epoch +) { unsigned long long curtime1=monotonic_time(); wrlock(); @@ -1947,6 +1949,18 @@ bool MySQL_HostGroups_Manager::commit(const std::string& checksum, const time_t SQLite3_result *resultset=NULL; char *query=(char *)"SELECT hostgroup_id, hostname, port, gtid_port, CASE status WHEN 0 OR 1 OR 4 THEN 0 ELSE status END status, weight, compression, max_connections, max_replication_lag, use_ssl, max_latency_ms, comment FROM mysql_servers WHERE status<>3 ORDER BY hostgroup_id, hostname, port"; mydb->execute_statement(query, &error , &cols , &affected_rows , &resultset); + if (runtime_mysql_servers == nullptr) { + char* error = NULL; + int cols = 0; + int affected_rows = 0; + SQLite3_result* resultset = NULL; + + mydb->execute_statement(MYHGM_GEN_ADMIN_RUNTIME_SERVERS, &error, &cols, &affected_rows, &resultset); + save_runtime_mysql_servers(resultset); + } else { + save_runtime_mysql_servers(runtime_mysql_servers); + } + if (resultset) { if (resultset->rows_count) { if (init == false) { @@ -2594,9 +2608,8 @@ SQLite3_result * MySQL_HostGroups_Manager::dump_table_mysql_servers() { int cols=0; int affected_rows=0; SQLite3_result *resultset=NULL; - char *query=(char *)"SELECT hostgroup_id, hostname, port, gtid_port, CASE status WHEN 0 THEN \"ONLINE\" WHEN 1 THEN \"SHUNNED\" WHEN 2 THEN \"OFFLINE_SOFT\" WHEN 3 THEN \"OFFLINE_HARD\" WHEN 4 THEN \"SHUNNED\" END status, weight, compression, max_connections, max_replication_lag, use_ssl, max_latency_ms, comment FROM mysql_servers ORDER BY hostgroup_id, hostname, port"; - proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "%s\n", query); - mydb->execute_statement(query, &error , &cols , &affected_rows , &resultset); + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "%s\n", MYHGM_GEN_ADMIN_RUNTIME_SERVERS); + mydb->execute_statement(MYHGM_GEN_ADMIN_RUNTIME_SERVERS, &error , &cols , &affected_rows , &resultset); wrunlock(); return resultset; } @@ -3789,15 +3802,15 @@ __exit_get_multiple_idle_connections: return num_conn_current; } -void MySQL_HostGroups_Manager::set_incoming_mysql_servers(SQLite3_result *s) { - if (incoming_mysql_servers) { - delete incoming_mysql_servers; - incoming_mysql_servers = nullptr; +void MySQL_HostGroups_Manager::save_runtime_mysql_servers(SQLite3_result *s) { + if (runtime_mysql_servers) { + delete runtime_mysql_servers; + runtime_mysql_servers = nullptr; } - incoming_mysql_servers=s; + runtime_mysql_servers=s; } -void MySQL_HostGroups_Manager::set_incoming_replication_hostgroups(SQLite3_result *s) { +void MySQL_HostGroups_Manager::save_incoming_replication_hostgroups(SQLite3_result *s) { if (incoming_replication_hostgroups) { delete incoming_replication_hostgroups; incoming_replication_hostgroups = nullptr; @@ -3805,7 +3818,7 @@ void MySQL_HostGroups_Manager::set_incoming_replication_hostgroups(SQLite3_resul incoming_replication_hostgroups=s; } -void MySQL_HostGroups_Manager::set_incoming_group_replication_hostgroups(SQLite3_result *s) { +void MySQL_HostGroups_Manager::save_incoming_group_replication_hostgroups(SQLite3_result *s) { if (incoming_group_replication_hostgroups) { delete incoming_group_replication_hostgroups; incoming_group_replication_hostgroups = NULL; @@ -3813,7 +3826,7 @@ void MySQL_HostGroups_Manager::set_incoming_group_replication_hostgroups(SQLite3 incoming_group_replication_hostgroups=s; } -void MySQL_HostGroups_Manager::set_incoming_galera_hostgroups(SQLite3_result *s) { +void MySQL_HostGroups_Manager::save_incoming_galera_hostgroups(SQLite3_result *s) { if (incoming_galera_hostgroups) { delete incoming_galera_hostgroups; incoming_galera_hostgroups = NULL; @@ -3821,7 +3834,7 @@ void MySQL_HostGroups_Manager::set_incoming_galera_hostgroups(SQLite3_result *s) incoming_galera_hostgroups=s; } -void MySQL_HostGroups_Manager::set_incoming_aws_aurora_hostgroups(SQLite3_result *s) { +void MySQL_HostGroups_Manager::save_incoming_aws_aurora_hostgroups(SQLite3_result *s) { if (incoming_aws_aurora_hostgroups) { delete incoming_aws_aurora_hostgroups; incoming_aws_aurora_hostgroups = NULL; @@ -3830,7 +3843,7 @@ void MySQL_HostGroups_Manager::set_incoming_aws_aurora_hostgroups(SQLite3_result } SQLite3_result* MySQL_HostGroups_Manager::get_current_mysql_servers_inner() { - return this->incoming_mysql_servers; + return this->runtime_mysql_servers; } SQLite3_result* MySQL_HostGroups_Manager::get_current_mysql_replication_hostgroups_inner() { diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index e3cc1b4b0..249aee73c 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -981,13 +981,13 @@ bool is_admin_command_or_alias(const std::vector& cmds, char *query incoming_servers_t::incoming_servers_t() {} incoming_servers_t::incoming_servers_t( - SQLite3_result* incoming_mysql_servers, + SQLite3_result* runtime_mysql_servers, SQLite3_result* incoming_replication_hostgroups, SQLite3_result* incoming_group_replication_hostgroups, SQLite3_result* incoming_galera_hostgroups, SQLite3_result* incoming_aurora_hostgroups ) : - incoming_mysql_servers(incoming_mysql_servers), + runtime_mysql_servers(runtime_mysql_servers), incoming_replication_hostgroups(incoming_replication_hostgroups), incoming_group_replication_hostgroups(incoming_group_replication_hostgroups), incoming_galera_hostgroups(incoming_galera_hostgroups), @@ -11890,41 +11890,24 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime( SQLite3_result *resultset_galera=NULL; SQLite3_result *resultset_aws_aurora=NULL; - SQLite3_result* incoming_mysql_servers = incoming_servers.incoming_mysql_servers; + SQLite3_result* runtime_mysql_servers = incoming_servers.runtime_mysql_servers; SQLite3_result* incoming_replication_hostgroups = incoming_servers.incoming_replication_hostgroups; SQLite3_result* incoming_group_replication_hostgroups = incoming_servers.incoming_group_replication_hostgroups; SQLite3_result* incoming_galera_hostgroups = incoming_servers.incoming_galera_hostgroups; SQLite3_result* incoming_aurora_hostgroups = incoming_servers.incoming_aurora_hostgroups; - // TODO: Fix ordering here and place mixed ordering in TEST char *query=(char *)"SELECT hostgroup_id,hostname,port,gtid_port,status,weight,compression,max_connections,max_replication_lag,use_ssl,max_latency_ms,comment FROM main.mysql_servers ORDER BY hostgroup_id, hostname, port"; proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", query); - if (incoming_mysql_servers == nullptr) { + if (runtime_mysql_servers == nullptr) { admindb->execute_statement(query, &error , &cols , &affected_rows , &resultset_servers); } else { - resultset_servers = incoming_mysql_servers; + resultset_servers = runtime_mysql_servers; } //MyHGH->wrlock(); if (error) { proxy_error("Error on %s : %s\n", query, error); } else { MyHGM->servers_add(resultset_servers); - size_t init_row_count = resultset_servers->rows_count; - size_t rm_rows_count = 0; - const auto is_offline_server = [&rm_rows_count] (SQLite3_row* row) { - if (strcasecmp(row->fields[4], "OFFLINE_HARD") == 0) { - rm_rows_count += 1; - return true; - } else { - return false; - } - }; - resultset_servers->rows.erase( - std::remove_if(resultset_servers->rows.begin(), resultset_servers->rows.end(), is_offline_server), - resultset_servers->rows.end() - ); - resultset_servers->rows_count = init_row_count - rm_rows_count; - MyHGM->set_incoming_mysql_servers(resultset_servers); } resultset=NULL; @@ -11954,7 +11937,7 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime( proxy_error("Error on %s : %s\n", query, error); } else { // Pass the resultset to MyHGM - MyHGM->set_incoming_replication_hostgroups(resultset_replication); + MyHGM->save_incoming_replication_hostgroups(resultset_replication); } //if (resultset) delete resultset; //resultset=NULL; @@ -11988,7 +11971,7 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime( proxy_error("Error on %s : %s\n", query, error); } else { // Pass the resultset to MyHGM - MyHGM->set_incoming_group_replication_hostgroups(resultset_group_replication); + MyHGM->save_incoming_group_replication_hostgroups(resultset_group_replication); } // support for Galera, table mysql_galera_hostgroups @@ -12019,7 +12002,7 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime( proxy_error("Error on %s : %s\n", query, error); } else { // Pass the resultset to MyHGM - MyHGM->set_incoming_galera_hostgroups(resultset_galera); + MyHGM->save_incoming_galera_hostgroups(resultset_galera); } // support for AWS Aurora, table mysql_aws_aurora_hostgroups @@ -12054,10 +12037,10 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime( proxy_error("Error on %s : %s\n", query, error); } else { // Pass the resultset to MyHGM - MyHGM->set_incoming_aws_aurora_hostgroups(resultset_aws_aurora); + MyHGM->save_incoming_aws_aurora_hostgroups(resultset_aws_aurora); } // commit all the changes - MyHGM->commit(checksum, epoch); + MyHGM->commit(runtime_mysql_servers, checksum, epoch); GloAdmin->save_mysql_servers_runtime_to_database(true); // clean up