41 votes

MySQL réduit la valeur wait_timeout pour réduire le nombre de connexions ouvertes.

Je gère un site plutôt fréquenté, et pendant les heures de pointe, je vois plus de 10 000 connexions ouvertes à mon serveur de base de données sur mon serveur web lorsque j'exécute une commande netstat. 99% des connexions sont dans l'état TIME_WAIT.

J'ai appris l'existence de cette variable mysql : wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout aujourd'hui. La mienne est toujours réglée sur la valeur par défaut de 28,800 secondes.

Est-il sûr de réduire cette valeur ?

Aucune de mes requêtes ne dépasse généralement une seconde. Il semble donc ridicule de garder une connexion ouverte pendant 480 minutes.

J'ai aussi entendu parler de l'utilisation de mysql_pconnect au lieu de mysql_connect, mais j'ai lu rien d'autre que des histoires d'horreur à son sujet, donc je pense que je vais m'en abstenir.

77voto

Adam Points 11

Abaisser la valeur est assez trivial sans redémarrer mysql

Disons que vous voulez abaisser les délais à 30 secondes

Tout d'abord, ajoutez ceci à my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Ensuite, vous pouvez faire quelque chose comme ceci

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

Toutes les connexions à la base de données après cela expireront en 30 secondes

AVERTISSEMENT

Assurez-vous d'utiliser explicitement mysql_close. Je ne fais pas confiance à Apache comme la plupart des développeurs le font. Sinon, parfois, il y a une condition de course où Apache ferme une connexion de base de données mais ne le signale pas à mysqld et mysqld maintient cette connexion ouverte jusqu'à ce qu'elle expire. Pire encore, vous pouvez voir des TIME_WAITs plus souvent. Choisissez judicieusement vos valeurs de délai d'expiration.

MISE À JOUR 2012-11-12 10:10 EDT

AVIS

Après avoir appliqué mes suggestions publiées, créez un script appelé /root/show_mysql_netstat.sh avec les lignes suivantes:

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/'

Lorsque vous exécutez ceci, vous devriez voir quelque chose comme ceci:

[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

Si vous voyez toujours beaucoup de TIME_WAITs mysql pour un serveur web donné, voici deux étapes d'escalade à prendre:

ESCALADE #1

Connectez-vous au serveur web fautif et redémarrez Apache comme suit:

service httpd stop
sleep 30
service httpd start

Si nécessaire, faites-le pour tous les serveurs web

service httpd stop (sur tous les serveurs web)
service mysql stop
sleep 120
service mysql start
service httpd start (sur tous les serveurs web)

ESCALADE #2

Vous pouvez forcer le système d'exploitation à tuer les TIME_WAITs pour mysql ou toute autre application avec ce qui suit:

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

Cela fera expirer les TIME_WAITs en 1 seconde.

Pour donner du crédit là où le crédit est dû...

4voto

Jon Points 545

Si vous obtenez beaucoup de connexions TIME_WAIT sur le serveur MySQL, cela signifie que le serveur MySQL ferme la connexion. Le cas le plus probable dans ce cas serait qu'un hôte ou plusieurs hôtes ont été placés sur une liste de blocage. Vous pouvez résoudre ce problème en exécutant :

mysqladmin flush-hosts

Pour obtenir une liste du nombre de connexions que vous avez par IP, exécutez :

netstat -nat | awk {'print $5'} | cut -d ":" -f1 | sort | uniq -c | sort -n

Vous pouvez également confirmer que cela se produit en allant sur l'un de vos clients qui a des problèmes de connexion et en vous connectant en telnet sur le port 3306. Vous verrez un message du type :

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.

1voto

Garreth McDaid Points 3269

Si vous avez beaucoup de connexions TIME_WAIT à votre serveur MySQL, cela signifie que votre code exécute beaucoup de requêtes contre votre base de données et ouvre/ferme une connexion pour chaque requête.

Dans ce cas, vous devriez utiliser une connectivité persistante à votre serveur de base de données en utilisant l'extension MySQLi.

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

Si vous ne pouvez pas utiliser MySQLi, vous devriez plutôt utiliser le paramètre thread_cache_size dans la configuration de votre MySQL.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X