草庐IT

MySQL 已经消失 : Connection_errors_peer_address with high numbers

coder 2023-06-12 原文

我们有 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/

    有关MySQL 已经消失 : Connection_errors_peer_address with high numbers的更多相关文章

    1. ruby-on-rails - Ruby on Rails : . 常量化 : wrong constant name error? - 2

      我正在使用这个:4.times{|i|assert_not_equal("content#{i+2}".constantize,object.first_content)}我之前声明过局部变量content1content2content3content4content5我得到的错误NameError:wrongconstantnamecontent2这个错误是什么意思?我很确定我想要content2=\ 最佳答案 你必须用一个大字母来调用ruby​​常量:Content2而不是content2。Aconstantnamestart

    2. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

      我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

    3. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

      我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

    4. 使用canal同步MySQL数据到ES - 2

      文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

    5. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

      有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

    6. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

      了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

    7. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

      我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

    8. ruby-on-rails - 尝试设置 Amazon 的 S3 存储桶 : 403 Forbidden error & setting permissions - 2

      我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不

    9. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

      我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

    10. ruby-on-rails - phusion passenger 和 ruby​​ 1.9.1 已经开始工作了吗? - 2

      我有一台生产机器和一台开发机器,都运行ubuntu8.10并且都运行最新的phusionpassenger。当我在osx上的本地开发机器上使用ruby​​1.9.1时,我想知道外面的人是否已经在使用带有ruby​​1.9.1甚至1.9.2的phusionpassenger?如果是这样,请告诉我们您的设置!此外,有没有办法在apache上使用phusionpassenger同时运行ruby​​1.8.7(ree)和1.9.1?感谢您的指点,我在任何地方都找不到任何提示... 最佳答案 是的,从某些2.2.x版本开始就正式支持它,我不记

    随机推荐