更新时间:2012-11-12 10:10 EDT

更新时间:2012-11-12 10:10 EDT

我运行一个相当繁忙的网站,在高峰时段,当我运行 netstat 命令时,我会看到我的网络服务器上有超过 10,000 个到数据库服务器的打开连接。99% 的连接处于该TIME_WAIT状态。

我了解了这个mysql变量:wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout今天。我的仍然设置为默认的 28.800 秒。

降低这个值是否安全?

我的查询通常都不会超过一秒钟。因此,让连接保持打开状态 480 分钟似乎很愚蠢。

我也听说过使用mysql_pconnect而不是mysql_connect,但是我读到的都是关于它的恐怖故事,所以我想我会远离它。

答案1

无需重启 mysql,降低该值非常简单

假设你想将超时时间缩短至 30 秒

首先,将其添加到 my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

然后你可以做这样的事情

mysql -uroot -ppassword -e"SET GLOBAL wait_timeout=30; SET GLOBAL interactive_timeout=30"

此后的所有数据库连接将在 30 秒内超时

警告

确保明确使用 mysql_close。我不像大多数开发人员那样信任 Apache。如果不信任,有时就会出现竞争条件,Apache 关闭数据库连接但不通知 mysqld,mysqld 会保持该连接打开直到超时。更糟糕的是,您可能会更频繁地看到 TIME_WAIT。请明智地选择您的超时值。

更新时间:2012-11-12 10:10 EDT

警告

应用我发布的建议后,创建一个名为/root/show_mysql_netstat.sh以下行的脚本:

netstat | grep mysql > /root/mysql_netstat.txt
cat /root/mysql_netstat.txt | awk '{print $5}' | sed 's/:/ /g' | awk '{print $2}' | sort -u > /root/mysql_netstat_iplist.txt
for IP in `cat /root/mysql_netstat_iplist.txt`
do
        ESCOUNT=`cat /root/mysql_netstat.txt | grep ESTABLISHED | awk '{print $5}' | grep -c "${IP}"`
        TWCOUNT=`cat /root/mysql_netstat.txt | grep TIME_WAIT   | awk '{print $5}' | grep -c "${IP}"`
        IPPAD=`echo "${IP}..................................." | cut -b -35`
        (( ESCOUNT += 1000000 ))
        (( TWCOUNT += 1000000 ))
        ES=`echo ${ESCOUNT} | cut -b 3-`
        TW=`echo ${TWCOUNT} | cut -b 3-`
        echo ${IPPAD} : ESTABLISHED:${ES} TIME_WAIT:${TW}
done
echo ; echo
netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n | sed 's/d)/d/'

当你运行这个程序时,你应该看到类似这样的内容:

[root@*** ~]# /root/ShowConnProfiles.sh
10.48.22.4......................... : ESTABLISHED:00002 TIME_WAIT:00008
10.48.22.8......................... : ESTABLISHED:00000 TIME_WAIT:00002
10.64.51.130....................... : ESTABLISHED:00001 TIME_WAIT:00000
10.64.51.133....................... : ESTABLISHED:00000 TIME_WAIT:00079
10.64.51.134....................... : ESTABLISHED:00002 TIME_WAIT:00001
10.64.51.17........................ : ESTABLISHED:00003 TIME_WAIT:01160
10.64.51.171....................... : ESTABLISHED:00002 TIME_WAIT:00000
10.64.51.174....................... : ESTABLISHED:00000 TIME_WAIT:00589
10.64.51.176....................... : ESTABLISHED:00001 TIME_WAIT:00570


      1 established
      1 Foreign
     11 LISTEN
     25 ESTABLISHED
   1301 TIME_WAIT

如果您仍然看到任何给定的 Web 服务器上有很多 mysql TIME_WAITs,请采取以下两个升级步骤:

升级 #1

登录到有问题的 Web 服务器并重新启动 apache,如下所示:

service httpd stop
sleep 30
service httpd start

如果有必要,对所有 Web 服务器执行此操作

service httpd stop (on all web servers)
service mysql stop
sleep 120
service mysql start
service httpd start (on all web servers)

升级 #2

您可以使用以下命令强制操作系统杀死 mysql 或任何其他应用程序的 TIME_WAIT:

SEC_TO_TIMEWAIT=1
echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_recycle
echo ${SEC_TO_TIMEWAIT} > /proc/sys/net/ipv4/tcp_tw_reuse

这将使 TIME_WAIT 在 1 秒内超时。

给予应得赞扬的人赞扬...

答案2

如果 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

如果您的 MySQL 服务器有大量 TIME_WAIT 连接,则意味着您的代码正在针对数据库运行大量查询,并且为每个查询打开/关闭一个连接。

在这种情况下,您应该使用 MySQLi 扩展与您的 DB 服务器建立持久连接。

http://php.net/manual/en/mysqli.persistconns.php

如果您不能使用 MySQLi,则应该使用 MySQL 配置中的 thread_cache_size 参数。

相关内容