From f52a0acbbe7079e5899a3a5e6450cd380cc95675 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Wed, 25 Oct 2017 16:01:13 +0300 Subject: [PATCH] MXS-1474 Document and act in the same way From the documentation: * `never`: When there is an active transaction, no data will be returned from the cache, but all requests will always be sent to the backend. The cache will be populated inside _explicitly_ read-only transactions. Inside transactions that are not explicitly read-only, the cache will be populated _until_ the first non-SELECT statement. * `read_only_transactions`: The cache will be used and populated inside _explicitly_ read-only transactions. Inside transactions that are not explicitly read-only, the cache will be populated, but not used _until_ the first non-SELECT statement. * `all_transactions`: The cache will be used and populated inside _explicitly_ read-only transactions. Inside transactions that are not explicitly read-only, the cache will be used and populated _until_ the first non-SELECT statement. --- Documentation/Filters/Cache.md | 9 ++- .../filter/cache/cachefiltersession.cc | 72 +++++++++++-------- .../filter/cache/cachefiltersession.hh | 22 +++++- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/Documentation/Filters/Cache.md b/Documentation/Filters/Cache.md index 0310d077b..68958287a 100644 --- a/Documentation/Filters/Cache.md +++ b/Documentation/Filters/Cache.md @@ -265,10 +265,13 @@ are active transactions: * `never`: When there is an active transaction, no data will be returned from the cache, but all requests will always be sent to the backend. - The cache will be populated if the transaction is explicitly read only - or if no non-SELECT statement has been encounted. + The cache will be populated inside _explicitly_ read-only transactions. + Inside transactions that are not explicitly read-only, the cache will + be populated _until_ the first non-SELECT statement. * `read_only_transactions`: The cache will be used and populated inside - _explicitly_ read-only transactions. + _explicitly_ read-only transactions. Inside transactions that are not + explicitly read-only, the cache will be populated, but not used + _until_ the first non-SELECT statement. * `all_transactions`: The cache will be used and populated inside _explicitly_ read-only transactions. Inside transactions that are not explicitly read-only, the cache will be used and populated _until_ the diff --git a/server/modules/filter/cache/cachefiltersession.cc b/server/modules/filter/cache/cachefiltersession.cc index 442c83c03..32df9e29c 100644 --- a/server/modules/filter/cache/cachefiltersession.cc +++ b/server/modules/filter/cache/cachefiltersession.cc @@ -740,11 +740,11 @@ void CacheFilterSession::store_result() * * @param pParam The GWBUF being handled. * - * @return True, if the cache should be consulted, false otherwise. + * @return Enum value indicating appropriate action. */ -bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) +CacheFilterSession::cache_action_t CacheFilterSession::get_cache_action(GWBUF* pPacket) { - bool consult_cache = false; + cache_action_t action = CACHE_IGNORE; uint32_t type_mask = qc_get_trx_type_mask(pPacket); // Note, only trx-related type mask @@ -767,7 +767,7 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) { zReason = "no transaction"; } - consult_cache = true; + action = CACHE_USE_AND_POPULATE; } else if (session_trx_is_read_only(m_pSession)) { @@ -777,7 +777,7 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) { zReason = "explicitly read-only transaction"; } - consult_cache = true; + action = CACHE_USE_AND_POPULATE; } else { @@ -785,8 +785,9 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) if (log_decisions()) { - zReason = "no caching inside transactions"; + zReason = "populating but not using cache inside read-only transactions"; } + action = CACHE_POPULATE; } } else if (m_is_read_only) @@ -800,7 +801,7 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) { zReason = "ordinary transaction that has so far been read-only"; } - consult_cache = true; + action = CACHE_USE_AND_POPULATE; } else { @@ -809,8 +810,11 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) if (log_decisions()) { - zReason = "no caching inside not explicitly read-only transactions"; + zReason = + "populating but not using cache inside transaction that is not " + "explicitly read-only, but that has used only SELECTs sofar"; } + action = CACHE_POPULATE; } } else @@ -821,7 +825,7 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) } } - if (consult_cache) + if (action != CACHE_IGNORE) { if (is_select_statement(pPacket)) { @@ -833,22 +837,22 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) if (qc_query_is_type(type_mask, QUERY_TYPE_USERVAR_READ)) { - consult_cache = false; + action = CACHE_IGNORE; zReason = "user variables are read"; } else if (qc_query_is_type(type_mask, QUERY_TYPE_SYSVAR_READ)) { - consult_cache = false; + action = CACHE_IGNORE; zReason = "system variables are read"; } else if (uses_non_cacheable_function(pPacket)) { - consult_cache = false; + action = CACHE_IGNORE; zReason = "uses non-cacheable function"; } else if (uses_non_cacheable_variable(pPacket)) { - consult_cache = false; + action = CACHE_IGNORE; zReason = "uses non-cacheable variable"; } } @@ -857,9 +861,11 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) { // A bit broad, as e.g. SHOW will cause the read only state to be turned // off. However, during normal use this will always be an UPDATE, INSERT - // or DELETE. + // or DELETE. Note that 'm_is_read_only' only affects transactions that + // are not explicitly read-only. m_is_read_only = false; - consult_cache = false; + + action = CACHE_IGNORE; zReason = "statement is not SELECT"; } } @@ -885,13 +891,13 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket) length = max_length - 3; // strlen("..."); } - const char* zDecision = (consult_cache ? "CONSULT" : "IGNORE "); + const char* zDecision = (action == CACHE_IGNORE) ? "IGNORE" : "CONSULT"; ss_dassert(zReason); MXS_NOTICE(zFormat, zDecision, length, pSql, zReason); } - return consult_cache; + return action; } /** @@ -908,9 +914,10 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_COM_QUERY(GWBUF* ss_debug(uint8_t* pData = static_cast(GWBUF_DATA(pPacket))); ss_dassert((int)MYSQL_GET_COMMAND(pData) == MXS_COM_QUERY); - routing_action_t action = ROUTING_CONTINUE; + routing_action_t routing_action = ROUTING_CONTINUE; + cache_action_t cache_action = get_cache_action(pPacket); - if (should_consult_cache(pPacket)) + if (cache_action != CACHE_IGNORE) { if (m_pCache->should_store(m_zDefaultDb, pPacket)) { @@ -918,7 +925,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_COM_QUERY(GWBUF* if (CACHE_RESULT_IS_OK(result)) { - action = route_SELECT(pPacket); + routing_action = route_SELECT(cache_action, pPacket); } else { @@ -932,24 +939,25 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_COM_QUERY(GWBUF* } } - return action; + return routing_action; } /** * Routes a SELECT packet. * - * @param pPacket A contiguous COM_QUERY packet containing a SELECT. + * @param cache_action The desired action. + * @param pPacket A contiguous COM_QUERY packet containing a SELECT. * * @return ROUTING_ABORT if the processing of the packet should be aborted * (as the data is obtained from the cache) or * ROUTING_CONTINUE if the normal processing should continue. */ -CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPacket) +CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(cache_action_t cache_action, GWBUF* pPacket) { - routing_action_t action = ROUTING_CONTINUE; + routing_action_t routing_action = ROUTING_CONTINUE; - if (m_pCache->should_use(m_pSession)) + if (should_use(cache_action) && m_pCache->should_use(m_pSession)) { uint32_t flags = CACHE_FLAGS_INCLUDE_STALE; GWBUF* pResponse; @@ -975,7 +983,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa gwbuf_free(pResponse); m_refreshing = true; - action = ROUTING_CONTINUE; + routing_action = ROUTING_CONTINUE; } else { @@ -986,7 +994,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa MXS_NOTICE("Cache data is stale but returning it, fresh " "data is being fetched already."); } - action = ROUTING_ABORT; + routing_action = ROUTING_ABORT; } } else @@ -995,15 +1003,15 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa { MXS_NOTICE("Using fresh data from cache."); } - action = ROUTING_ABORT; + routing_action = ROUTING_ABORT; } } else { - action = ROUTING_CONTINUE; + routing_action = ROUTING_CONTINUE; } - if (action == ROUTING_CONTINUE) + if (routing_action == ROUTING_CONTINUE) { m_state = CACHE_EXPECTING_RESPONSE; } @@ -1020,6 +1028,8 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa } else { + ss_dassert(should_populate(cache_action)); + // We will not use any value in the cache, but we will update // the existing value. if (log_decisions()) @@ -1030,5 +1040,5 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa m_state = CACHE_EXPECTING_RESPONSE; } - return action; + return routing_action; } diff --git a/server/modules/filter/cache/cachefiltersession.hh b/server/modules/filter/cache/cachefiltersession.hh index d4ba32bd2..7eea52ccd 100644 --- a/server/modules/filter/cache/cachefiltersession.hh +++ b/server/modules/filter/cache/cachefiltersession.hh @@ -109,7 +109,25 @@ private: void store_result(); - bool should_consult_cache(GWBUF* pPacket); + enum cache_action_t + { + CACHE_IGNORE = 0, + CACHE_USE = 1, + CACHE_POPULATE = 2, + CACHE_USE_AND_POPULATE = (CACHE_USE | CACHE_POPULATE) + }; + + static bool should_use(cache_action_t action) + { + return action & CACHE_USE ? true : false; + } + + static bool should_populate(cache_action_t action) + { + return action & CACHE_POPULATE ? true : false; + } + + cache_action_t get_cache_action(GWBUF* pPacket); enum routing_action_t { @@ -118,7 +136,7 @@ private: }; routing_action_t route_COM_QUERY(GWBUF* pPacket); - routing_action_t route_SELECT(GWBUF* pPacket); + routing_action_t route_SELECT(cache_action_t action, GWBUF* pPacket); private: CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, char* zDefaultDb);