MySQL reduzindo o valor de wait_timeout para um número menor de conexões abertas

34

Eu corro um site bastante ocupado, e durante as horas de peek eu vejo mais de 10.000 conexões abertas para o meu servidor de banco de dados no meu servidor web quando um comando executar um netstat. 99% das conexões estão no estado TIME_WAIT .

Eu aprendi sobre essa variável mysql: wait_timeout link hoje. O meu ainda está definido no padrão 28.800 segundos.

Está diminuindo este valor com segurança?

Nenhuma das minhas consultas costuma demorar mais de um segundo. Então, parece tolo manter uma conexão aberta por 480 minutos.

Eu também ouvi sobre usar mysql_pconnect em vez de mysql_connect , mas eu tenho lido nada além de histórias de horror sobre isso, então acho que vou ficar longe disso.

    
por Mr.Boon 01.02.2012 / 12:42

3 respostas

69

Diminuir o valor é bem trivial sem uma reinicialização do mysql

Digamos que você queira diminuir o limite de tempo para 30 segundos

Primeiro, adicione isso ao my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Então, você pode fazer algo assim

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

Todas as conexões de banco de dados após esse tempo limite em 30 segundos

AVISO

Certifique-se de usar explicitamente o mysql_close. Eu não confio no Apache como a maioria dos desenvolvedores. Se não, às vezes, há uma condição de corrida em que o Apache fecha uma conexão com o banco de dados, mas não informa ao mysqld e ao mysqld que mantêm a conexão aberta até o tempo limite. Pior ainda, você pode ver TIME_WAITs com mais frequência. Escolha seus valores de tempo limite com sabedoria.

ATUALIZAÇÃO 2012-11-12 10:10 EDT

CAVEAT

Depois de aplicar minhas sugestões postadas, crie um script chamado /root/show_mysql_netstat.sh com as seguintes linhas:

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 você executa isso, você deve ver algo assim:

[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 você ainda vê muito mysql TIME_WAITs para qualquer servidor web, aqui estão duas etapas de escalação a seguir:

ESCALATION # 1

Faça login no servidor da web e reinicie o apache da seguinte forma:

service httpd stop
sleep 30
service httpd start

Se necessário, faça isso em todos os servidores da 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

Você pode forçar o SO a matar TIME_WAITs para o mysql ou qualquer outro aplicativo com o seguinte:

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

Isso fará com que TIME_WAIT termine em 1 segundo.

Para dar crédito onde o crédito é devido ...

por 01.02.2012 / 20:30
3

Se você está obtendo muitas conexões TIME_WAIT no servidor MySQL, significa que o servidor MySQL está fechando a conexão. O caso mais provável neste exemplo seria que um host ou vários hosts entrassem em uma lista de bloqueios. Você pode limpar isso executando:

mysqladmin flush-hosts

Para obter uma lista do número de conexões que você tem por execução de IP:

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

Você também pode confirmar que isso está acontecendo indo para um dos seus clientes que está tendo problemas para se conectar e telnet para a porta 3306. Ele mostrará uma mensagem com algo como:

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.
    
por 10.07.2013 / 04:14
1

Se você tem muitas conexões TIME_WAIT com seu servidor MySQL, significa que você está executando muitas consultas em seu banco de dados e abrindo / fechando uma conexão para cada consulta.

Nesse caso, você deve usar conectividade persistente com seu servidor de banco de dados, usando a extensão MySQLi.

link

Se você não pode usar o MySQLi, você deve usar o parâmetro thread_cache_size em sua configuração do MySQL.

    
por 01.07.2013 / 21:18