MySQL bajando el valor wait_timeout para disminuir el número de conexiones abiertas

39

Ejecuto un sitio bastante ocupado, y durante las horas de observación veo más de 10.000 conexiones abiertas a mi servidor de base de datos en mi servidor web cuando ejecuto un comando netstat. El 99% de las conexiones están en el TIME_WAITestado.

Aprendí sobre esta variable mysql: wait_timeout http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout hoy. El mío todavía está configurado en los 28.800 segundos predeterminados.

¿Es seguro bajar este valor?

Ninguna de mis consultas generalmente toma más de un segundo. Por lo tanto, parece una tontería mantener una conexión abierta durante 480 minutos.

También escuché sobre el uso en mysql_pconnectlugar de mysql_connect, pero no he estado leyendo más que historias de terror al respecto, así que creo que me mantendré alejado de eso.

Mr.Boon
fuente
3
Hay una diferencia entre consultas y conexiones. Al menos, debe asegurarse de que el software de su sitio web no se rompa si un corto wait_timeouthace que se cierre una conexión cuando el software espera que permanezca abierto.
John Gardeniers

Respuestas:

74

Bajar el valor es bastante trivial sin un reinicio de mysql

Digamos que desea reducir los tiempos de espera a 30 segundos.

Primero, agregue esto a my.cnf

[mysqld]
interactive_timeout=30
wait_timeout=30

Entonces, puedes hacer algo como esto

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

Todas las conexiones de base de datos después de esto expirarán en 30 segundos

ADVERTENCIA

Asegúrese de usar explícitamente mysql_close. No confío en Apache como lo hacen la mayoría de los desarrolladores. Si no, a veces, hay una condición de carrera en la que Apache cierra una conexión DB pero no informa a mysqld y mysqld mantiene esa conexión abierta hasta que se agota el tiempo de espera. Peor aún, puede ver TIME_WAITs con más frecuencia. Elija sus valores de tiempo de espera sabiamente.

ACTUALIZACIÓN 2012-11-12 10:10 EDT

ADVERTENCIA

Después de aplicar mis sugerencias publicadas, cree un script llamado /root/show_mysql_netstat.shcon las siguientes líneas:

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

Cuando ejecute esto, debería ver algo como esto:

[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

Si todavía ve una gran cantidad de mysql TIME_WAITspara cualquier servidor web dado, aquí hay dos pasos de escalación a seguir:

ESCALACIÓN # 1

Inicie sesión en el servidor web infractor y reinicie Apache de la siguiente manera:

service httpd stop
sleep 30
service httpd start

Si es necesario, haga esto a todos los servidores web

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

ESCALACIÓN # 2

Puede forzar al sistema operativo a eliminar TIME_WAITs para mysql o cualquier otra aplicación con lo siguiente:

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

Esto hará que TIME_WAITs agote el tiempo de espera en 1 segundo.

Para dar crédito donde se debe crédito ...

RolandoMySQLDBA
fuente
1
¡Casi 2k vistas para esto y solo 2 votos para arriba (incluido el mío, así que 1), wtf ?! Esta es una respuesta genial. Lo siento, solo puedo dar 1 voto.
jwbensley
Probé esta técnica y tenía muchas conexiones CLOSE_WAIT (2622) pero no conexiones TIME_WAIT. ¿Cómo debo interpretar este resultado?
robguinness
4

Si está obteniendo muchas conexiones TIME_WAIT en el servidor MySQL, eso significa que el servidor MySQL está cerrando la conexión. El caso más probable en este caso sería que un host o varios hosts se pusieran en una lista de bloqueo. Puede borrar esto ejecutando:

mysqladmin flush-hosts

Para obtener una lista de la cantidad de conexiones que tiene por ejecución de IP:

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

También puede confirmar que esto está sucediendo yendo a uno de sus clientes que tiene problemas para conectarse y telnet al puerto 3306. Mostrará un mensaje con 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.
usuario2566717
fuente
1

Si tiene muchas conexiones TIME_WAIT a su servidor MySQL, significa que su código ejecuta muchas consultas en su base de datos y abre / cierra una conexión para cada consulta.

En este caso, debe utilizar la conectividad persistente a su servidor de base de datos, utilizando la extensión MySQLi.

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

Si no puede usar MySQLi, debería usar el parámetro thread_cache_size en su configuración de MySQL.

Garreth McDaid
fuente