diff --git a/Documentation/Getting-Started/Configuration-Guide.md b/Documentation/Getting-Started/Configuration-Guide.md index 726d02a25..d232a93b6 100644 --- a/Documentation/Getting-Started/Configuration-Guide.md +++ b/Documentation/Getting-Started/Configuration-Guide.md @@ -798,6 +798,12 @@ When value all is used, queries reading session variables can be routed to any a In above-mentioned case the user-defined variable would only be updated in the master where query would be routed due to `INSERT` statement. +`max_sescmd_history` sets a limit on how many session commands each session can execute before the connection is closed. The default is an unlimited number of session commands. + + max_sescmd_history=1500 + +When a limitation is set, it effectively creates a cap on the session's memory consumption. This might be useful if connection pooling is used and the sessions use large amounts of session commands. + An example of Read/Write Split router configuration : ``` diff --git a/server/MaxScale_template.cnf b/server/MaxScale_template.cnf index 90d994520..feec5695d 100644 --- a/server/MaxScale_template.cnf +++ b/server/MaxScale_template.cnf @@ -182,6 +182,12 @@ replace=select # router_options= # slave_selection_criteria=[LEAST_CURRENT_OPERATIONS|LEAST_BEHIND_MASTER] # +# router_options=max_sescmd_history specifies a limit on the number of 'session commands' +# a single session can execute. Please refer to the configuration guide for more details - optional. +# +# router_options= +# max_sescmd_history=2500 +# # max_slave_connections specifies how many slaves a router session can # connect to - optional. # diff --git a/server/modules/include/readwritesplit.h b/server/modules/include/readwritesplit.h index 929b66b0b..c79373533 100644 --- a/server/modules/include/readwritesplit.h +++ b/server/modules/include/readwritesplit.h @@ -246,7 +246,8 @@ typedef struct rwsplit_config_st { int rw_max_slave_conn_count; select_criteria_t rw_slave_select_criteria; int rw_max_slave_replication_lag; - target_t rw_use_sql_variables_in; + target_t rw_use_sql_variables_in; + int rw_max_sescmd_history_size; } rwsplit_config_t; @@ -285,6 +286,7 @@ struct router_client_session { backend_ref_t* rses_backend_ref; /*< Pointer to backend reference array */ rwsplit_config_t rses_config; /*< copied config info from router instance */ int rses_nbackends; + int rses_nsescmd; /*< Number of executed session commands */ int rses_capabilities; /*< input type, for example */ bool rses_autocommit_enabled; bool rses_transaction_active; diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 694d17f1b..d3c959c5b 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -4347,6 +4347,19 @@ static bool route_session_write( goto return_succp; } + + if(router_cli_ses->rses_config.rw_max_sescmd_history_size > 0 && + router_cli_ses->rses_nsescmd >= router_cli_ses->rses_config.rw_max_sescmd_history_size) + { + LOGIF(LT, (skygw_log_write( + LOGFILE_TRACE, + "Router session exceeded session command history limit. " + "Closing router session. <"))); + router_cli_ses->rses_closed = true; + rses_end_locked_router_action(router_cli_ses); + goto return_succp; + } + /** * Additional reference is created to querybuf to * prevent it from being released before properties @@ -4418,6 +4431,9 @@ static bool route_session_write( } } } + + atomic_add(&router_cli_ses->rses_nsescmd,1); + /** Unlock router session */ rses_end_locked_router_action(router_cli_ses); @@ -4517,6 +4533,10 @@ static void rwsplit_process_router_options( router->rwsplit_config.rw_slave_select_criteria = c; } } + else if(strcmp(options[i], "max_sescmd_history") == 0) + { + router->rwsplit_config.rw_max_sescmd_history_size = atoi(value); + } } } /*< for */ }