MXS-3892: Limit concurrent mapping of databases
As there are no practical benefits to multiple sessions for the same user mapping the databases at the same time, limiting them to one update per user is sensible. This is especially true now that we know the information_schema tables aren't the most efficient things in the world. The current code implements this rate limiting by closing any extra sessions that would start a second update. The final implementation should suspend them for the duration of the update as it is far more user-friendly. The limits are currently global as the shard caches are also global. This is a performance bottleneck and it could be solved by storing the shard cache inside of a mxs::WorkerGlobal instead of having it as a global cache.
This commit is contained in:
@ -45,7 +45,8 @@ SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session,
|
||||
, m_backends(backends)
|
||||
, m_config(router->m_config)
|
||||
, m_router(router)
|
||||
, m_shard(m_router->m_shard_manager.get_shard(get_cache_key(), m_config->refresh_min_interval))
|
||||
, m_key(get_cache_key())
|
||||
, m_shard(m_router->m_shard_manager.get_shard(m_key, m_config->refresh_min_interval))
|
||||
, m_state(0)
|
||||
, m_sent_sescmd(0)
|
||||
, m_replied_sescmd(0)
|
||||
@ -111,6 +112,11 @@ void SchemaRouterSession::close()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state & INIT_MAPPING)
|
||||
{
|
||||
m_router->m_shard_manager.cancel_update(m_key);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(m_router->m_lock);
|
||||
|
||||
if (m_router->m_stats.longest_sescmd < m_stats.longest_sescmd)
|
||||
@ -283,8 +289,26 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
|
||||
|
||||
if (m_shard.empty())
|
||||
{
|
||||
/* Generate database list */
|
||||
query_databases();
|
||||
// Check if another session has managed to update the shard cache
|
||||
m_shard = m_router->m_shard_manager.get_shard(m_key, m_config->refresh_min_interval);
|
||||
|
||||
if (m_shard.empty())
|
||||
{
|
||||
// No entries in the cache, try to start an update
|
||||
if (m_router->m_shard_manager.start_update(m_key))
|
||||
{
|
||||
// No other sessions are doing an update for this user, start one
|
||||
query_databases();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Too many concurrent updates
|
||||
|
||||
// TODO: Queue this session instead of killing it
|
||||
m_pSession->kill(modutil_create_mysql_err_msg(1, 0, 1096, "HY000", "Too many updates"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
@ -753,7 +777,7 @@ void SchemaRouterSession::handleError(GWBUF* pMessage,
|
||||
void SchemaRouterSession::synchronize_shards()
|
||||
{
|
||||
m_router->m_stats.shmap_cache_miss++;
|
||||
m_router->m_shard_manager.update_shard(m_shard, get_cache_key());
|
||||
m_router->m_shard_manager.update_shard(m_shard, m_key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user