mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
Fix per-hour user connection limits by making sure that the number of
connections is actually reset after an hour, and also fix (unlikely) conditions under which the per-hour query and connection limits could be exceeded. (Bug #8350) sql/sql_parse.cc: Add time_out_user_resource_limits() function to reset the user resource limits before they are checked, and add locking to check_mqh() because not doing so isn't as safe as the old comment explaining its absence said it is.
This commit is contained in:
parent
22f839cdd2
commit
71acf51498
1 changed files with 42 additions and 18 deletions
|
@ -52,7 +52,8 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
|
|||
extern "C" int gethostname(char *name, int namelen);
|
||||
#endif
|
||||
|
||||
static int check_for_max_user_connections(USER_CONN *uc);
|
||||
static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
|
||||
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
|
||||
static void decrease_user_connections(USER_CONN *uc);
|
||||
static bool check_db_used(THD *thd,TABLE_LIST *tables);
|
||||
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
|
||||
|
@ -272,7 +273,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
return -1;
|
||||
if (thd->user_connect && (thd->user_connect->user_resources.connections ||
|
||||
max_user_connections) &&
|
||||
check_for_max_user_connections(thd->user_connect))
|
||||
check_for_max_user_connections(thd, thd->user_connect))
|
||||
return -1;
|
||||
if (db && db[0])
|
||||
{
|
||||
|
@ -312,7 +313,7 @@ void init_max_user_conn(void)
|
|||
}
|
||||
|
||||
|
||||
static int check_for_max_user_connections(USER_CONN *uc)
|
||||
static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
|
||||
{
|
||||
int error=0;
|
||||
DBUG_ENTER("check_for_max_user_connections");
|
||||
|
@ -325,6 +326,7 @@ static int check_for_max_user_connections(USER_CONN *uc)
|
|||
error=1;
|
||||
goto end;
|
||||
}
|
||||
time_out_user_resource_limits(thd, uc);
|
||||
if (uc->user_resources.connections &&
|
||||
uc->user_resources.connections <= uc->conn_per_hour)
|
||||
{
|
||||
|
@ -397,14 +399,41 @@ void init_update_queries(void)
|
|||
|
||||
|
||||
/*
|
||||
Check if maximum queries per hour limit has been reached
|
||||
returns 0 if OK.
|
||||
Reset per-hour user resource limits when it has been more than
|
||||
an hour since they were last checked
|
||||
|
||||
In theory we would need a mutex in the USER_CONN structure for this to
|
||||
be 100 % safe, but as the worst scenario is that we would miss counting
|
||||
a couple of queries, this isn't critical.
|
||||
SYNOPSIS:
|
||||
time_out_user_resource_limits()
|
||||
thd Thread handler
|
||||
uc User connection details
|
||||
|
||||
NOTE:
|
||||
This assumes that the LOCK_user_conn mutex has been acquired, so it is
|
||||
safe to test and modify members of the USER_CONN structure.
|
||||
*/
|
||||
|
||||
void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
|
||||
{
|
||||
time_t check_time = thd->start_time ? thd->start_time : time(NULL);
|
||||
DBUG_ENTER("time_out_user_resource_limits");
|
||||
|
||||
/* If more than a hour since last check, reset resource checking */
|
||||
if (check_time - uc->intime >= 3600)
|
||||
{
|
||||
uc->questions=1;
|
||||
uc->updates=0;
|
||||
uc->conn_per_hour=0;
|
||||
uc->intime=check_time;
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if maximum queries per hour limit has been reached
|
||||
returns 0 if OK.
|
||||
*/
|
||||
|
||||
static bool check_mqh(THD *thd, uint check_command)
|
||||
{
|
||||
|
@ -414,16 +443,10 @@ static bool check_mqh(THD *thd, uint check_command)
|
|||
DBUG_ENTER("check_mqh");
|
||||
DBUG_ASSERT(uc != 0);
|
||||
|
||||
/* If more than a hour since last check, reset resource checking */
|
||||
if (check_time - uc->intime >= 3600)
|
||||
{
|
||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||
uc->questions=1;
|
||||
uc->updates=0;
|
||||
uc->conn_per_hour=0;
|
||||
uc->intime=check_time;
|
||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||
}
|
||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||
|
||||
time_out_user_resource_limits(thd, uc);
|
||||
|
||||
/* Check that we have not done too many questions / hour */
|
||||
if (uc->user_resources.questions &&
|
||||
uc->questions++ >= uc->user_resources.questions)
|
||||
|
@ -446,6 +469,7 @@ static bool check_mqh(THD *thd, uint check_command)
|
|||
}
|
||||
}
|
||||
end:
|
||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue