我们有MySQL5.7主-从复制,在从服务器端,我们的应用程序监控工具(tideways和php7.0)可能会不时报告
mysql已经消失了。
检查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已经消失了
和
连接\u错误\u对等\u地址
编辑:
主服务器
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
1条答案
按热度按时间rdrgkggo1#
在MySQL5.7中,当一个新的tcp/ip连接到达服务器时,服务器会执行一些检查,在中实现
sql/sql_connect.cc
在功能上check_connection()
这些检查之一是获取客户端连接的ip地址,如下所示:失败时,状态变量
connection_errors_peer_addr
则拒绝连接。vio_peer_addr()
在中实现vio/viosocket.c
(代码简化为仅显示重要调用)简言之,唯一的失败途径
vio_peer_addr()
当呼叫mysql_socket_getpeername()
或者vio_getnameinfo()
失败。mysql\u socket\u getpeername()只是getpeername()之上的一个 Package 器。
这个
man 2 getpeername
手册列出了以下可能的错误:名称
错误
在这些错误中,只有
ENOBUFS
是有道理的。至于
vio_getnameinfo()
,它只是getnameinfo()上的一个 Package ,根据手册页man 3 getnameinfo
可能由于以下原因而失败:名称
返回值
请求了主机名或服务名。
这里可能发生许多故障,基本上是由于重载或网络。
为了理解这段代码背后的过程,mysql服务器实际上在做一个反向dns查找,以:
查找客户端的主机名
找到与此主机名对应的ip地址,以便稍后再次将此ip地址转换为主机名(请参阅下面的对ip\ to\ U hostname()的调用)。
总的来说,失败是由
Connection_errors_peer_address
可能是由于系统负载(导致内存不足等瞬时故障)或影响dns的网络问题。披露:我恰好是实施这个计划的人
Connection_errors_peer_address
mysql中的status变量,作为在代码的这个区域中具有更好的可见性/可观察性的努力的一部分。[编辑]跟进更多细节和/或指南:
什么时候
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\ U缓存中的行:它可能包含报告的其他故障。
表
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
status变量显示服务器强制关闭的一些连接。这通常发生在会话空闲很长时间的情况下。发生这种情况的典型情况是:
客户端打开一个连接,并发送一些查询
然后,客户端在一段较长的时间内不执行任何操作(大于net\u read\u超时)
由于缺少通信量,服务器将关闭会话,然后重新连接
然后客户端发送另一个查询,看到一个关闭的连接,并报告“mysql已经消失”
请注意,忘记干净地关闭会话的客户机应用程序将执行1-3,这可能是主服务器上中止的\u客户机的情况。在这里进行一些清理来修复使用主服务器的客户端应用程序,这将有助于减少资源消耗,因为让151650个会话在超时时关闭是有代价的。
执行1-4的客户机应用程序可能会导致服务器上的\u客户机中止,而客户机上的mysql已经消失。报告“mysql已经消失”的客户端应用程序很可能是罪魁祸首。
如果一个监视应用程序每n秒检查一次服务器,那么请确保超时时间(这里是30秒和60秒)明显大于n,否则服务器将终止监视会话。