diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cd0abafc0c9..bc7d71d8eaa 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -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); }