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.
This commit is contained in:
@ -265,10 +265,13 @@ are active transactions:
|
|||||||
|
|
||||||
* `never`: When there is an active transaction, no data will be returned
|
* `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.
|
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
|
The cache will be populated inside _explicitly_ read-only transactions.
|
||||||
or if no non-SELECT statement has been encounted.
|
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
|
* `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
|
* `all_transactions`: The cache will be used and populated inside
|
||||||
_explicitly_ read-only transactions. Inside transactions that are not
|
_explicitly_ read-only transactions. Inside transactions that are not
|
||||||
explicitly read-only, the cache will be used and populated _until_ the
|
explicitly read-only, the cache will be used and populated _until_ the
|
||||||
|
@ -740,11 +740,11 @@ void CacheFilterSession::store_result()
|
|||||||
*
|
*
|
||||||
* @param pParam The GWBUF being handled.
|
* @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
|
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";
|
zReason = "no transaction";
|
||||||
}
|
}
|
||||||
consult_cache = true;
|
action = CACHE_USE_AND_POPULATE;
|
||||||
}
|
}
|
||||||
else if (session_trx_is_read_only(m_pSession))
|
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";
|
zReason = "explicitly read-only transaction";
|
||||||
}
|
}
|
||||||
consult_cache = true;
|
action = CACHE_USE_AND_POPULATE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -785,8 +785,9 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
|
|||||||
|
|
||||||
if (log_decisions())
|
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)
|
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";
|
zReason = "ordinary transaction that has so far been read-only";
|
||||||
}
|
}
|
||||||
consult_cache = true;
|
action = CACHE_USE_AND_POPULATE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -809,8 +810,11 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
|
|||||||
|
|
||||||
if (log_decisions())
|
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
|
else
|
||||||
@ -821,7 +825,7 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consult_cache)
|
if (action != CACHE_IGNORE)
|
||||||
{
|
{
|
||||||
if (is_select_statement(pPacket))
|
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))
|
if (qc_query_is_type(type_mask, QUERY_TYPE_USERVAR_READ))
|
||||||
{
|
{
|
||||||
consult_cache = false;
|
action = CACHE_IGNORE;
|
||||||
zReason = "user variables are read";
|
zReason = "user variables are read";
|
||||||
}
|
}
|
||||||
else if (qc_query_is_type(type_mask, QUERY_TYPE_SYSVAR_READ))
|
else if (qc_query_is_type(type_mask, QUERY_TYPE_SYSVAR_READ))
|
||||||
{
|
{
|
||||||
consult_cache = false;
|
action = CACHE_IGNORE;
|
||||||
zReason = "system variables are read";
|
zReason = "system variables are read";
|
||||||
}
|
}
|
||||||
else if (uses_non_cacheable_function(pPacket))
|
else if (uses_non_cacheable_function(pPacket))
|
||||||
{
|
{
|
||||||
consult_cache = false;
|
action = CACHE_IGNORE;
|
||||||
zReason = "uses non-cacheable function";
|
zReason = "uses non-cacheable function";
|
||||||
}
|
}
|
||||||
else if (uses_non_cacheable_variable(pPacket))
|
else if (uses_non_cacheable_variable(pPacket))
|
||||||
{
|
{
|
||||||
consult_cache = false;
|
action = CACHE_IGNORE;
|
||||||
zReason = "uses non-cacheable variable";
|
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
|
// 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
|
// 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;
|
m_is_read_only = false;
|
||||||
consult_cache = false;
|
|
||||||
|
action = CACHE_IGNORE;
|
||||||
zReason = "statement is not SELECT";
|
zReason = "statement is not SELECT";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -885,13 +891,13 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
|
|||||||
length = max_length - 3; // strlen("...");
|
length = max_length - 3; // strlen("...");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* zDecision = (consult_cache ? "CONSULT" : "IGNORE ");
|
const char* zDecision = (action == CACHE_IGNORE) ? "IGNORE" : "CONSULT";
|
||||||
|
|
||||||
ss_dassert(zReason);
|
ss_dassert(zReason);
|
||||||
MXS_NOTICE(zFormat, zDecision, length, pSql, 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<uint8_t*>(GWBUF_DATA(pPacket)));
|
ss_debug(uint8_t* pData = static_cast<uint8_t*>(GWBUF_DATA(pPacket)));
|
||||||
ss_dassert((int)MYSQL_GET_COMMAND(pData) == MXS_COM_QUERY);
|
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))
|
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))
|
if (CACHE_RESULT_IS_OK(result))
|
||||||
{
|
{
|
||||||
action = route_SELECT(pPacket);
|
routing_action = route_SELECT(cache_action, pPacket);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -932,24 +939,25 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_COM_QUERY(GWBUF*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action;
|
return routing_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routes a SELECT packet.
|
* 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
|
* @return ROUTING_ABORT if the processing of the packet should be aborted
|
||||||
* (as the data is obtained from the cache) or
|
* (as the data is obtained from the cache) or
|
||||||
* ROUTING_CONTINUE if the normal processing should continue.
|
* 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;
|
uint32_t flags = CACHE_FLAGS_INCLUDE_STALE;
|
||||||
GWBUF* pResponse;
|
GWBUF* pResponse;
|
||||||
@ -975,7 +983,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa
|
|||||||
gwbuf_free(pResponse);
|
gwbuf_free(pResponse);
|
||||||
|
|
||||||
m_refreshing = true;
|
m_refreshing = true;
|
||||||
action = ROUTING_CONTINUE;
|
routing_action = ROUTING_CONTINUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -986,7 +994,7 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa
|
|||||||
MXS_NOTICE("Cache data is stale but returning it, fresh "
|
MXS_NOTICE("Cache data is stale but returning it, fresh "
|
||||||
"data is being fetched already.");
|
"data is being fetched already.");
|
||||||
}
|
}
|
||||||
action = ROUTING_ABORT;
|
routing_action = ROUTING_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -995,15 +1003,15 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa
|
|||||||
{
|
{
|
||||||
MXS_NOTICE("Using fresh data from cache.");
|
MXS_NOTICE("Using fresh data from cache.");
|
||||||
}
|
}
|
||||||
action = ROUTING_ABORT;
|
routing_action = ROUTING_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
action = ROUTING_CONTINUE;
|
routing_action = ROUTING_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == ROUTING_CONTINUE)
|
if (routing_action == ROUTING_CONTINUE)
|
||||||
{
|
{
|
||||||
m_state = CACHE_EXPECTING_RESPONSE;
|
m_state = CACHE_EXPECTING_RESPONSE;
|
||||||
}
|
}
|
||||||
@ -1020,6 +1028,8 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ss_dassert(should_populate(cache_action));
|
||||||
|
|
||||||
// We will not use any value in the cache, but we will update
|
// We will not use any value in the cache, but we will update
|
||||||
// the existing value.
|
// the existing value.
|
||||||
if (log_decisions())
|
if (log_decisions())
|
||||||
@ -1030,5 +1040,5 @@ CacheFilterSession::routing_action_t CacheFilterSession::route_SELECT(GWBUF* pPa
|
|||||||
m_state = CACHE_EXPECTING_RESPONSE;
|
m_state = CACHE_EXPECTING_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return action;
|
return routing_action;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,25 @@ private:
|
|||||||
|
|
||||||
void store_result();
|
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
|
enum routing_action_t
|
||||||
{
|
{
|
||||||
@ -118,7 +136,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
routing_action_t route_COM_QUERY(GWBUF* pPacket);
|
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:
|
private:
|
||||||
CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, char* zDefaultDb);
|
CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, char* zDefaultDb);
|
||||||
|
Reference in New Issue
Block a user