mysql_ping hangs with Amazon RDS



我正试图从运行在外部ubuntu服务器上的php工作程序持久连接到MySQL RDS数据库。作为连接的一部分,我首先检查"mysql_ping"。如果ping返回true,则使用当前连接,否则创建新连接。

我面临的问题是,当我启动我的worker时,连接建立得很好,并且在一段时间内运行良好,即我可以成功地重复查询RDS数据库。然而,大约15分钟后,如果我发出请求,那么"mysql_ping"将挂起,因此php脚本本身也将挂起。在进一步的调试中,我发现mysql_ping响应在936秒后返回为false。

从外部服务器访问数据库所需的权限已经存在,在这段时间里(当脚本挂起时),我可以使用mysql命令行选项成功连接到RDS数据库。此外,如果我杀死工人并重新启动它,它可以再次成功连接,但问题在15分钟左右后再次出现。

为了避免这个问题,RDS服务器设置中有什么需要更改的吗??

谨致问候,Kapil

我在文档中找不到引文,但我的经验表明,EC2的网络基础设施通常(包括RDS和可能在每个客户(如果不是所有AWS的话)提供的虚拟机上运行的任何其他AWS服务,当然似乎并不严格限于"EC2实例")实现了状态数据包检查,并且会在几分钟的绝对空闲后"忘记"TCP连接是有效的。。。导致你描述的行为。

连接两端的机器可能会确信连接仍然存在,但网络不会允许流量在它们之间通过,因为SPI环境中的TCP会话不会被发现,它们是创建的,并且只有在网络一开始看到连接时才能创建(SYN、SYN/ACK、ACK)。我最初在EC2(而不是RDS)中的MySQL服务器上遇到了这个问题,但如果根本原因不一样,我会非常惊讶。

有两种可能的方法来解决这个问题。

如果您的PHP机器是Linux,请配置内核以保持第4层的连接。这种更改对您来说是不可见的,因为这些keepalive不会更改Sleep中连接的SHOW PROCESSLISTTime列中的值,因为它不会重置连接在第7层的空闲时间。。。但是,如果管理MySQL连接的库正确设置了套接字选项以利用它,它应该避免AWS基础设施的超时。

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html解释了如何实时设置,以及如何使其在重新启动时保持不变。

如果做不到这一点,另一种选择是强制MySQL在网络超时之前关闭连接,这样PHP机器就会立即识别出它正试图在一个关闭的套接字上进行对话。缩短超时而不是延长超时听起来可能有违直觉,但如果会话空闲时间过长,缩短超时会导致ping测试很快失败,这也(本质上)"解决"了问题,假设PHP客户端库是健全的。一旦您的应用程序更忙,连接可能很少空闲足够长的时间来达到超时。

MySQL Server有两种不同的空闲超时设置:wait_timeout(用于非交互式会话,即来自代码的连接,如PHP)和interactive_timeout(来自查询浏览器和命令行客户端),但服务器只知道区别,因为客户端库必须通知服务器它正在建立哪种类型的连接。假设您的客户端库使用了正确的设置,那么wait_timeout就是您要查找的。如果在Linux内核中更改TCP保持活动设置没有,那么将其设置为低于900的值应该可以解决问题。不过,请注意,在进行更改后,只有未来的连接才会受到影响——在进行更改时已经建立的连接仍将以当前值运行,默认值为8小时(28800秒)。这些可在您实例的RDS参数组中进行配置。

这里的AWS文档中有类似行为的提示,以及Windows注册表设置,如果您在Windows而不是Linux上运行PHP服务器,则需要调整这些设置以更改TCP保持有效,正如我上面假设的那样。。。尽管这篇文章专门讨论了Redshift和EC2外部的连接,但它似乎仍然验证了上面讨论的根本问题。

最新更新