Não consigo encontrar uma citação na documentação, mas minha experiência sugere que a infraestrutura de rede do EC2 em geral (que inclui RDS e provavelmente qualquer outro serviço da AWS executado em máquinas virtuais provisionadas por cliente, se não todas AWS, e certamente não parece estar limitado estritamente a "instâncias do EC2") implementa a inspeção de pacotes com estado e "esquece" que uma conexão TCP é válida após alguns minutos de inatividade absoluta... causando o comportamento que você descreve.
As máquinas em ambas as extremidades da conexão podem estar convencidas de que a conexão ainda está lá, mas a rede não permitirá que o tráfego passe entre elas, porque as sessões TCP em um ambiente SPI não são descobertas, elas são criadas e só podem ser criado quando a rede vê a conexão logo no início (SYN, SYN/ACK, ACK ). Eu originalmente encontrei esse problema com servidores MySQL no EC2 (não no RDS), mas ficaria muito surpreso se a causa subjacente não fosse a mesma.
Existem duas abordagens possíveis para contornar isso.
Se sua máquina PHP for Linux, configure o kernel para manter as conexões ativas na camada 4. Essa mudança será invisível para você no sentido de que esses keepalives não alterarão o valor no
Time
coluna em SHOW PROCESSLIST
para conexões em Sleep
porque não redefinirá a quantidade de tempo que a conexão ficou ociosa na camada 7 ... mas deve evitar os tempos limite da infraestrutura da AWS se as bibliotecas que gerenciam as conexões do MySQL estiverem configurando as opções de soquete corretamente para tirar proveito disso. http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive .html explica como configurar isso ao vivo e como torná-lo persistente nas reinicializações.
Caso contrário, a outra opção é forçar o MySQL a fechar a conexão antes do tempo limite da rede para que a máquina PHP reconheça imediatamente que está tentando falar em um soquete fechado. Pode parecer contra-intuitivo encurtar um tempo limite em vez de prolongá-lo, mas encurtar o tempo limite deve fazer com que seu teste de ping falhe muito rapidamente se uma sessão estiver ociosa por muito tempo, o que também (essencialmente) "resolve" o problema, assumindo sanidade na biblioteca cliente PHP. Quando seu aplicativo estiver mais ocupado, as conexões provavelmente raramente ficarão ociosas por tempo suficiente para atingir o tempo limite.
O MySQL Server tem duas configurações diferentes de tempo limite ocioso:
wait_timeout
(para sessões não interativas, ou seja, conexões de código, como PHP) e interactive_timeout
(dos navegadores de consulta e do cliente de linha de comando), mas o servidor só sabe a diferença porque a biblioteca do cliente precisa notificar o servidor sobre o tipo de conexão que está estabelecendo. Supondo que sua biblioteca cliente use a configuração correta, então wait_timeout
é o que você está procurando. Definir isso para um valor abaixo de 900 deve resolver o problema se a alteração das configurações de manutenção de atividade do TCP no kernel do Linux não resolver. Observe, no entanto, que depois de fazer a alteração, apenas as conexões futuras serão afetadas - as conexões já estabelecidas quando a alteração for feita ainda estarão em execução com o valor atual, cujo padrão é 8 horas (28.800 segundos). Eles são configuráveis no RDS Parameter Group para sua instância. Existem dicas de comportamento semelhante nos documentos da AWS aqui , junto com as configurações de registro do Windows que precisam ser ajustadas para alterar os keepalives do TCP se você estiver executando o servidor PHP no Windows, em vez do Linux, como presumi acima ... mesmo que o artigo seja especificamente sobre Redshift e conexões externas a EC2 ainda parece validar o problema subjacente, conforme discutido acima.