1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

MDEV-4058

MySQL 5.6.10 performance schema: merge of host_cache table
This commit is contained in:
unknown
2013-06-27 12:51:34 +03:00
parent 68262ba648
commit ecbf36a914
13 changed files with 1076 additions and 251 deletions

View File

@ -124,6 +124,7 @@ end:
int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error= 1;
Host_errors errors;
DBUG_ENTER("check_for_max_user_connections");
mysql_mutex_lock(&LOCK_user_conn);
@ -135,6 +136,8 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
!(thd->security_ctx->master_access & SUPER_ACL))
{
my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
error=1;
errors.m_max_user_connection= 1;
goto end;
}
time_out_user_resource_limits(thd, uc);
@ -144,6 +147,8 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
"max_user_connections",
(long) uc->user_resources.user_conn);
error= 1;
errors.m_max_user_connection= 1;
goto end;
}
if (uc->user_resources.conn_per_hour &&
@ -152,6 +157,8 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc)
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
"max_connections_per_hour",
(long) uc->user_resources.conn_per_hour);
error=1;
errors.m_max_user_connection_per_hour= 1;
goto end;
}
uc->conn_per_hour++;
@ -169,6 +176,10 @@ end:
thd->user_connect= NULL;
}
mysql_mutex_unlock(&LOCK_user_conn);
if (error)
{
inc_host_errors(thd->main_security_ctx.ip, &errors);
}
DBUG_RETURN(error);
}
@ -867,7 +878,10 @@ bool init_new_connection_handler_thread()
{
pthread_detach_this_thread();
if (my_thread_init())
{
statistic_increment(connection_errors_internal, &LOCK_status);
return 1;
}
return 0;
}
@ -887,6 +901,7 @@ bool init_new_connection_handler_thread()
static int check_connection(THD *thd)
{
uint connect_errors= 0;
int auth_rc;
NET *net= &thd->net;
DBUG_PRINT("info",
@ -898,37 +913,103 @@ static int check_connection(THD *thd)
if (!thd->main_security_ctx.host) // If TCP/IP connection
{
my_bool peer_rc;
char ip[NI_MAXHOST];
if (vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST))
{
my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
/* BEGIN : DEBUG */
DBUG_EXECUTE_IF("addr_fake_ipv4",
peer_rc= vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST);
/*
===========================================================================
DEBUG code only (begin)
Simulate various output from vio_peer_addr().
===========================================================================
*/
DBUG_EXECUTE_IF("vio_peer_addr_error",
{
peer_rc= 1;
}
);
DBUG_EXECUTE_IF("vio_peer_addr_fake_ipv4",
{
struct sockaddr *sa= (sockaddr *) &net->vio->remote;
sa->sa_family= AF_INET;
struct in_addr *ip4= &((struct sockaddr_in *)sa)->sin_addr;
/* See RFC 5737, 192.0.2.0/23 is reserved */
struct in_addr *ip4= &((struct sockaddr_in *) sa)->sin_addr;
/* See RFC 5737, 192.0.2.0/24 is reserved. */
const char* fake= "192.0.2.4";
ip4->s_addr= inet_addr(fake);
strcpy(ip, fake);
};);
/* END : DEBUG */
peer_rc= 0;
}
);
#ifdef HAVE_IPV6
DBUG_EXECUTE_IF("vio_peer_addr_fake_ipv6",
{
struct sockaddr_in6 *sa= (sockaddr_in6 *) &net->vio->remote;
sa->sin6_family= AF_INET6;
struct in6_addr *ip6= & sa->sin6_addr;
/* See RFC 3849, ipv6 2001:DB8::/32 is reserved. */
const char* fake= "2001:db8::6:6";
/* inet_pton(AF_INET6, fake, ip6); not available on Windows XP. */
ip6->s6_addr[ 0] = 0x20;
ip6->s6_addr[ 1] = 0x01;
ip6->s6_addr[ 2] = 0x0d;
ip6->s6_addr[ 3] = 0xb8;
ip6->s6_addr[ 4] = 0x00;
ip6->s6_addr[ 5] = 0x00;
ip6->s6_addr[ 6] = 0x00;
ip6->s6_addr[ 7] = 0x00;
ip6->s6_addr[ 8] = 0x00;
ip6->s6_addr[ 9] = 0x00;
ip6->s6_addr[10] = 0x00;
ip6->s6_addr[11] = 0x00;
ip6->s6_addr[12] = 0x00;
ip6->s6_addr[13] = 0x06;
ip6->s6_addr[14] = 0x00;
ip6->s6_addr[15] = 0x06;
strcpy(ip, fake);
peer_rc= 0;
}
);
#endif /* HAVE_IPV6 */
/*
===========================================================================
DEBUG code only (end)
===========================================================================
*/
if (peer_rc)
{
/*
Since we can not even get the peer IP address,
there is nothing to show in the host_cache,
so increment the global status variable for peer address errors.
*/
statistic_increment(connection_errors_peer_addr, &LOCK_status);
my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
{
/*
No error accounting per IP in host_cache,
this is treated as a global server OOM error.
TODO: remove the need for my_strdup.
*/
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by my_strdup(). */
}
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
if (!(specialflag & SPECIAL_NO_RESOLVE))
{
if (ip_to_hostname(&net->vio->remote, thd->main_security_ctx.ip,
&thd->main_security_ctx.host, &connect_errors))
{
my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
int rc;
rc= ip_to_hostname(&net->vio->remote,
thd->main_security_ctx.ip,
&thd->main_security_ctx.host,
&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
if (thd->main_security_ctx.host)
@ -938,8 +1019,10 @@ static int check_connection(THD *thd)
HOSTNAME_LENGTH)]= 0;
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
}
if (connect_errors > max_connect_errors)
if (rc == RC_BLOCKED_HOST)
{
/* HOST_CACHE stats updated by ip_to_hostname(). */
my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
@ -951,6 +1034,7 @@ static int check_connection(THD *thd)
thd->main_security_ctx.ip : "unknown ip")));
if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
{
/* HOST_CACHE stats updated by acl_check_host(). */
my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
thd->main_security_ctx.host_or_ip);
return 1;
@ -967,9 +1051,34 @@ static int check_connection(THD *thd)
vio_keepalive(net->vio, TRUE);
if (thd->packet.alloc(thd->variables.net_buffer_length))
{
/*
Important note:
net_buffer_length is a SESSION variable,
so it may be tempting to account OOM conditions per IP in the HOST_CACHE,
in case some clients are more demanding than others ...
However, this session variable is *not* initialized with a per client
value during the initial connection, it is initialized from the
GLOBAL net_buffer_length variable from the server.
Hence, there is no reason to account on OOM conditions per client IP,
we count failures in the global server status instead.
*/
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by alloc(). */
}
return acl_authenticate(thd, connect_errors, 0);
auth_rc= acl_authenticate(thd, connect_errors, 0);
if (auth_rc == 0 && connect_errors != 0)
{
/*
A client connection from this IP was successful,
after some previous failures.
Reset the connection error counter.
*/
reset_host_connect_errors(thd->main_security_ctx.ip);
}
return auth_rc;
}
@ -1118,6 +1227,7 @@ void prepare_new_connection_state(THD* thd)
execute_init_command(thd, &opt_init_connect, &LOCK_sys_init_connect);
if (thd->is_error())
{
Host_errors errors;
thd->killed= KILL_CONNECTION;
thd->print_aborted_warning(0, "init_connect command failed");
sql_print_warning("%s", thd->get_stmt_da()->message());
@ -1145,6 +1255,8 @@ void prepare_new_connection_state(THD* thd)
thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
thd->protocol->end_statement();
thd->killed = KILL_CONNECTION;
errors.m_init_connect= 1;
inc_host_errors(thd->main_security_ctx.ip, &errors);
return;
}