Use cache as long as a trx only performes reads

As before, the cache will be used if there is no ongoing transaction
(includes autocommit being on), or if there is an explicitly read-
only transaction.

In addition, the cache will be used and populated during any other
transaction as long as only pure read statements are executed. After
first non-read statement, the use of the cache is disabled.
This commit is contained in:
Johan Wikman
2017-02-28 14:46:57 +02:00
parent f1ea0b03d1
commit 82049b8ed1
4 changed files with 75 additions and 14 deletions

View File

@ -41,6 +41,7 @@ CacheFilterSession::CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, cha
, m_zDefaultDb(zDefaultDb)
, m_zUseDb(NULL)
, m_refreshing(false)
, m_is_read_only(true)
{
memset(m_key.data, 0, CACHE_KEY_MAXLEN);
@ -130,7 +131,59 @@ int CacheFilterSession::routeQuery(GWBUF* pPacket)
case MYSQL_COM_QUERY:
{
if (!session_trx_is_active(m_pSession) || session_trx_is_read_only(m_pSession))
bool consult_cache = false;
uint32_t type_mask = qc_get_type_mask(pPacket);
if (type_mask & QUERY_TYPE_BEGIN_TRX)
{
// When a transaction is started, we initially assume it is read-only.
m_is_read_only = true;
}
else if (!(type_mask & QUERY_TYPE_READ))
{
// Thereafter, if there's any non-read statement we mark it as non-readonly.
// Note that the state of m_is_read_only is not consulted if there is no
// on-going transaction of if there is an explicitly read-only transaction.
m_is_read_only = false;
}
if (!session_trx_is_active(m_pSession))
{
if (log_decisions())
{
MXS_NOTICE("Cache can be used and stored to, since there is no transaction.");
}
consult_cache = true;
}
else if (session_trx_is_read_only(m_pSession))
{
if (log_decisions())
{
MXS_NOTICE("Cache can be used and stored to since there is an explicitly "
"read-only transaction.");
}
consult_cache = true;
}
else if (m_is_read_only)
{
if (log_decisions())
{
MXS_NOTICE("Cache can be used and stored to, since the current transaction "
"(not explicitly read-only) has so far been read-only.");
}
consult_cache = true;
}
else
{
if (log_decisions())
{
MXS_NOTICE("Cache can not be used, since a not explicitly read-only transaction "
"is active and the transaction has executed non-read statements.");
}
}
if (consult_cache)
{
// We do not care whether the query was fully parsed or not.
// If a query cannot be fully parsed, the worst thing that can
@ -215,16 +268,6 @@ int CacheFilterSession::routeQuery(GWBUF* pPacket)
}
}
}
else
{
if (log_decisions())
{
MXS_NOTICE("autocommit = %s and transaction state %s => Not using or "
"storing to cache.",
session_is_autocommit(m_pSession) ? "ON" : "OFF",
session_trx_state_to_string(session_get_trx_state(m_pSession)));
}
}
}
break;

View File

@ -119,5 +119,6 @@ private:
char* m_zDefaultDb; /**< The default database. */
char* m_zUseDb; /**< Pending default database. Needs server response. */
bool m_refreshing; /**< Whether the session is updating a stale cache entry. */
bool m_is_read_only;/**< Whether the current trx has been read-only in pratice. */
};