MySQL senkt den wait_timeout-Wert, um die Anzahl der offenen Verbindungen zu verringern

39

Ich führe eine ziemlich geschäftige Site aus und sehe während weniger Stunden mehr als 10.000 offene Verbindungen zu meinem Datenbankserver auf meinem Webserver, wenn ein netstat-Befehl ausgeführt wird. 99% der Verbindungen befinden sich im TIME_WAITStatus.

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

Ist es sicher, diesen Wert zu senken?

Keine meiner Abfragen dauert in der Regel länger als eine Sekunde. Es ist also albern, eine Verbindung 480 Minuten lang offen zu halten.

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

Mr.Boon
quelle
3
Es gibt einen Unterschied zwischen Abfragen und Verbindungen. Sie müssen mindestens sicherstellen, dass die Software Ihrer Website nicht beschädigt wird, wenn eine kürzere wait_timeoutVerbindung unterbrochen wird, wenn die Software erwartet, dass sie geöffnet bleibt.
John Gardeniers

Antworten:

74

Das Verringern des Werts ist ohne einen Neustart von MySQL 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"

Danach werden alle DB-Verbindungen in 30 Sekunden beendet

WARNUNG

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

UPDATE 2012-11-12 10:10 EDT

VORBEHALT

Erstellen Sie nach dem Anwenden meiner geposteten Vorschläge ein Skript /root/show_mysql_netstat.shmit den 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, sollte Folgendes angezeigt werden:

[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

Wenn TIME_WAITsfür einen bestimmten Webserver immer noch viele MySQL-Dateien angezeigt werden, müssen Sie zwei Eskalationsschritte ausführen :

ESCALATION # 1

Melden Sie sich beim anstößigen Webserver an und starten Sie Apache wie folgt neu:

service httpd stop
sleep 30
service httpd start

Führen Sie dies bei Bedarf 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 mit den folgenden Aktionen 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.

Kredite geben, wo Kredite fällig sind ...

RolandoMySQLDBA
quelle
1
Fast 2k Views für diese und nur 2 Up Votes (einschließlich meiner, also 1), wtf ?! Das ist eine großartige Antwort. Entschuldigung, ich kann nur 1 Stimme abgeben!
Jwbensley
Ich habe diese Technik ausprobiert und hatte viele CLOSE_WAIT-Verbindungen (2622), aber keine TIME_WAIT-Verbindungen. Wie soll ich dieses Ergebnis interpretieren?
Robguinness
4

Wenn Sie auf dem MySQL-Server viele TIME_WAIT-Verbindungen erhalten, bedeutet dies, dass der MySQL-Server die Verbindung schließt. In diesem Fall ist es am wahrscheinlichsten, dass ein Host oder mehrere Hosts auf eine Sperrliste gesetzt 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 mit der Verbindung hat, und eine Telnet-Verbindung zu Port 3306 herstellen.

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.
user2566717
quelle
1

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 über die 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.

Garreth McDaid
quelle