MySQL将wait_timeout值降低到较低的打开连接数


39

我运行了一个非常繁忙的站点,在偷看时间内,运行netstat命令时,我的Web服务器上的数据库服务器有超过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,但是我一直在阅读关于它的恐怖故事,所以我认为我会避免使用它。


3
查询和连接之间有区别。您至少需要确保您的网站软件不会中断,如果较短的时间wait_timeout导致该软件期望它保持打开状态时,连接会关闭。
John Gardeniers '02

Answers:


74

降低该值非常简单,无需重启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

如果TIME_WAITs对于任何给定的Web服务器仍然看到很多mysql ,请执行以下两个升级步骤:

升级#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秒内超时。

在应得的信用额上给予信用...


1
为此,将近2k次观看,只有2票(包括我的,所以1票),wtf ?! 这是一个很好的答案。抱歉,我只能投1票!
jwbensley 2012年

我尝试了这种技术,但我有很多CLOSE_WAIT连接(2622),但没有TIME_WAIT连接。我应该如何解释这个结果?
robguinness

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.

1

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

在这种情况下,您应该使用MySQLi扩展对数据库服务器的持久连接。

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

如果无法使用MySQLi,则应在MySQL配置中使用thread_cache_size参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.