it-swarm.com.de

MySQL senkt den Wert für wait_timeout auf eine geringere Anzahl offener Verbindungen

Ich führe eine ziemlich ausgelastete Site aus und sehe während der Peek-Stunden über 10.000 offene Verbindungen zu meinem Datenbankserver auf meinem Webserver, wenn ein netstat-Befehl ausgeführt wird. 99% der Verbindungen befinden sich im Status TIME_WAIT.

Ich habe heute von dieser MySQL-Variablen erfahren: wait_timeouthttp://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout . Meins ist immer noch auf den Standardwert von 28.800 Sekunden eingestellt.

Ist das Verringern dieses Wertes sicher?

Keine meiner Anfragen dauert normalerweise mehr als eine Sekunde. Es scheint also albern, eine Verbindung 480 Minuten lang offen zu halten.

Ich habe auch davon gehört, mysql_pconnect Anstelle von mysql_connect Zu verwenden, aber ich habe nur Horrorgeschichten darüber gelesen, also denke ich, dass ich mich davon fernhalten werde.

40
Mr.Boon

Das Verringern des Werts ist ohne einen MySQL-Neustart ziemlich trivial

Angenommen, Sie möchten die Zeitüberschreitung auf 30 Sekunden senken

Fügen Sie dies zunächst zu my.cnf hinzu

[mysqld]
interactive_timeout=30
wait_timeout=30

Dann können Sie so etwas tun

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

Alle DB-Verbindungen nach dieser Zeit werden in 30 Sekunden abgelaufen

WARNUNG

Stellen Sie sicher, dass Sie explizit mysql_close verwenden. Ich vertraue Apache nicht wie die meisten Entwickler. Wenn nicht, gibt es manchmal eine Race-Bedingung, bei der Apache eine DB-Verbindung schließt, mysqld jedoch nicht informiert und mysqld diese Verbindung bis zum Timeout offen hält. Schlimmer noch, Sie sehen TIME_WAITs möglicherweise häufiger. Wählen Sie Ihre Timeout-Werte mit Bedacht aus.

UPDATE 2012-11-12 10:10 EDT

VORBEHALT

Erstellen Sie nach dem Anwenden meiner veröffentlichten Vorschläge ein Skript mit dem Namen /root/show_mysql_netstat.sh mit folgenden Zeilen:

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

Wenn Sie dies ausführen, sollten Sie Folgendes sehen:

[[email protected]*** ~]# /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

Wenn Sie immer noch viel MySQL sehen TIME_WAITs Für einen bestimmten Webserver müssen zwei Eskalationsschritte ausgeführt werden:

ESCALATION # 1

Melden Sie sich beim fehlerhaften Webserver an und starten Sie Apache wie folgt neu:

service httpd stop
sleep 30
service httpd start

Führen Sie dies gegebenenfalls auf allen Webservern durch

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

ESCALATION # 2

Sie können das Betriebssystem zwingen, TIME_WAITs für MySQL oder eine andere App wie folgt zu beenden:

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

Dadurch läuft TIME_WAITs in 1 Sekunde ab.

Kredit geben, wo Kredit fällig ist ...

75
RolandoMySQLDBA

Wenn Sie viele TIME_WAIT-Verbindungen auf dem MySQL-Server erhalten, bedeutet dies, dass der MySQL-Server die Verbindung schließt. Der wahrscheinlichste Fall in diesem Fall wäre, dass ein Host oder mehrere Hosts in eine Sperrliste aufgenommen wurden. Sie können dies löschen, indem Sie Folgendes ausführen:

mysqladmin flush-hosts

So erhalten Sie eine Liste der Anzahl der Verbindungen, die Sie pro IP-Lauf haben:

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

Sie können dies auch bestätigen, indem Sie sich an einen Ihrer Clients wenden, der Probleme beim Verbinden und Telnet mit Port 3306 hat. Daraufhin wird eine Meldung mit folgenden Informationen angezeigt:

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.
4
user2566717

Wenn Sie viele TIME_WAIT-Verbindungen zu Ihrem MySQL-Server haben, bedeutet dies, dass Ihr Code viele Abfragen für Ihre Datenbank ausführt und für jede Abfrage eine Verbindung öffnet/schließt.

In diesem Fall sollten Sie mithilfe der MySQLi-Erweiterung eine dauerhafte Verbindung zu Ihrem DB-Server herstellen.

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

Wenn Sie MySQLi nicht verwenden können, sollten Sie stattdessen den Parameter thread_cache_size in Ihrer MySQL-Konfiguration verwenden.

1
Garreth McDaid