Added configurable multistatement behavior
Whether all queries should be routed to the master after a multistatement query is executed can now be controlled with the `strict_multi_stmt` option. When the option is disabled queries executed after a multistatement query will be routed normally.
This commit is contained in:
@ -32,6 +32,12 @@ In master-slave replication cluster also read-only queries are routed to master
|
|||||||
|
|
||||||
* statement includes a stored procedure, or an UDF call
|
* statement includes a stored procedure, or an UDF call
|
||||||
|
|
||||||
|
If the client enables and executes multi-statements, they will be routed to
|
||||||
|
the master. All future queries will also be routed to the master to guarantee
|
||||||
|
a consistent session state after the multi-statement query. This behavior can
|
||||||
|
be controlled with the `strict_multi_stmt` router option. For more information,
|
||||||
|
read the [ReadWriteSplit](../Routers/ReadWriteSplit.md) router documentation.
|
||||||
|
|
||||||
### Limitations in client session handling
|
### Limitations in client session handling
|
||||||
|
|
||||||
Some of the queries that client sends are routed to all backends instead of sending them just to one of server. These queries include `USE <db name>` and `SET autocommit=0` among many others. Readwritesplit sends a copy of these queries to each backend server and forwards the master's reply to the client. Below is a list of MySQL commands which are classified as session commands :
|
Some of the queries that client sends are routed to all backends instead of sending them just to one of server. These queries include `USE <db name>` and `SET autocommit=0` among many others. Readwritesplit sends a copy of these queries to each backend server and forwards the master's reply to the client. Below is a list of MySQL commands which are classified as session commands :
|
||||||
|
@ -143,6 +143,22 @@ disable_sescmd_history=true
|
|||||||
master_accept_reads=true
|
master_accept_reads=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `strict_multi_stmt`
|
||||||
|
|
||||||
|
When a client executes a multistatement query, all queries after that will be routed to
|
||||||
|
the master to guarantee a consistent session state. This behavior can be controlled with
|
||||||
|
the **`strict_multi_stmt`** router option. This option is enabled by default.
|
||||||
|
|
||||||
|
If set to false, queries are routed normally after a multistatement query. **Warning**, this
|
||||||
|
can cause false data to be read from the slaves if the multistatement query modifies
|
||||||
|
the session state. Only disable the strict mode if you know that no changes to the session
|
||||||
|
state will be made inside the multistatement queries.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Disable strict multistatement mode
|
||||||
|
strict_multi_stmt=false
|
||||||
|
```
|
||||||
|
|
||||||
## Routing hints
|
## Routing hints
|
||||||
|
|
||||||
The readwritesplit router supports routing hints. For a detailed guide on hint syntax and functionality, please read [this](../Reference/Hint-Syntax.md) document.
|
The readwritesplit router supports routing hints. For a detailed guide on hint syntax and functionality, please read [this](../Reference/Hint-Syntax.md) document.
|
||||||
|
@ -252,6 +252,8 @@ typedef struct rwsplit_config_st
|
|||||||
int rw_max_sescmd_history_size;
|
int rw_max_sescmd_history_size;
|
||||||
bool rw_disable_sescmd_hist;
|
bool rw_disable_sescmd_hist;
|
||||||
bool rw_master_reads; /*< Use master for reads */
|
bool rw_master_reads; /*< Use master for reads */
|
||||||
|
bool rw_strict_multi_stmt; /*< Force non-multistatement queries to be routed
|
||||||
|
* to the master after a multistatement query. */
|
||||||
} rwsplit_config_t;
|
} rwsplit_config_t;
|
||||||
|
|
||||||
#if defined(PREP_STMT_CACHING)
|
#if defined(PREP_STMT_CACHING)
|
||||||
|
@ -697,6 +697,9 @@ createInstance(SERVICE *service, char **options)
|
|||||||
router->bitmask = 0;
|
router->bitmask = 0;
|
||||||
router->bitvalue = 0;
|
router->bitvalue = 0;
|
||||||
|
|
||||||
|
/** Enable strict multistatement handling by default */
|
||||||
|
router->rwsplit_config.rw_strict_multi_stmt = true;
|
||||||
|
|
||||||
/** Call this before refreshInstance */
|
/** Call this before refreshInstance */
|
||||||
if (options)
|
if (options)
|
||||||
{
|
{
|
||||||
@ -1384,7 +1387,7 @@ static route_target_t get_route_target(ROUTER_CLIENT_SES *rses,
|
|||||||
target_t use_sql_variables_in = rses->rses_config.rw_use_sql_variables_in;
|
target_t use_sql_variables_in = rses->rses_config.rw_use_sql_variables_in;
|
||||||
route_target_t target = TARGET_UNDEFINED;
|
route_target_t target = TARGET_UNDEFINED;
|
||||||
|
|
||||||
if (rses->forced_node == rses->rses_master_ref)
|
if (rses->rses_config.rw_strict_multi_stmt && rses->forced_node == rses->rses_master_ref)
|
||||||
{
|
{
|
||||||
target = TARGET_MASTER;
|
target = TARGET_MASTER;
|
||||||
}
|
}
|
||||||
@ -4640,6 +4643,10 @@ static void rwsplit_process_router_options(
|
|||||||
{
|
{
|
||||||
router->rwsplit_config.rw_master_reads = config_truth_value(value);
|
router->rwsplit_config.rw_master_reads = config_truth_value(value);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(options[i],"strict_multi_stmt") == 0)
|
||||||
|
{
|
||||||
|
router->rwsplit_config.rw_strict_multi_stmt = config_truth_value(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /*< for */
|
} /*< for */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user