MySQL riduce il valore wait_timeout per ridurre il numero di connessioni aperte


39

Gestisco un sito piuttosto occupato e durante le ore di anteprima vedo oltre 10.000 connessioni aperte al mio server di database sul mio server web quando eseguo un comando netstat. Il 99% delle connessioni è nello TIME_WAITstato.

Ho imparato a conoscere questa variabile mysql: wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout oggi. Il mio è ancora impostato sui 28.800 secondi predefiniti.

Abbassare questo valore è sicuro?

Nessuna delle mie domande di solito impiega più di un secondo. Quindi sembra sciocco mantenere una connessione aperta per 480 minuti.

Ho anche sentito parlare dell'uso mysql_pconnectinvece di mysql_connect, ma non ho letto altro che storie horror a riguardo, quindi penso che starò lontano da quello.


3
C'è una differenza tra query e connessioni. È necessario almeno assicurarsi che il software del sito Web non si interrompa se un breve wait_timeoutcausa la chiusura di una connessione quando il software prevede che rimanga aperto.
John Gardeniers,

Risposte:


74

Abbassare il valore è piuttosto banale senza un riavvio mysql

Supponiamo che tu voglia ridurre i timeout a 30 secondi

Per prima cosa, aggiungi questo a my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Quindi, puoi fare qualcosa del genere

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

Tutte le connessioni DB dopo questo scadono in 30 secondi

AVVERTIMENTO

Assicurati di usare esplicitamente usa mysql_close. Non mi fido di Apache come fanno molti sviluppatori. Altrimenti, a volte, esiste una condizione di competizione in cui Apache chiude una connessione DB ma non informa mysqld e mysqld di tenere aperta quella connessione fino al timeout. Ancora peggio, potresti vedere TIME_WAIT più spesso. Scegli saggiamente i valori di timeout.

AGGIORNAMENTO 2012-11-12 10:10 EDT

AVVERTIMENTO

Dopo aver applicato i miei suggerimenti pubblicati, crea uno script chiamato /root/show_mysql_netstat.shcon le seguenti righe:

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

Quando esegui questo, dovresti vedere qualcosa del genere:

[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

Se vedi ancora un sacco di mysql TIME_WAITsper un determinato server Web, ecco due passaggi di escalation da eseguire:

ESCALATION # 1

Accedi al server Web offensivo e riavvia apache come segue:

service httpd stop
sleep 30
service httpd start

Se necessario, eseguire questa operazione su tutti i server 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

Puoi forzare il sistema operativo a eliminare TIME_WAITs per mysql o qualsiasi altra app con quanto segue:

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

Ciò farà scadere TIME_WAIT in 1 secondo.

Per dare credito quando il credito è dovuto ...


1
Quasi 2k visualizzazioni per questo e solo 2 voti positivi (incluso il mio, quindi 1), wtf ?! Questa è un'ottima risposta Mi dispiace, posso solo dare 1 voto!
jwbensley,

Ho provato questa tecnica e avevo molte connessioni CLOSE_WAIT (2622) ma non connessioni TIME_WAIT. Come devo interpretare questo risultato?
rapina

4

Se stai ricevendo molte connessioni TIME_WAIT sul server MySQL, significa che il server MySQL sta chiudendo la connessione. Il caso più probabile in questo caso sarebbe che un host o più host entrassero in un elenco di blocchi. Puoi cancellarlo eseguendo:

mysqladmin flush-hosts

Per ottenere un elenco del numero di connessioni che hai per ogni esecuzione IP:

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

Puoi anche confermare che ciò sta accadendo andando a uno dei tuoi clienti che ha problemi di connessione e telnet alla porta 3306. Mostrerà un messaggio con qualcosa del tipo:

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.

1

Se hai molte connessioni TIME_WAIT al tuo server MySQL, significa che il tuo codice sta eseguendo molte query sul tuo DB e sta aprendo / chiudendo una connessione per ogni query.

In questo caso, è necessario utilizzare la connettività persistente al server DB, utilizzando l'estensione MySQLi.

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

Se non puoi usare MySQLi, dovresti invece usare il parametro thread_cache_size nella tua configurazione MySQL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.