gpt4 book ai didi

MySQL 已经消失 : Connection_errors_peer_address with high numbers

转载 作者:IT王子 更新时间:2023-10-29 00:34:54 26 4
gpt4 key购买 nike

我们有 MySQL 5.7 主从复制,在从服务器端,我们的应用程序监控工具(Tideways 和 PHP7.0)不时报告

MySQL has gone away.



检查 MYSQL 端:
show global status like '%Connection%';

+-----------------------------------+----------+
| Variable_name | Value |
+-----------------------------------+----------+
| Connection_errors_accept | 0 |
| Connection_errors_internal | 0 |
| Connection_errors_max_connections | 0 |
| Connection_errors_peer_address | 323 |
| Connection_errors_select | 0 |
| Connection_errors_tcpwrap | 0 |
| Connections | 55210496 |
| Max_used_connections | 387 |
| Slave_connections | 0 |
+-----------------------------------+----------+
Connection_errors_peer_address显示 323. 如何进一步调查导致双方出现此问题的原因:

MySQL has gone away





Connection_errors_peer_address



编辑:

主服务器
net_retry_count = 10 
net_read_timeout = 120
net_write_timeout = 120
skip_networking = OFF
Aborted_clients = 151650

从服务器 1
net_retry_count = 10
net_read_timeout = 30
net_write_timeout = 60
skip_networking = OFF
Aborted_clients = 3

从属服务器 2
net_retry_count = 10
net_read_timeout = 30
net_write_timeout = 60
skip_networking = OFF
Aborted_clients = 3

最佳答案

在 MySQL 5.7 中,当新的 TCP/IP 连接到达服务器时,服务器执行多项检查,在 sql/sql_connect.cc 中实现在函数中 check_connection()
其中一项检查是获取客户端连接的 IP 地址,如下所示:

static int check_connection(THD *thd)
{
...
if (!thd->m_main_security_ctx.host().length) // If TCP/IP connection
{
...
peer_rc= vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST);
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.
*/
connection_errors_peer_addr++;
my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
...
}

失败时,状态变量 connection_errors_peer_addr递增,并拒绝连接。
vio_peer_addr()vio/viosocket.c 中实现(代码简化为仅显示重要调用)
my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
size_t ip_buffer_size)
{
if (vio->localhost)
{
...
}
else
{
/* Get sockaddr by socked fd. */

err_code= mysql_socket_getpeername(vio->mysql_socket, addr, &addr_length);

if (err_code)
{
DBUG_PRINT("exit", ("getpeername() gave error: %d", socket_errno));
DBUG_RETURN(TRUE);
}

/* Normalize IP address. */

vio_get_normalized_ip(addr, addr_length,
(struct sockaddr *) &vio->remote, &vio->addrLen);

/* Get IP address & port number. */

err_code= vio_getnameinfo((struct sockaddr *) &vio->remote,
ip_buffer, ip_buffer_size,
port_buffer, NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV);

if (err_code)
{
DBUG_PRINT("exit", ("getnameinfo() gave error: %s",
gai_strerror(err_code)));
DBUG_RETURN(TRUE);
}
...
}
...
}

简而言之, vio_peer_addr() 中唯一的失败路径当拨打 mysql_socket_getpeername() 时发生或 vio_getnameinfo()失败。

mysql_socket_getpeername() 只是 getpeername() 之上的一个包装器。
man 2 getpeername手册列出了以下可能的错误:

NAME

   getpeername - get name of connected peer socket

ERRORS

   EBADF  The argument sockfd is not a valid descriptor.

EFAULT The addr argument points to memory not in a valid part of the process address space.

EINVAL addrlen is invalid (e.g., is negative).

ENOBUFS
Insufficient resources were available in the system to perform the operation.

ENOTCONN
The socket is not connected.

ENOTSOCK
The argument sockfd is a file, not a socket.


在这些错误中,只有 ENOBUFS是合理的。

至于 vio_getnameinfo() ,它只是 getnameinfo() 的一个包装器,这也是根据手册页 man 3 getnameinfo可能由于以下原因而失败:

NAME

   getnameinfo - address-to-name translation in protocol-independent manner

RETURN VALUE

   EAI_AGAIN
The name could not be resolved at this time. Try again later.

EAI_BADFLAGS
The flags argument has an invalid value.

EAI_FAIL
A nonrecoverable error occurred.

EAI_FAMILY
The address family was not recognized, or the address length was invalid for the specified family.

EAI_MEMORY
Out of memory.

EAI_NONAME
The name does not resolve for the supplied arguments. NI_NAMEREQD is set and the host's name cannot be located, or neither

hostname nor service name were requested.

   EAI_OVERFLOW
The buffer pointed to by host or serv was too small.

EAI_SYSTEM
A system error occurred. The error code can be found in errno.

The gai_strerror(3) function translates these error codes to a human readable string, suitable for error reporting.


这里可能会发生许多故障,主要是由于负载过重或网络造成的。

为了理解这段代码背后的过程,MySQL 服务器本质上在做的是一个 Reverse DNS lookup , 到:
  • 找到客户端的主机名
  • 找到这个主机名对应的IP地址
    稍后再次将此 IP 地址转换为主机名(请参阅随后对 ip_to_hostname() 的调用)。

  • 总体而言,故障占 Connection_errors_peer_address可能是由于系统负载(导致内存不足等暂时性故障)或影响 DNS 的网络问题。

    披露:我恰好是实现此的人 Connection_errors_peer_address MySQL 中的状态变量,作为在代码的这一区域具有更好的可见性/可观察性的努力的一部分。

    [编辑] 要跟进更多细节和/或指南:
  • Connection_errors_peer_address递增,根本原因不会打印在日志中。这对于故障排除来说是不幸的,但也避免了泛滥日志造成更多损害,这里有一个权衡。请记住,登录之前发生的任何事情都是非常敏感的...
  • 如果服务器真的内存不足,很可能会出现很多其他的事情,服务器很快就会宕机。通过监控mysqld的总内存使用量,并监控 uptime ,应该很容易确定故障是“仅”导致连接关闭而服务器保持正常运行,还是服务器本身发生灾难性故障。
  • 假设服务器在发生故障时保持正常运行,则更有可能的罪魁祸首是第二次调用 getnameinfo .
  • 使用 skip-name-resolve将无效,因为此检查稍后发生(请参阅 specialflag & SPECIAL_NO_RESOLVE 中的代码中的 check_connection())
  • Connection_errors_peer_address失败,注意服务器干净地返回错误 ER_BAD_HOST_ERROR到客户端,然后关闭套接字。这与突然关闭套接字(如崩溃)不同:前者应由客户端报告为 "Can't get hostname for your address" ,而后者报告为 "MySQL has gone away" .
  • 客户端连接器是否真正对待 ER_BAD_HOST_ERROR以不同方式关闭的套接字是另一回事

  • 鉴于此故障总体上似乎与 DNS 查找有关,我将检查以下项目:
  • 查看 performance_schema.host_cache 中有多少行 table 。
  • 将此与主机缓存的大小进行比较,请参阅 host_cache_size系统变量。
  • 如果主机缓存显示已满,请考虑增加其大小:这将减少总体 DNS 调用次数,减轻 DNS 压力,希望(诚然,这只是黑暗中的一个镜头)DNS 瞬时故障将消失。
  • 5500 万个连接中有 323 个确实看起来是短暂的。假设监控客户端有时确实连接正常,请检查此客户端的表 host_cache 中的行:它可能包含报告的其他故障。

  • performance_schema.host_cache文档:

    https://dev.mysql.com/doc/refman/5.7/en/host-cache-table.html

    进一步阅读:

    http://marcalff.blogspot.com/2012/04/performance-schema-nailing-host-cache.html

    [编辑 2] 基于可用的新数据:
    Aborted_clients状态变量显示服务器强行关闭的一些连接。这通常发生在 session 空闲很长时间时。

    发生这种情况的典型场景是:
  • 客户端打开一个连接,并发送一些查询
  • 然后客户端在很长一段时间内不做任何事情(大于 net_read_timeout)
  • 由于流量不足,服务器关闭 session ,并增加 Aborted_connects
  • 然后客户端发送另一个查询,看到一个关闭的连接,并报告“MySQL 已经消失”

  • 请注意,忘记彻底关闭 session 的客户端应用程序将执行 1-3,这可能是主服务器上的 Aborted_clients 的情况。此处使用 master 修复客户端应用程序的一些清理将有助于减少资源消耗,因为在超时时打开 151650 个 session 会导致死亡。

    执行 1-4 的客户端应用程序可能会导致服务器上的 Aborted_clients 和 MySQL 在客户端上消失。报告“MySQL 已经消失”的客户端应用程序很可能是这里的罪魁祸首。

    例如,如果监控应用程序每 N 秒检查一次服务器,则确保超时(此处为 30 秒和 60 秒)明显大于 N,否则服务器将终止监控 session 。

    关于MySQL 已经消失 : Connection_errors_peer_address with high numbers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52496902/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com