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.
This commit is contained in:
Markus Mäkelä 2020-03-11 23:46:35 +02:00
parent caf3b4cf75
commit 291d2e987f
No known key found for this signature in database
GPG Key ID: 5CE746D557ACC499
3 changed files with 17 additions and 8 deletions

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;
}
}