【问题标题】:MySQL "Gone Away" Error with Persistent PHP Connection持久 PHP 连接的 MySQL“消失”错误
【发布时间】:2014-12-24 13:59:55
【问题描述】:

我在 WAMP 堆栈上本地托管一个网站。我最近通过将array(PDO::ATTR_PERSISTENT => true) 添加到PDO 构造函数选项参数来将PHP 连接切换为持久连接。结果,我注意到响应时间大幅下降(万岁!)。

当机器唤醒时,缺点似乎是消失的错误。这在更改连接样式之前从未发生过。

有没有可能是缓存的连接被关闭了,但是继续返回?是否可以通过 catch 块内的PHP 重置PDO 连接或重置连接池?

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    我已经解决了几天这个问题,根据网络上类似问题的普遍性,这似乎是 PDO 的缺陷,阻碍了持久连接的有效管理。

    对显而易见的问题的回答:

    • PHP 5.4.22
    • php.ini 中的驱动程序设置已开启持久连接
    • 会话限制不受限制(设置为 -1)
    • 池限制不受限制(设置为 -1)

    我可以通过执行以下操作重新创建问题:

    在 MySQL 数据库上发出以下语句。

    set @@GLOBAL.interactive_timeout := 10;
    set @@GLOBAL.wait_timeout := 10;
    

    向服务器发出一些请求以生成一些缓存连接。与使用非持久连接相比,您可以通过以下方式看到线程数增加:

    echo $conn->getAttribute(PDO::ATTR_SERVER_INFO);
    

    等待至少 10 秒,然后开始发出更多请求。您应该开始收到“离开”消息。

    问题是 SQL 关闭连接,随后对 PDO 构造函数的调用返回这些关闭的连接重新连接它们。

    这就是 PDO 的不足之处。没有办法强制打开连接,甚至没有检测状态的好方法。

    我目前解决这个问题的方法(诚然有点 hack)是发出这些 MySQL 语句

    set @@GLOBAL.interactive_timeout := 86400;
    
    set @@GLOBAL.wait_timeout := 86400;
    

    These variables are set to 28800sec (8 hours) by default。请注意,您需要重新启动 Apache 以清除缓存的连接,否则在池中的所有连接都已循环之前您不会注意到差异(我不知道这种情况如何/何时发生)。我选择了 86400,即 24 小时,我每天都在这台机器上,所以这应该可以满足基本需求。

    在此更新之后,我让我的机器至少放置了 12 个小时,这是我之前开始收到“离开消息”时的放置时间。看起来问题解决了。

    我一直在想,虽然我不能强制打开连接,但有可能从池中删除坏连接。我还没有尝试过,但稍微更优雅的解决方案可能是检测“消失”消息,然后将对象设置为 NULL,告诉 PHP 销毁资源。如果数据库逻辑进行了几次这样的尝试(必须有一个限制,以防发生更严重的错误),它可能有助于将这些错误保持在最低限度。

    【讨论】:

      【解决方案2】:

      我正在研究在 nginx 后面的 php-fpm 7.3 上使用持久连接并尝试使用 1 个子节点的静态池重现该行为,但到目前为止我还做不到。

      我可以在一个单独的终端上通过SHOW PROCESSLIST 看到数据库如何在执行 SELECT 的请求 5 秒后关闭持久连接,但下一个只是打开一个新的并且工作正常。另一方面,如果我用负载测试工具轰炸 API,则保持相同的连接并且所有请求都成功。

      可能是因为您使用了 Apache+mod_php 而不是 php-fpm 工作池,或者 PHP 5.4 和 7.3 之间存在真正的修复

      测试的版本:

      PHP-FPM: 7.3.13
      mysqlnd (underlying PDO_MYSQL driver): 5.0.12-dev - 20150407
      MySQL Server: 5.7.29 and 8.0.19
      MariaDB Server (MySQL drop-in replacement): 10.1.43
      

      PD 感谢您布置复制步骤和您的思考过程,这是非常宝贵的。

      【讨论】:

        【解决方案3】:

        是的,如果连接关闭,您将需要重新连接。

        http://brady.lucidgene.com/2013/04/handling-pdo-lost-mysql-connection-error/

        【讨论】:

        • 我的问题不是连接是否需要重新连接。我在问缓存连接是否会超时,然后被允许坐在池中,从而导致返回关闭或有其他问题的连接。引用的帖子并没有真正解决根本问题。我收到消失消息的查询并不显着,应该立即返回,所以我怀疑问题不是超时,而是连接管理方式的问题。
        • 是的,PDO 不会主动检查空闲连接的连接状态。我不知道有任何数据库接口。它只会在连接被唤醒时检查它。通常,除非您考虑了所有问题,否则应避免使用持久连接。
        猜你喜欢
        • 2011-04-21
        • 2012-07-30
        • 2016-11-08
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多