如何防止 MySQL 中出现如此多的中止客户端(增加 aborted_clients 计数)?

JYe*_*ton 5 mysql

我在 Ubuntu 服务器上运行 MySQL 5.6.14 并注意到错误日志不断填充:

到 db 的连接 17201 中止:'somedb' 用户:'sdb' 主机:'xxxx'(读取通信数据包超时)

(这些情况每分钟大约发生 10 次。在服务器正常运行时间仅 24 小时后,计数器最多可达 13,000。)

我们可能有二十或三十个 Windows 客户端程序实例,它们通过连接器/NET (6.2.2.0) 使用 .NET 框架连接到数据库,并且我确保每次它创建连接时 (MySqlConnection.Open( )) 它也被正确关闭 (MySqlConnection.Close())。

max_allowed_packet根据网络研究调整了各种超时、和其他设置,但这些似乎仍然存在。

以下是(我认为是)相关设置:

connect_timeout = 20
wait_timeout = 60
net_read_timeout = 60
net_write_timeout = 60
max_allowed_packet = 33554432 // 32M
Run Code Online (Sandbox Code Playgroud)

我能做些什么来阻止这些事件不断发生?

JYe*_*ton 6

事实证明,MySQL 连接器/NET 行为是问题的核心。

默认情况下,它会自动创建一个连接池并在必要时重用它们。当您调用.Open()连接时,可能会重新创建连接,或者您可能会获得一个已经存在但处于空闲状态 (SLEEP) 的连接。当您调用.Close()连接时,将返回到池中。

还有很多其他问题和答案涉及“我应该为每个动作创建新连接还是应该重用相同的连接?”的概念。- 连接器/NET 会为您处理这些问题,因此您应该创建、打开和关闭它们。池化是在幕后自动进行的。

这里有一点很重要:默认情况下,Connector/NET 可以创建的最大连接数是 100。如果您有很多客户端在执行并发查询或其他什么,则服务器可能会超出其max_connections限制。如有必要,您可以通过在其连接字符串选项中指定最大池大小选项来限制连接器/NET 创建的连接数

那么,为什么所有中止的客户?连接器/NET 管理的池中的连接保持打开的时间比服务器的更长wait_timeout,因此服务器关闭它们并将它们视为客户端中止。

他们开放多久?好吧,这取决于您的连接器/NET 版本,但是:

从 MySQL Connector/Net 6.2 开始,有一个后台作业每三分钟运行一次,并从池中删除闲置(未使用)超过三分钟的连接。池清理释放客户端和服务器端的资源。这是因为在客户端每个连接都使用一个套接字,而在服务器端每个连接都使用一个套接字和一个线程。

在此更改之前,连接从未从池中删除,并且池始终包含打开连接的峰值数量。例如,在 1000 个并发数据库连接时达到峰值的 Web 应用程序将在服务器上消耗 1000 个线程和 1000 个打开的套接字,而不会从连接池中释放这些资源。请注意,如果池中的连接数小于或等于 Min Pool Size 连接字符串参数设置的值,则无论多旧的连接都不会关闭。

--参考

由于您使用的是 6.2.2.0 版,因此它们会在客户端在三分钟后关闭,这不会导致服务器将其视为警告。

解决办法:增加wait_timeout五分钟左右。注意:观察到服务器的连接数以确保连接能够睡眠更长时间不会导致连接总数接近max_connections