MySQL TIME_WAIT;连接过多问题

7

当我检查网站上的mysql加载时间时,结果显示连接为TIME_WAIT。即使我在每个页面上关闭了连接。有时候网站无法加载,显示连接过多。这个问题的解决方案是什么?

非常感谢您提供任何回复或建议。


1
可能在某些流程路径中存在连接泄漏,或者在调用mysql_close之前php抛出了错误。如果您正在使用mod_php,请考虑使用持久连接http://php.net/manual/en/function.mysql-pconnect.php。 - Zimbabao
这只是一个简单的选择查询,我正在使用mysql_connect()和mysql_close()函数。我猜持久连接会创建问题,它们有时会在关闭后仍处于睡眠模式。 - Parag
3个回答

7
如果客户端连接到MySQL服务器,通常会打开本地端口,例如:
 localhost:12345 -> mysqlserver:3306

如果客户端关闭连接,客户端将得到一个TIME_WAIT。由于TCP路由,数据包可能会延迟到达临时端口。TIME_WAIT状态下的连接会丢弃这些数据包。如果没有TIME_WAIT,本地端口可能会被重新用于另一个连接,并可能收到来自以前连接的数据包。
在高频web应用程序中,每个请求都会打开一个mysql连接,预计会有大量的TIME_WAIT连接,这是正常现象。
问题可能会发生在本地端口范围过低的情况下,因此您无法再打开出站连接。通常的超时时间设置为60秒。因此,在低范围上每秒超过400个请求就可能出现问题。
检查:
要检查TIME_WAIT的数量,可以使用以下命令:
$ cat /proc/net/sockstat
sockets: used 341
TCP: inuse 12 orphan 0 tw 33365 alloc 23 mem 16
UDP: inuse 9 mem 2
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

“tw”后面的数值,本例中为33365,表示TIME_WAIT的数量。

解决方案:

a. TIME_WAIT调整(以基于Linux的操作系统为例):

缩短TIME_WAIT的超时时间:

# small values are ok, if your mysql server is in the same local network
echo 15 > /proc/sys/net/ipv4/tcp_fin_timeout

增加本地端口的端口范围:

# check, what you highest listening ports are, before setting this
echo 15000 65000 > /proc/sys/net/ipv4/ip_local_port_range

设置/proc/sys/net/ipv4/tcp_tw_recycle/proc/sys/net/ipv4/tcp_tw_reuse也可能很有趣。(但是我们尝试这些设置时经历了奇怪的副作用,最好避免使用。更多信息可以在此答案中找到)

b. 持久连接

一些编程语言和库支持持久连接。另一个解决方案可能是使用本地安装的代理,例如“ProxySQL”。这会减少新建和关闭连接的数量。


如果客户端关闭连接,你会得到一个TIME_WAIT。在这个语句中,“you”指的是谁?如果它指的是“mysqlserver”,那么这个语句是不正确的。 - sactiw

4

如果您在Mysql服务器上得到了很多TIME_WAIT连接,那么这意味着Mysql服务器正在关闭连接。在这种情况下最有可能的情况是某个主机或几个主机被列入了阻止列表。您可以通过运行以下命令来清除此问题:

mysqladmin flush-hosts

要获取每个 IP 地址的连接数列表,请运行以下命令:
 netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n

您可以通过telnet到3306端口来确认客户端连接问题。如果出现以下信息,则表示存在问题:

telnet mysqlserver 3306
Trying 192.168.1.102...
Connected to mysqlserver.
Escape character is '^]'.
sHost 'clienthost.local' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'Connection closed by foreign host.

3

正如@Zimbabao在评论中建议的那样,调试您的代码,查找可能会阻止关闭Mysql连接的潜在错误。

如果什么都不起作用,请检查您的my.cnf文件是否有一个名为wait_timeout的系统变量。如果不存在,则将其添加到[mysqld]部分并重新启动Mysql服务器。

[mysqld]
wait_timeout = 3600

这是指服务器在关闭非交互式连接之前等待活动的秒数。更多信息请参见http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_wait_timeout

根据您的需求调整该数字3600(1小时)。

希望对您有所帮助。


我曾尝试通过放置条件 <?php if(mysql_close($conn)) echo "connection closed"; ?> 进行检查。它会打印回“connection closed”。在PHP中是否有显式关闭数据库连接的方法? - Parag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接