From 7db8f24b8b4ce03b2e379d20d71b8760ff50a09c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 11 Jun 2018 08:51:36 +0200 Subject: [PATCH] For Galera cluster, try to find the most appropriate node if none seems healthy --- include/MySQL_Monitor.hpp | 1 + lib/MySQL_HostGroups_Manager.cpp | 58 ++++++++++++++++++++++++++++++++ lib/MySQL_Monitor.cpp | 35 +++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/include/MySQL_Monitor.hpp b/include/MySQL_Monitor.hpp index 1bf668927..b40a2a42a 100644 --- a/include/MySQL_Monitor.hpp +++ b/include/MySQL_Monitor.hpp @@ -188,6 +188,7 @@ class MySQL_Monitor { void populate_monitor_mysql_server_group_replication_log(); void populate_monitor_mysql_server_galera_log(); char * galera_find_last_node(int); + std::vector * galera_find_possible_last_nodes(int); bool server_responds_to_ping(char *address, int port); }; diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 2a057ebcc..2a3917248 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -3956,6 +3956,7 @@ void MySQL_HostGroups_Manager::converge_galera_config(int _writer_hostgroup) { if (num_writers == 0 && num_backup_writers == 0) { proxy_warning("Galera: we couldn't find any healthy node for writer HG %d\n", info->writer_hostgroup); // ask Monitor to get the status of the whole cluster + /* char * s0 = GloMyMon->galera_find_last_node(info->writer_hostgroup); if (s0) { std::string s = string(s0); @@ -3980,6 +3981,63 @@ void MySQL_HostGroups_Manager::converge_galera_config(int _writer_hostgroup) { } free(s0); } + */ + std::vector * pn = GloMyMon->galera_find_possible_last_nodes(info->writer_hostgroup); + if (pn->size()) { + std::vector::iterator it2; + for (it2=pn->begin(); it2!=pn->end(); ++it2) { + string s0 = *it2; + proxy_info("Galera: possible writer candidate for HG %d: %s\n", info->writer_hostgroup, s0.c_str()); + } + char *error=NULL; + int cols; + int affected_rows; + SQLite3_result *resultset2=NULL; + q = (char *)"SELECT hostname, port FROM mysql_servers_incoming WHERE hostgroup_id IN (%d, %d, %d, %d) ORDER BY weight DESC, hostname DESC, port DESC"; + query=(char *)malloc(strlen(q) + 256); + sprintf(query,q,info->writer_hostgroup, info->writer_hostgroup, info->backup_writer_hostgroup, info->reader_hostgroup, info->offline_hostgroup); + mydb->execute_statement(query, &error , &cols , &affected_rows , &resultset2); + free(query); + if (resultset2) { + bool stop = false; + for (std::vector::iterator it = resultset2->rows.begin() ; (it != resultset2->rows.end()) && !stop ; ++it) { + SQLite3_row *r=*it; + char *h = r->fields[0]; + int p = atoi(r->fields[1]); + if (h) { + for (it2=pn->begin(); (it2!=pn->end()) && !stop; ++it2) { + std::string s = string(*it2); + std::size_t found=s.find_last_of(":"); + std::string host=s.substr(0,found); + std::string port=s.substr(found+1); + int port_n = atoi(port.c_str()); + if (strcmp(h,host.c_str())==0) { + if (p == port_n) { + stop = true; // we found a host to make a writer + proxy_info("Galera: trying to use server %s:%s as a writer for HG %d\n", host.c_str(), port.c_str(), info->writer_hostgroup); + q=(char *)"UPDATE OR REPLACE mysql_servers_incoming SET status=0, hostgroup_id=%d WHERE hostgroup_id IN (%d, %d, %d, %d) AND hostname='%s' AND port=%d"; + query=(char *)malloc(strlen(q) + s.length() + 512); + sprintf(query,q,info->writer_hostgroup, info->writer_hostgroup, info->backup_writer_hostgroup, info->reader_hostgroup, info->offline_hostgroup, host.c_str(), port_n); + mydb->execute(query); + free(query); + bool writer_is_also_reader = info->writer_is_also_reader; + if (writer_is_also_reader) { + int read_HG = info->reader_hostgroup; + q=(char *)"INSERT OR IGNORE INTO mysql_servers_incoming (hostgroup_id,hostname,port,gtid_port,status,weight,compression,max_connections,max_replication_lag,use_ssl,max_latency_ms,comment) SELECT %d,hostname,port,gtid_port,status,weight,compression,max_connections,max_replication_lag,use_ssl,max_latency_ms,comment FROM mysql_servers_incoming WHERE hostgroup_id=%d AND hostname='%s' AND port=%d"; + query=(char *)malloc(strlen(q) + s.length() + 128); + sprintf(query,q,read_HG, info->writer_hostgroup, host.c_str(), port_n); + mydb->execute(query); + free(query); + } + } + } + } + } + } + delete resultset2; + } + } + delete pn; } } } diff --git a/lib/MySQL_Monitor.cpp b/lib/MySQL_Monitor.cpp index 39f0eb480..c40ea4d2e 100644 --- a/lib/MySQL_Monitor.cpp +++ b/lib/MySQL_Monitor.cpp @@ -2768,3 +2768,38 @@ char * MySQL_Monitor::galera_find_last_node(int writer_hostgroup) { pthread_mutex_unlock(&GloMyMon->galera_mutex); return str; } + +std::vector * MySQL_Monitor::galera_find_possible_last_nodes(int writer_hostgroup) { + std::vector * result = new std::vector(); +// std::vector tmp_list; + char *str = NULL; + pthread_mutex_lock(&GloMyMon->galera_mutex); + std::map::iterator it2; + Galera_monitor_node *node=NULL; + unsigned int writer_nodes = 0; + unsigned long long curtime = monotonic_time(); + unsigned long long ti = mysql_thread___monitor_galera_healthcheck_interval; + ti *= 2; + //std::string s = ""; + for (it2=GloMyMon->Galera_Hosts_Map.begin(); it2!=GloMyMon->Galera_Hosts_Map.end(); ++it2) { + node=it2->second; + if (node->writer_hostgroup == writer_hostgroup) { + Galera_status_entry_t * st = node->last_entry(); + if (st) { + if (st->start_time >= curtime - ti) { // only consider recent checks + if (st->error == NULL) { // no check error + if (st->read_only == false) { // the server is writable (this check is arguable) + if (st->wsrep_sst_donor_rejects_queries == false) { + //tmp_list.push_back(node); + string s = it2->first; + result->push_back(s); + } + } + } + } + } + } + } + pthread_mutex_unlock(&GloMyMon->galera_mutex); + return result; +}