MySQL降低wait_timeout值以减less打开连接的数量

我运行了一个相当繁忙的站点,在扫描期间,当运行netstat命令时,在我的web服务器上看到超过10.000个打开的连接到我的数据库服务器。 99%的连接处于TIME_WAIT状态。

我了解了这个mysqlvariables:今天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 ,但是我一直在读什么,只是恐怖的故事,所以我想我会远离。

如果不重新启动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会closures数据库连接,但不会通知mysqld和mysqld使连接处于打开状态,直到超时。 更糟糕的是,您可能会更频繁地看到TIME_WAIT。 明智地select你的超时值。

更新2012-11-12 10:10 EDT

警告

应用我发布的build议后,使用以下几行创build一个名为/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 ,那么需要执行两个升级步骤:

ESCALATION#1

login到有问题的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) 

ESCALATION#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_WAITs在1秒内超时。

在信贷到期时给予贷款

  • 我从这篇文章中得到了这个想法: 如何在TIME_WAIT中强制closures套接字?
  • 被接受的答案有一个TIME_WAIT存在时的graphics表示。
  • 我所喜欢的这个想法的答案就是我现在所build议的那个 。

如果您在MySQL服务器上获得了很多TIME_WAIT连接,那么这意味着MySQL服务器正在closures连接。 在这种情况下,最有可能的情况是主机或多个主机出现在阻止列表中。 您可以通过运行来清除它:

 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. 

如果你有很多的TIME_WAIT连接到你的MySQL服务器,这意味着你的代码对你的数据库运行了很多查询,并且打开/closures了每个查询的连接。

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

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

如果你不能使用MySQLi,你应该在MySQLconfiguration中使用thread_cache_size参数。