Frage MySQL senkt den wait_timeout-Wert auf eine geringere Anzahl offener Verbindungen


Ich betreibe eine ziemlich gut besuchte Seite, und während der kurzen Zeit sehe ich mehr als 10.000 offene Verbindungen zu meinem Datenbankserver auf meinem Webserver, wenn ich einen netstat-Befehl ausführe. 99% der Verbindungen sind in der TIME_WAIT Zustand.

Ich habe über diese mysql-Variable erfahren: wait_timeout  http://dev.mysql.com/doc/refman/5.1/de/server-system-variables.html#sysvar_wait_timeout heute. Meine ist immer noch auf die Standard 28.800 Sekunden eingestellt.

Verringert sich dieser Wert?

Keine meiner Abfragen dauert normalerweise eine Sekunde. Es scheint also albern, eine Verbindung für 480 Minuten offen zu halten.

Ich habe auch davon gehört mysql_pconnect anstatt mysql_connect, aber ich habe nichts als Horrorgeschichten darüber gelesen, also denke ich, dass ich mich davon fern halte.


34
2018-02-01 11:42


Ursprung


Es gibt einen Unterschied zwischen Abfragen und Verbindungen. Sie müssen zumindest sicherstellen, dass Ihre Website-Software nicht bricht, wenn eine kürzere wait_timeout Schließen einer Verbindung, wenn die Software erwartet, dass sie geöffnet bleibt. - John Gardeniers


Antworten:


Das Verringern des Wertes ist ohne einen mysql-Neustart ziemlich trivial

Nehmen wir an, Sie möchten Timeouts auf 30 Sekunden verringern

Zuerst füge das 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 nachfolgenden DB-Verbindungen werden nach 30 Sekunden ablaufen

WARNUNG

Stellen Sie sicher, dass Sie explizit mysql_close verwenden. Ich traue Apache nicht wie die meisten Entwickler. Wenn nicht, gibt es manchmal eine Race-Bedingung, bei der Apache eine DB-Verbindung schließt, aber nicht informiert, dass mysqld und mysqld diese Verbindung offen halten, bis das Zeitlimit überschritten wird. Schlimmer noch, Sie sehen TIME_WAITs häufiger. Wählen Sie Ihre Timeout-Werte mit Bedacht.

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 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 das ausführen, sollten Sie etwas wie folgt sehen:

[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 Sie noch viel mysql sehen TIME_WAITs Für jeden Webserver gibt es zwei Eskalationsschritte:

ESCALIERUNG # 1

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

service httpd stop
sleep 30
service httpd start

Führen Sie dies bei Bedarf für alle Webserver 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 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 wird TIME_WAITs in 1 Sekunde deaktiviert.

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


69
2018-02-01 19:30



Fast 2k Aufrufe für dieses und nur 2 oben Stimmen (einschließlich meiner, also 1), wtf ?! Das ist eine großartige Antwort. Sorry, ich kann nur 1 Stimme abgeben! - jwbensley
Ich habe diese Technik ausprobiert, und ich hatte viele CLOSE_WAIT Verbindungen (2622), aber keine TIME_WAIT Verbindungen. Wie soll ich dieses Ergebnis interpretieren? - robguinness


Wenn Sie auf dem MySQL-Server viele TIME_WAIT-Verbindungen erhalten, bedeutet dies, dass der MySQL-Server die Verbindung schließt. Der wahrscheinlichste Fall wäre in diesem Fall, 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

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

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

Sie können auch bestätigen, dass dies geschieht, indem Sie zu einem Ihrer Clients gehen, der Probleme beim Verbinden und Telnet mit Port 3306 hat. Es wird eine Nachricht mit folgendem Inhalt 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.

3
2017-07-10 02:14





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

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
2017-07-01 19:18