From 291d2e987f9731a94035416a3c4828cfff1deb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Wed, 11 Mar 2020 23:46:35 +0200 Subject: [PATCH] Improve charset selection The charset sent in the handshake is now done with the following priorities: * First Master server * Last Slave server * First Running server or Down server whose charset is known The change is that server in the Down state to which we've successfully connected to can also be used as the charset source. This, in addition with an "empty" default charset, helps avoid the use of the default latin1 charset unless absolutely necessary. --- include/maxscale/server.hh | 7 ++++--- server/core/mysql_utils.cc | 11 +++++++++-- .../protocol/MySQL/mariadbclient/mysql_client.cc | 7 ++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/include/maxscale/server.hh b/include/maxscale/server.hh index 195cbd904..bd5b4fc3e 100644 --- a/include/maxscale/server.hh +++ b/include/maxscale/server.hh @@ -181,8 +181,10 @@ public: * routing sessions. */ // Base variables - bool is_active = false; /**< Server is active and has not been "destroyed" */ - uint8_t charset = DEFAULT_CHARSET; /**< Character set. Read from backend and sent to client. */ + bool is_active = false; /**< Server is active and has not been "destroyed" */ + uint8_t charset = 0; /**< Character set. Read from backend and sent to client. As no character set + * has the numeric value of 0, it can be used to detect servers we haven't + * connected to. */ // Statistics and events ConnStats stats; /**< The server statistics, e.g. number of connections */ @@ -535,7 +537,6 @@ protected: } private: - static const int DEFAULT_CHARSET = 0x08; /**< The latin1 charset */ maxbase::EMAverage m_response_time; /**< Response time calculations for this server */ std::mutex m_average_write_mutex; /**< Protects response time from concurrent writing */ mxs::SSLProvider m_ssl_provider; diff --git a/server/core/mysql_utils.cc b/server/core/mysql_utils.cc index 6c91ad40d..8e0d63ee5 100644 --- a/server/core/mysql_utils.cc +++ b/server/core/mysql_utils.cc @@ -406,7 +406,8 @@ const char* dbg_decode_response(GWBUF* pPacket) void mxs_update_server_charset(MYSQL* mysql, SERVER* server) { const char* CHARSET_QUERY = - "SELECT co.id FROM information_schema.collations AS co " + "SELECT co.id, @@global.character_set_server " + "FROM information_schema.collations AS co " "JOIN information_schema.character_sets AS cs " "ON (co.collation_name = cs.default_collate_name) " "WHERE cs.character_set_name=@@global.character_set_server;"; @@ -419,7 +420,13 @@ void mxs_update_server_charset(MYSQL* mysql, SERVER* server) { if (row[0]) { - server->charset = atoi(row[0]); + auto charset = atoi(row[0]); + + if (server->charset != charset) + { + MXS_NOTICE("Server '%s' charset: %s", server->name(), row[1]); + server->charset = charset; + } } } diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index 927811b24..e9edf1ac1 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -235,17 +235,18 @@ uint8_t get_charset(SERVER_REF* servers) for (SERVER_REF* s = servers; s; s = s->next) { - if (server_ref_is_active(s)) + if (server_ref_is_active(s) && s->server->charset) { + // The reference is active and we've queried the charset it uses if (s->server->is_master()) { // Master found, stop searching rval = s->server->charset; break; } - else if (s->server->is_slave() || (s->server->is_running() && rval == 0)) + else if (s->server->is_slave() || rval == 0) { - // Slaves precede Running servers + // Slaves precede Running servers and server that are Down but whose charset is known rval = s->server->charset; } }