263 lines
8.2 KiB
Diff
263 lines
8.2 KiB
Diff
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
|
|
index ff81198..449a8d7 100644
|
|
--- a/sql/mysqld.cc
|
|
+++ b/sql/mysqld.cc
|
|
@@ -429,7 +429,7 @@ uint opt_large_page_size= 0;
|
|
uint opt_debug_sync_timeout= 0;
|
|
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
|
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
|
|
-my_bool opt_userstat= 0, opt_thread_statistics= 0;
|
|
+my_bool opt_userstat= 1, opt_thread_statistics= 0;
|
|
/*
|
|
True if there is at least one per-hour limit for some user, so we should
|
|
check them before each query (and possibly reset counters when hour is
|
|
@@ -7469,6 +7469,7 @@ static void set_server_version(void)
|
|
#endif
|
|
if (opt_log || opt_slow_log || opt_bin_log)
|
|
strmov(end, "-log"); // This may slow down system
|
|
+ end= strmov(end, "-cll");
|
|
}
|
|
|
|
|
|
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
|
|
index 1875813..63240d5 100644
|
|
--- a/sql/sql_acl.cc
|
|
+++ b/sql/sql_acl.cc
|
|
@@ -906,7 +906,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
|
{
|
|
/* Starting from 5.0.3 we have max_user_connections field */
|
|
ptr= get_field(thd->mem_root, table->field[next_field++]);
|
|
- user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
|
|
+ user.user_resource.user_conn= ptr ? atoll(ptr) : 0;
|
|
}
|
|
|
|
if (table->s->fields >= 41)
|
|
@@ -9311,10 +9311,7 @@ acl_authenticate(THD *thd, uint connect_errors, uint com_change_user_pkt_len)
|
|
}
|
|
|
|
/* Don't allow the user to connect if he has done too many queries */
|
|
- if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
|
|
- acl_user->user_resource.conn_per_hour ||
|
|
- acl_user->user_resource.user_conn ||
|
|
- global_system_variables.max_user_connections) &&
|
|
+ if (
|
|
get_or_create_user_conn(thd,
|
|
(opt_old_style_user_limits ? sctx->user : sctx->priv_user),
|
|
(opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
|
|
diff --git a/sql/sql_class.h b/sql/sql_class.h
|
|
index 6ee2821..ba8b9ac 100644
|
|
--- a/sql/sql_class.h
|
|
+++ b/sql/sql_class.h
|
|
@@ -3718,6 +3718,7 @@ inline bool add_group_to_list(THD *thd, Item *item, bool asc)
|
|
|
|
#endif /* MYSQL_SERVER */
|
|
|
|
+
|
|
/**
|
|
The meat of thd_proc_info(THD*, char*), a macro that packs the last
|
|
three calling-info parameters.
|
|
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
|
|
index 3499e0f..7eb4898 100644
|
|
--- a/sql/sql_connect.cc
|
|
+++ b/sql/sql_connect.cc
|
|
@@ -630,6 +630,10 @@ static void update_global_thread_stats_with_thread(THD* thd,
|
|
thread_stats->empty_queries+= thd->diff_empty_queries;
|
|
}
|
|
|
|
+int is_root_access(char *user_name){
|
|
+ return !strcmp(user_name,"root")||!strcmp(user_name,"mysql");
|
|
+}
|
|
+
|
|
// Updates the global stats of a user or client
|
|
void update_global_user_stats(THD* thd, bool create_user, time_t now)
|
|
{
|
|
@@ -734,6 +738,15 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
|
|
DBUG_ENTER("check_for_max_user_connections");
|
|
|
|
mysql_mutex_lock(&LOCK_user_conn);
|
|
+
|
|
+
|
|
+ if (((uc->user_resources.user_conn==(uint)~0) || (global_system_variables.max_user_connections == (uint)~0)) && !is_root_access(uc->user))
|
|
+ {
|
|
+ my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
|
|
+ error=1;
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
if (global_system_variables.max_user_connections &&
|
|
!uc->user_resources.user_conn &&
|
|
global_system_variables.max_user_connections < (uint) uc->connections)
|
|
diff --git a/sql/sql_list.cc b/sql/sql_list.cc
|
|
index 31f0ba2..20707de 100644
|
|
--- a/sql/sql_list.cc
|
|
+++ b/sql/sql_list.cc
|
|
@@ -39,6 +39,14 @@ void free_list(I_List <i_string> *list)
|
|
}
|
|
|
|
|
|
+void free_list(I_List <i_thd> *list)
|
|
+{
|
|
+ i_thd *tmp;
|
|
+ while ((tmp= list->get()))
|
|
+ delete tmp;
|
|
+}
|
|
+
|
|
+
|
|
base_list::base_list(const base_list &rhs, MEM_ROOT *mem_root)
|
|
{
|
|
if (rhs.elements)
|
|
diff --git a/sql/sql_list.h b/sql/sql_list.h
|
|
index 5cd2423..a10f4b4 100644
|
|
--- a/sql/sql_list.h
|
|
+++ b/sql/sql_list.h
|
|
@@ -562,6 +562,15 @@ public:
|
|
i_string(const char* s) : ptr(s) {}
|
|
};
|
|
|
|
+/* DB_GOVERNOR ADDITIONS */
|
|
+class i_thd: public ilink
|
|
+{
|
|
+ public:
|
|
+ THD* ptr;
|
|
+ i_thd():ptr(0) { }
|
|
+ i_thd(THD* s) : ptr(s) {}
|
|
+};
|
|
+
|
|
/* needed for linked list of two strings for replicate-rewrite-db */
|
|
class i_string_pair: public ilink
|
|
{
|
|
@@ -711,5 +720,6 @@ list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
|
|
|
|
void free_list(I_List <i_string_pair> *list);
|
|
void free_list(I_List <i_string> *list);
|
|
+void free_list(I_List <i_thd> *list);
|
|
|
|
#endif // INCLUDES_MYSQL_SQL_LIST_H
|
|
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
|
|
index 9ee6c42..ea6c42e 100644
|
|
--- a/sql/sql_parse.cc
|
|
+++ b/sql/sql_parse.cc
|
|
@@ -114,6 +114,7 @@
|
|
|
|
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
|
|
static void sql_kill(THD *thd, ulong id, bool only_kill_query);
|
|
+static void sql_kill_user(THD *thd, char *user, bool only_kill_query);
|
|
|
|
// Uses the THD to update the global stats by user name and client IP
|
|
void update_global_user_stats(THD* thd, bool create_user, time_t now);
|
|
@@ -3593,7 +3594,13 @@ end_with_restore_list:
|
|
MYF(0));
|
|
goto error;
|
|
}
|
|
- sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
|
|
+
|
|
+ if(it->type()==Item::STRING_ITEM){
|
|
+ sql_kill_user(thd, it->val_str(0)->c_ptr(), lex->type & ONLY_KILL_QUERY);
|
|
+ } else {
|
|
+ sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
|
|
+ }
|
|
+
|
|
break;
|
|
}
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
@@ -6477,6 +6484,15 @@ void sql_kill(THD *thd, ulong id, bool only_kill_query)
|
|
my_error(error, MYF(0), id);
|
|
}
|
|
|
|
+static void sql_kill_user(THD *thd, char *user, bool only_kill_query)
|
|
+{
|
|
+ uint error;
|
|
+ if (!(error= kill_user_thread(thd, user, only_kill_query)))
|
|
+ if (! thd->killed) my_ok(thd);
|
|
+ else
|
|
+ my_error(error, MYF(0), user);
|
|
+}
|
|
+
|
|
|
|
/** If pointer is not a null pointer, append filename to it. */
|
|
|
|
@@ -7382,3 +7398,58 @@ merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl)
|
|
}
|
|
return cs;
|
|
}
|
|
+
|
|
+uint kill_user_thread(THD *thd, char *user, bool only_kill_query)
|
|
+{
|
|
+ THD *tmp;
|
|
+ uint error=0;
|
|
+ DBUG_ENTER("kill_user_thread");
|
|
+ DBUG_PRINT("enter", ("id=%s only_kill=%d", !user?"nop":user, only_kill_query));
|
|
+ i_thd *thd_tmp;
|
|
+ I_List<i_thd> threads_tmp;
|
|
+ threads_tmp.empty();
|
|
+ mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
|
|
+ I_List_iterator<THD> it(threads);
|
|
+ while ((tmp=it++))
|
|
+ {
|
|
+ if (tmp->command == COM_DAEMON)
|
|
+ continue;
|
|
+ if((tmp)&&(user)&&(tmp->user_connect)&&(tmp->user_connect->user)){
|
|
+ if (!strncmp(tmp->user_connect->user,user,16))
|
|
+ {
|
|
+ mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
|
|
+ thd_tmp = new i_thd(tmp);
|
|
+ if (thd_tmp) threads_tmp.append(thd_tmp);
|
|
+ else mysql_mutex_unlock(&tmp->LOCK_thd_data);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ mysql_mutex_unlock(&LOCK_thread_count);
|
|
+
|
|
+ if(!threads_tmp.is_empty())
|
|
+ {
|
|
+ I_List_iterator<i_thd> it_tmp(threads_tmp);
|
|
+ while ((thd_tmp=it_tmp++)){
|
|
+ tmp=thd_tmp->ptr;
|
|
+
|
|
+ if ((tmp)&&(thd->security_ctx->master_access & SUPER_ACL) ||
|
|
+ thd->security_ctx->user_matches(tmp->security_ctx))
|
|
+ {
|
|
+ tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
|
|
+ error=0;
|
|
+ }
|
|
+ else
|
|
+ error=ER_KILL_DENIED_ERROR;
|
|
+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
|
|
+ }
|
|
+ free_list(&threads_tmp);
|
|
+ threads_tmp.empty();
|
|
+ }
|
|
+ DBUG_PRINT("exit", ("%d", error));
|
|
+ DBUG_RETURN(error);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
|
|
index 9eea074..7262d4c 100644
|
|
--- a/sql/sql_parse.h
|
|
+++ b/sql/sql_parse.h
|
|
@@ -50,6 +50,7 @@ bool parse_sql(THD *thd,
|
|
Parser_state *parser_state,
|
|
Object_creation_ctx *creation_ctx);
|
|
|
|
+uint kill_user_thread(THD *thd, char *user, bool only_kill_query);
|
|
uint kill_one_thread(THD *thd, ulong id, bool only_kill_query);
|
|
|
|
void free_items(Item *item);
|
|
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
|
|
index 5ff927d..692ceff 100644
|
|
--- a/sql/sys_vars.cc
|
|
+++ b/sql/sys_vars.cc
|
|
@@ -1603,7 +1603,7 @@ static Sys_var_mybool Sys_userstat(
|
|
"userstat",
|
|
"Control USER_STATISTICS, CLIENT_STATISTICS, THREAD_STATISTICS, "
|
|
"INDEX_STATISTICS and TABLE_STATISTICS running",
|
|
- GLOBAL_VAR(opt_userstat), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
|
|
+ GLOBAL_VAR(opt_userstat), CMD_LINE(OPT_ARG), DEFAULT(TRUE));
|
|
|
|
static Sys_var_mybool Sys_thread_statistics(
|
|
"thread_statistics",
|