MXS-969: Detect user variable modifications

With the use_sql_variables_in=master option, readwritesplit should route
all user variable modifications and reads with user variables to the
master.

Previously, the modification of user variables was grouped into generic
system variables which caused all modifications to system variables to go
to the master only. The router requires a finer grained distiction between
normal system variable modifications and user variable modifications.

With the improvements to the query classifier, readwritesplit now properly
routes all user variable operations to the master and other system
variable modifications to all servers.
This commit is contained in:
Markus Makela 2016-11-15 13:36:28 +02:00
parent 59ee5a78c9
commit 5aefd35df9

View File

@ -1346,9 +1346,10 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
*/
else if (!load_active &&
(QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
/** Configured to allow writing variables to all nodes */
/** Configured to allow writing user variables to all nodes */
(use_sql_variables_in == TYPE_ALL &&
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_WRITE)) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_WRITE)) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_WRITE) ||
/** enable or disable autocommit are always routed to all */
QUERY_IS_TYPE(qtype, QUERY_TYPE_ENABLE_AUTOCOMMIT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_DISABLE_AUTOCOMMIT)))
@ -1388,44 +1389,29 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
* Hints may affect on routing of the following queries
*/
else if (!trx_active && !load_active &&
!QUERY_IS_TYPE(qtype, QUERY_TYPE_MASTER_READ) &&
!QUERY_IS_TYPE(qtype, QUERY_TYPE_WRITE) &&
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) || /*< any SELECT */
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) || /*< 'SHOW TABLES' */
QUERY_IS_TYPE(qtype,
QUERY_TYPE_USERVAR_READ) || /*< read user var */
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) || /*< read sys var */
QUERY_IS_TYPE(qtype,
QUERY_TYPE_EXEC_STMT) || /*< prepared stmt exec */
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) ||
QUERY_IS_TYPE(qtype,
QUERY_TYPE_GSYSVAR_READ))) /*< read global sys var */
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ)))
{
/** First set expected targets before evaluating hints */
if (!QUERY_IS_TYPE(qtype, QUERY_TYPE_MASTER_READ) &&
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) || /*< 'SHOW TABLES' */
/** Configured to allow reading variables from slaves */
(use_sql_variables_in == TYPE_ALL &&
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ)))))
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ))
{
if (use_sql_variables_in == TYPE_ALL)
{
target = TARGET_SLAVE;
}
}
else if (QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) || // Normal read
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) || // SHOW TABLES
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) || // System variable
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ)) // Global system variable
{
target = TARGET_SLAVE;
}
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_MASTER_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) ||
/** Configured not to allow reading variables from slaves */
(use_sql_variables_in == TYPE_MASTER &&
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ))))
{
target = TARGET_MASTER;
}
/** If nothing matches then choose the master */
if ((target & (TARGET_ALL | TARGET_SLAVE | TARGET_MASTER)) == 0)
{
@ -1434,7 +1420,7 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
}
else
{
ss_dassert(trx_active ||
ss_dassert(trx_active || load_active ||
(QUERY_IS_TYPE(qtype, QUERY_TYPE_WRITE) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_MASTER_READ) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
@ -1446,6 +1432,8 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
use_sql_variables_in == TYPE_MASTER) ||
(QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_WRITE) &&
use_sql_variables_in == TYPE_MASTER) ||
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_WRITE) &&
use_sql_variables_in == TYPE_MASTER) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_BEGIN_TRX) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_ENABLE_AUTOCOMMIT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_DISABLE_AUTOCOMMIT) ||
@ -1454,7 +1442,10 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_CREATE_TMP_TABLE) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_READ_TMP_TABLE) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_UNKNOWN)));
QUERY_IS_TYPE(qtype, QUERY_TYPE_UNKNOWN)) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_STMT) ||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_NAMED_STMT));
target = TARGET_MASTER;
}