MXS-1549: Track transaction type in the query classifier

The characteristics of a transaction can now be tracked by the query
classifier. This allows read-only and read-write transaction statistics to
be calculated.
This commit is contained in:
Markus Mäkelä 2018-06-23 09:48:32 +03:00
parent ccdbfa8997
commit b59f607471
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
2 changed files with 64 additions and 28 deletions

View File

@ -208,6 +208,16 @@ public:
m_load_data_state = state;
}
/**
* Check if current transaction is still a read-only transaction
*
* @return True if no statements have been executed that modify data
*/
bool is_trx_still_read_only() const
{
return m_trx_is_read_only;
}
/**
* @brief Store and process a prepared statement
*
@ -313,6 +323,15 @@ private:
*/
uint32_t ps_id_internal_get(GWBUF* pBuffer);
/**
* Check if the query type is that of a read-only query
*
* @param qtype Query type mask
*
* @return True if the query type is that of a read-only query
*/
bool query_type_is_read_only(uint32_t qtype) const;
uint32_t get_route_target(uint8_t command, uint32_t qtype, HINT* pHints);
MXS_SESSION* session() const
@ -361,6 +380,7 @@ private:
SPSManager m_sPs_manager;
HandleMap m_ps_handles; /** External ID to internal ID */
RouteInfo m_route_info;
bool m_trx_is_read_only;
};
}

View File

@ -346,6 +346,7 @@ QueryClassifier::QueryClassifier(Handler* pHandler,
, m_large_query(false)
, m_multi_statements_allowed(are_multi_statements_allowed(pSession))
, m_sPs_manager(new PSManager)
, m_trx_is_read_only(true)
{
}
@ -369,6 +370,34 @@ void QueryClassifier::ps_erase(GWBUF* buffer)
return m_sPs_manager->erase(buffer);
}
bool QueryClassifier::query_type_is_read_only(uint32_t qtype) const
{
bool rval = false;
if (!qc_query_is_type(qtype, QUERY_TYPE_MASTER_READ) &&
!qc_query_is_type(qtype, QUERY_TYPE_WRITE) &&
(qc_query_is_type(qtype, QUERY_TYPE_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_SHOW_TABLES) ||
qc_query_is_type(qtype, QUERY_TYPE_USERVAR_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_SYSVAR_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_READ)))
{
if (qc_query_is_type(qtype, QUERY_TYPE_USERVAR_READ))
{
if (m_use_sql_variables_in == TYPE_ALL)
{
rval = true;
}
}
else
{
rval = true;
}
}
return rval;
}
uint32_t QueryClassifier::get_route_target(uint8_t command, uint32_t qtype, HINT* pHints)
{
bool trx_active = session_trx_is_active(m_pSession);
@ -430,35 +459,9 @@ uint32_t QueryClassifier::get_route_target(uint8_t command, uint32_t qtype, HINT
/**
* Hints may affect on routing of the following queries
*/
else if (!trx_active && !load_active &&
!qc_query_is_type(qtype, QUERY_TYPE_MASTER_READ) &&
!qc_query_is_type(qtype, QUERY_TYPE_WRITE) &&
(qc_query_is_type(qtype, QUERY_TYPE_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_SHOW_TABLES) ||
qc_query_is_type(qtype, QUERY_TYPE_USERVAR_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_SYSVAR_READ) ||
qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_READ)))
else if (!trx_active && !load_active && query_type_is_read_only(qtype))
{
if (qc_query_is_type(qtype, QUERY_TYPE_USERVAR_READ))
{
if (m_use_sql_variables_in == TYPE_ALL)
{
target = TARGET_SLAVE;
}
}
else if (qc_query_is_type(qtype, QUERY_TYPE_READ) || // Normal read
qc_query_is_type(qtype, QUERY_TYPE_SHOW_TABLES) || // SHOW TABLES
qc_query_is_type(qtype, QUERY_TYPE_SYSVAR_READ) || // System variable
qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_READ)) // Global system variable
{
target = TARGET_SLAVE;
}
/** If nothing matches then choose the master */
if ((target & (TARGET_ALL | TARGET_SLAVE | TARGET_MASTER)) == 0)
{
target = TARGET_MASTER;
}
target = TARGET_SLAVE;
}
else if (session_trx_is_read_only(m_pSession))
{
@ -929,6 +932,19 @@ QueryClassifier::update_route_info(QueryClassifier::current_target_t current_tar
route_target = get_route_target(command, type_mask, pBuffer->hint);
}
if (session_trx_is_ending(m_pSession) ||
qc_query_is_type(type_mask, QUERY_TYPE_BEGIN_TRX))
{
// Transaction is ending or starting
m_trx_is_read_only = true;
}
else if (session_trx_is_active(m_pSession) &&
!query_type_is_read_only(type_mask))
{
// Transaction is no longer read-only
m_trx_is_read_only = false;
}
}
else if (load_data_state() == QueryClassifier::LOAD_DATA_ACTIVE)
{