mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
WL#1339 "Add per account max_user_connections limit (maximum number
of concurrent connections for the same account)" Added support of account specific max_user_connections limit. Made all user limits to be counted per account instead of the old behavior, which was per user/host accounting. Added option which enables the old behavior. Added testing of these to the test suite. (After review version). client/mysqltest.c: Extended mysqltest to be able to handle connect() statements for which error is expected. - Added replace_dynstr_append() utility function. - added connect_n_handle_errors() function which connects with server without retries and handles errors as if "connect" was usual statement. - do_connect(): added ability to handle connects which are expected to return an error. - run_query_normal(): Moved all expected-error-handling code to separate normal_handle_error()/normal_handle_no_error() functions to be able to reuse them in connect_n_handle_errors(). mysql-test/r/grant.result: Fixed test results since one more column to mysql.user was added. mysql-test/r/system_mysql_db.result: Fixed test results since one more column to mysql.user was added. scripts/mysql_create_system_tables.sh: Added max_user_connections column to mysql.user table for storing new maximal concurrent connections per account limit. scripts/mysql_fix_privilege_tables.sql: Added max_user_connections column to mysql.user table for storing new maximal concurrent connections per account limit. sql/lex.h: Added MAX_USER_CONNECTIONS symbol used for specifying maximum number of concurrent connections per account. sql/mysql_priv.h: Added declaration of opt_old_style_user_limits variable which is defined in sql/mysqld.cc used in sql/sql_parse.cc. sql/mysqld.cc: Added "old-style-user-limits" option which forces user limits to behave in old way i.e. to be counted per user/host pair instead of per account. Added comment describing mqh_used variable. sql/set_var.cc: Added sys_var_max_user_conn class which implements support for the new behavior of max_user_connections variable. Now the global instance of this variable holds default maximum number of concurrent connections per account (as it was before) and the session instance gives read-only access to account-specific version of this limit. sql/set_var.h: Added sys_var_max_user_conn class which implements support for the new behavior of max_user_connections variable. Now the global instance of this variable holds default maximum number of concurrent connections per account (as it was before) and the session instance gives read-only access to account-specific version of this limit. sql/sql_acl.cc: Added support for account-specific MAX_USER_CONNECTIONS limit. Tweaked USER_RESOURCES and their handling for better clarity. sql/sql_parse.cc: Added support for account-specific MAX_USER_CONNECTIONS (maximum number of concurrent connections per account) limit. Changed default behavior of all user limits to be per account instead of per user+host. '--old-style-user-limits' option was added to enable the old behavior. Made maximum number of connections per hour to be independant on the value of global max_user_connections variable. sql/sql_yacc.yy: Added support of new MAX_USER_CONNECTIONS limit to grammar. Renamed USER_RESOURCES::connections member to conn_per_hour and bits member to specified_limits. Also enum is used instead of naked numbers when we are working with specified_limits. sql/structs.h: USER_RESOURCES struct: - Added user_conn member to store the maximum number of concurrent connections for an account. Renamed connections member to conn_per_hour for less ambiguity. - Renamed member 'bits' to 'specified_limits' for the sake of clarity. The member was used as a flag indicating which limits were mentioned in GRANT clause. - Added comments. USER_CONN struct: - Removed unused user_len member. - Added comments.
This commit is contained in:
@ -172,14 +172,10 @@ static int get_or_create_user_conn(THD *thd, const char *user,
|
||||
}
|
||||
uc->user=(char*) (uc+1);
|
||||
memcpy(uc->user,temp_user,temp_len+1);
|
||||
uc->user_len= user_len;
|
||||
uc->host=uc->user + uc->user_len + 1;
|
||||
uc->host= uc->user + user_len + 1;
|
||||
uc->len = temp_len;
|
||||
uc->connections = 1;
|
||||
uc->questions=uc->updates=uc->conn_per_hour=0;
|
||||
uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
|
||||
uc->user_resources=*mqh;
|
||||
if (max_user_connections && mqh->connections > max_user_connections)
|
||||
uc->user_resources.connections = max_user_connections;
|
||||
uc->intime=thd->thr_create_time;
|
||||
if (my_hash_insert(&hash_user_connections, (byte*) uc))
|
||||
{
|
||||
@ -352,12 +348,16 @@ int check_user(THD *thd, enum enum_server_command command,
|
||||
thd->db_access=0;
|
||||
|
||||
/* Don't allow user to connect if he has done too many queries */
|
||||
if ((ur.questions || ur.updates || ur.connections ||
|
||||
if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
|
||||
max_user_connections) &&
|
||||
get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
|
||||
get_or_create_user_conn(thd,
|
||||
opt_old_style_user_limits ? thd->user : thd->priv_user,
|
||||
opt_old_style_user_limits ? thd->host_or_ip : thd->priv_host,
|
||||
&ur))
|
||||
DBUG_RETURN(-1);
|
||||
if (thd->user_connect &&
|
||||
(thd->user_connect->user_resources.connections ||
|
||||
(thd->user_connect->user_resources.conn_per_hour ||
|
||||
thd->user_connect->user_resources.user_conn ||
|
||||
max_user_connections) &&
|
||||
check_for_max_user_connections(thd, thd->user_connect))
|
||||
DBUG_RETURN(-1);
|
||||
@ -448,19 +448,28 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
|
||||
DBUG_ENTER("check_for_max_user_connections");
|
||||
|
||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||
if (max_user_connections &&
|
||||
if (max_user_connections && !uc->user_resources.user_conn &&
|
||||
max_user_connections < (uint) uc->connections)
|
||||
{
|
||||
net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
|
||||
error=1;
|
||||
goto end;
|
||||
}
|
||||
if (uc->user_resources.connections &&
|
||||
uc->user_resources.connections <= uc->conn_per_hour)
|
||||
if (uc->user_resources.user_conn &&
|
||||
uc->user_resources.user_conn < uc->connections)
|
||||
{
|
||||
net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
|
||||
"max_user_connections",
|
||||
(long) uc->user_resources.user_conn);
|
||||
error= 1;
|
||||
goto end;
|
||||
}
|
||||
if (uc->user_resources.conn_per_hour &&
|
||||
uc->user_resources.conn_per_hour <= uc->conn_per_hour)
|
||||
{
|
||||
net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
|
||||
"max_connections",
|
||||
(long) uc->user_resources.connections);
|
||||
(long) uc->user_resources.conn_per_hour);
|
||||
error=1;
|
||||
goto end;
|
||||
}
|
||||
@ -3507,7 +3516,7 @@ create_error:
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if (mqh_used && lex->sql_command == SQLCOM_GRANT)
|
||||
if (lex->sql_command == SQLCOM_GRANT)
|
||||
{
|
||||
List_iterator <LEX_USER> str_list(lex->users_list);
|
||||
LEX_USER *user;
|
||||
@ -5682,8 +5691,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
||||
{
|
||||
acl_reload(thd);
|
||||
grant_reload(thd);
|
||||
if (mqh_used)
|
||||
reset_mqh(thd,(LEX_USER *) NULL,TRUE);
|
||||
reset_mqh(thd, (LEX_USER *) NULL, TRUE);
|
||||
}
|
||||
#endif
|
||||
if (options & REFRESH_LOG)
|
||||
|
Reference in New Issue
Block a user