Skip to content

Commit 2726c27

Browse files
authored
Merge pull request #4662 from sysown/v2.7_dns_cache_fixes
DNS record will be removed if MySQL connection fails or times out for a specific hostname [v2.7]
2 parents 76e407e + c5bc9ed commit 2726c27

File tree

7 files changed

+76
-11
lines changed

7 files changed

+76
-11
lines changed

include/MySQL_Monitor.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,9 @@ struct DNS_Cache_Record {
398398
class DNS_Cache {
399399

400400
public:
401-
DNS_Cache() : enabled(true) {
401+
// By default, the DNS cache is disabled.
402+
// This handles the case when ProxySQL is executed with the -M/--no-monitor option.
403+
DNS_Cache() : enabled(false) {
402404
int rc = pthread_rwlock_init(&rwlock_, NULL);
403405
assert(rc == 0);
404406
}
@@ -445,6 +447,7 @@ class MySQL_Monitor {
445447
static std::string dns_lookup(const std::string& hostname, bool return_hostname_if_lookup_fails = true, size_t* ip_count = NULL);
446448
static std::string dns_lookup(const char* hostname, bool return_hostname_if_lookup_fails = true, size_t* ip_count = NULL);
447449
static bool update_dns_cache_from_mysql_conn(const MYSQL* mysql);
450+
static void remove_dns_record_from_dns_cache(const std::string& hostname);
448451
static void trigger_dns_cache_update();
449452

450453
void process_discovered_topology(const std::string& originating_server_hostname, const vector<MYSQL_ROW>& discovered_servers, int reader_hostgroup);
@@ -457,6 +460,7 @@ class MySQL_Monitor {
457460
void drop_tables_defs(std::vector<table_def_t *> *tables_defs);
458461
void check_and_build_standard_tables(SQLite3DB *db, std::vector<table_def_t *> *tables_defs);
459462
static bool _dns_cache_update(const std::string& hostname, std::vector<std::string>&& ip_address);
463+
static void _remove_dns_record_from_dns_cache(const std::string& hostname);
460464

461465
public:
462466
pthread_mutex_t group_replication_mutex; // for simplicity, a mutex instead of a rwlock

include/MySQL_Session.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ class KillArgs {
473473
KillArgs(char *u, char *p, char *h, unsigned int P, unsigned int _hid, unsigned long i, int kt, int _use_ssl, MySQL_Thread* _mt, char *ip);
474474
~KillArgs();
475475
const char* get_host_address() const;
476+
void resolve_hostname();
477+
void remove_dns_record();
476478

477479
private:
478480
char* ip_addr;

include/ProxySQL_Cluster.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class ProxySQL_Node_Address {
104104
~ProxySQL_Node_Address();
105105
const char* get_host_address() const;
106106
void resolve_hostname();
107+
void remove_dns_record();
107108
private:
108109
char* ip_addr;
109110
};

lib/MySQL_Monitor.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,10 @@ bool MySQL_Monitor_State_Data::create_new_connection() {
15641564
myrc=mysql_real_connect(mysql, "localhost", mysql_thread___monitor_username, mysql_thread___monitor_password, NULL, 0, hostname, 0);
15651565
}
15661566
if (myrc==NULL) {
1567+
// port == 0 means we are connecting to a unix socket
1568+
if (port) {
1569+
MySQL_Monitor::remove_dns_record_from_dns_cache(hostname);
1570+
}
15671571
mysql_error_msg=strdup(mysql_error(mysql));
15681572
int myerrno=mysql_errno(mysql);
15691573
MyHGM->p_update_mysql_error_counter(p_mysql_error_type::proxysql, hostgroup_id, hostname, port, myerrno);
@@ -6670,6 +6674,15 @@ bool MySQL_Monitor::update_dns_cache_from_mysql_conn(const MYSQL* mysql)
66706674
return result;
66716675
}
66726676

6677+
void MySQL_Monitor::remove_dns_record_from_dns_cache(const std::string& hostname) {
6678+
6679+
// if IP was provided, no need to update dns cache
6680+
if (hostname.empty() || validate_ip(hostname))
6681+
return;
6682+
6683+
_remove_dns_record_from_dns_cache(hostname);
6684+
}
6685+
66736686
bool MySQL_Monitor::_dns_cache_update(const std::string &hostname, std::vector<std::string>&& ip_address) {
66746687
static thread_local std::shared_ptr<DNS_Cache> dns_cache_thread;
66756688

@@ -6686,6 +6699,18 @@ bool MySQL_Monitor::_dns_cache_update(const std::string &hostname, std::vector<s
66866699
return false;
66876700
}
66886701

6702+
void MySQL_Monitor::_remove_dns_record_from_dns_cache(const std::string& hostname) {
6703+
static thread_local std::shared_ptr<DNS_Cache> dns_cache_thread;
6704+
6705+
if (!dns_cache_thread && GloMyMon)
6706+
dns_cache_thread = GloMyMon->dns_cache;
6707+
6708+
if (dns_cache_thread) {
6709+
dns_cache_thread->remove(trim(hostname));
6710+
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Direct DNS cache record removed. (Hostname:[%s])\n", hostname.c_str());
6711+
}
6712+
}
6713+
66896714
void MySQL_Monitor::trigger_dns_cache_update() {
66906715
if (GloMyMon) {
66916716
GloMyMon->force_dns_cache_update = true;
@@ -6714,19 +6739,20 @@ bool DNS_Cache::add(const std::string& hostname, std::vector<std::string>&& ips)
67146739

67156740
bool DNS_Cache::add_if_not_exist(const std::string& hostname, std::vector<std::string>&& ips) {
67166741
if (!enabled) return false;
6717-
6742+
bool item_added = false;
67186743
int rc = pthread_rwlock_wrlock(&rwlock_);
67196744
assert(rc == 0);
67206745
if (records.find(hostname) == records.end()) {
67216746
proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Updating DNS cache. (Hostname:[%s] IP:[%s])\n", hostname.c_str(), debug_iplisttostring(ips).c_str());
67226747
auto& ip_addr = records[hostname];
67236748
ip_addr.ips = std::move(ips);
67246749
__sync_fetch_and_and(&ip_addr.counter, 0);
6750+
item_added = true;
67256751
}
67266752
rc = pthread_rwlock_unlock(&rwlock_);
67276753
assert(rc == 0);
67286754

6729-
if (GloMyMon)
6755+
if (item_added && GloMyMon)
67306756
__sync_fetch_and_add(&GloMyMon->dns_cache_record_updated, 1);
67316757

67326758
return true;

lib/MySQL_Session.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,7 @@ bool Session_Regex::match(char *m) {
209209
KillArgs::KillArgs(char* u, char* p, char* h, unsigned int P, unsigned int _hid, unsigned long i, int kt, int _use_ssl, MySQL_Thread* _mt) :
210210
KillArgs(u, p, h, P, _hid, i, kt, _use_ssl, _mt, NULL) {
211211
// resolving DNS if available in Cache
212-
if (h && P) {
213-
const std::string& ip = MySQL_Monitor::dns_lookup(h, false);
214-
215-
if (ip.empty() == false) {
216-
ip_addr = strdup(ip.c_str());
217-
}
218-
}
212+
resolve_hostname();
219213
}
220214

221215
KillArgs::KillArgs(char* u, char* p, char* h, unsigned int P, unsigned int _hid, unsigned long i, int kt, int _use_ssl, MySQL_Thread *_mt, char *ip) {
@@ -250,6 +244,25 @@ const char* KillArgs::get_host_address() const {
250244
return host_address;
251245
}
252246

247+
void KillArgs::resolve_hostname() {
248+
if (ip_addr) {
249+
free(ip_addr);
250+
ip_addr = NULL;
251+
}
252+
if (hostname && port) {
253+
const std::string& ip = MySQL_Monitor::dns_lookup(hostname, false);
254+
255+
if (ip.empty() == false) {
256+
ip_addr = strdup(ip.c_str());
257+
}
258+
}
259+
}
260+
261+
void KillArgs::remove_dns_record() {
262+
if (hostname && port) {
263+
MySQL_Monitor::remove_dns_record_from_dns_cache(hostname);
264+
}
265+
}
253266

254267
/**
255268
* @brief Thread function to kill a query or connection on a MySQL server.
@@ -325,6 +338,8 @@ void* kill_query_thread(void *arg) {
325338
ret=mysql_real_connect(mysql,"localhost",ka->username,ka->password,NULL,0,ka->hostname,0);
326339
}
327340
if (!ret) {
341+
ka->remove_dns_record();
342+
//ka->resolve_hostname();
328343
int myerr = mysql_errno(mysql);
329344
if (ssl_params != NULL && myerr == 2026) {
330345
proxy_error("Failed to connect to server %s:%d to run KILL %s %lu. SSL Params: %s , %s , %s , %s , %s , %s , %s , %s\n",

lib/ProxySQL_Cluster.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ void * ProxySQL_Cluster_Monitor_thread(void *args) {
242242
}
243243
} else {
244244
proxy_warning("Cluster: unable to connect to peer %s:%d . Error: %s\n", node->hostname, node->port, mysql_error(conn));
245+
node->remove_dns_record();
245246
node->resolve_hostname();
246247
mysql_close(conn);
247248
conn = mysql_init(NULL);
@@ -4482,3 +4483,11 @@ void ProxySQL_Node_Address::resolve_hostname() {
44824483
}
44834484
}
44844485
}
4486+
4487+
void ProxySQL_Node_Address::remove_dns_record() {
4488+
// make sure hostname is not NULL and port is not 0 (UNIX socket)
4489+
if (hostname && port) {
4490+
MySQL_Monitor::remove_dns_record_from_dns_cache(hostname);
4491+
}
4492+
}
4493+

lib/mysql_connection.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1278,11 +1278,19 @@ MDB_ASYNC_ST MySQL_Connection::handler(short event) {
12781278
//}
12791279
MySQL_Monitor::update_dns_cache_from_mysql_conn(mysql);
12801280
break;
1281-
case ASYNC_CONNECT_FAILED:
1281+
case ASYNC_CONNECT_FAILED:
1282+
// port == 0 means we are connecting to a unix socket
1283+
if (parent->port) {
1284+
MySQL_Monitor::remove_dns_record_from_dns_cache(parent->address);
1285+
}
12821286
MyHGM->p_update_mysql_error_counter(p_mysql_error_type::mysql, parent->myhgc->hid, parent->address, parent->port, mysql_errno(mysql));
12831287
parent->connect_error(mysql_errno(mysql));
12841288
break;
12851289
case ASYNC_CONNECT_TIMEOUT:
1290+
// port == 0 means we are connecting to a unix socket
1291+
if (parent->port) {
1292+
MySQL_Monitor::remove_dns_record_from_dns_cache(parent->address);
1293+
}
12861294
//proxy_error("Connect timeout on %s:%d : %llu - %llu = %llu\n", parent->address, parent->port, myds->sess->thread->curtime , myds->wait_until, myds->sess->thread->curtime - myds->wait_until);
12871295
proxy_error("Connect timeout on %s:%d : exceeded by %lluus\n", parent->address, parent->port, myds->sess->thread->curtime - myds->wait_until);
12881296
MyHGM->p_update_mysql_error_counter(p_mysql_error_type::mysql, parent->myhgc->hid, parent->address, parent->port, mysql_errno(mysql));

0 commit comments

Comments
 (0)