sql >> Base de Datos >  >> RDS >> Mysql

mysql_ping se bloquea con Amazon RDS

No puedo encontrar una cita en la documentación, pero mi experiencia sugiere que la infraestructura de red de EC2 en general (que incluiría RDS y probablemente cualquier otro servicio de AWS que se ejecute en máquinas virtuales aprovisionadas por cliente, si no todos). AWS, y ciertamente no parece estar limitado estrictamente a "instancias EC2"), implementa la inspección de paquetes con estado y "olvidará" que una conexión TCP es válida después de unos minutos de inactividad absoluta... causando el comportamiento que usted describe.

Las máquinas en ambos extremos de la conexión pueden estar convencidas de que la conexión aún existe, pero la red no permitirá que el tráfico pase entre ellas, porque las sesiones TCP en un entorno SPI no se descubren, se crean y solo pueden se creará cuando la red vea la conexión desde el principio (SYN, SYN/ACK, ACK ). Originalmente me encontré con este problema con servidores MySQL en EC2 (no RDS), pero me sorprendería mucho si la causa subyacente no fuera la misma.

Hay dos enfoques posibles para evitar esto.

Si su máquina PHP es Linux, configure el kernel para mantener vivas las conexiones en la capa 4. Este cambio será invisible para usted en el sentido de que estos keepalives no cambiarán el valor en el Time columna en SHOW PROCESSLIST para conexiones en Sleep porque no restablecerá la cantidad de tiempo que la conexión ha estado inactiva en la capa 7... pero debería evitar los tiempos de espera de la infraestructura de AWS si las bibliotecas que administran las conexiones de MySQL están configurando las opciones de socket correctamente para aprovecharlo.

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive .html explica cómo configurar esto en vivo y cómo hacerlo persistente entre reinicios.

De lo contrario, la otra opción es obligar a MySQL a cerrar la conexión antes del tiempo de espera de la red para que la máquina PHP reconozca inmediatamente que está tratando de hablar en un socket cerrado. Puede parecer contrario a la intuición acortar un tiempo de espera en lugar de alargarlo, pero acortar el tiempo de espera debería hacer que la prueba de ping falle muy rápidamente si una sesión ha estado inactiva demasiado tiempo, lo que también (esencialmente) "resuelve" el problema, asumiendo la cordura. en la biblioteca del cliente PHP. Una vez que su aplicación esté más ocupada, es de suponer que las conexiones rara vez estarán inactivas el tiempo suficiente para alcanzar el tiempo de espera.

MySQL Server tiene dos configuraciones diferentes de tiempo de espera inactivo: wait_timeout (para sesiones no interactivas, es decir, conexiones desde código, como PHP) y interactive_timeout (desde los navegadores de consultas y el cliente de la línea de comandos) pero el servidor solo sabe la diferencia porque la biblioteca del cliente tiene que notificar al servidor qué tipo de conexión está estableciendo. Suponiendo que la biblioteca de su cliente utiliza la configuración correcta, wait_timeout es el que buscas. Establecer esto en un valor por debajo de 900 debería resolver el problema si cambiar la configuración de mantenimiento de TCP en el kernel de Linux no lo hace. Tenga en cuenta, sin embargo, que después de realizar el cambio, solo se verán afectadas las conexiones futuras:las conexiones ya establecidas cuando se realiza el cambio seguirán ejecutándose con el valor actual, que por defecto es de 8 horas (28800 segundos). Estos se pueden configurar en el grupo de parámetros de RDS para su instancia.

Hay indicios de comportamiento similar en los documentos de AWS aquí , junto con la configuración del registro de Windows que debe ajustarse para cambiar los keepalives de TCP si está ejecutando el servidor PHP en Windows, en lugar de Linux, como supuse anteriormente... aunque el artículo trata específicamente sobre Redshift y conexiones externas a EC2 todavía parece validar el problema subyacente como se discutió anteriormente.