MySQL 服务器已消失 - 但没有连接错误

MySQL server has gone away - but no connect error

考虑以下场景: 我们有一个 AWS 工作者实例(基于 SQS),它打开与我们的 RDS 的持久 MySQL 连接。

$this->connectRegistry[ $host ][ 'connect' ] = mysqli_connect(
    "p:" . $host ,
    $this->hostCredentials[ $host ][ 'username' ] ,
    $this->hostCredentials[ $host ][ 'password' ]
);

现在有时 - 不是定期 - 此调用会生成以下警告:

PHP Warning: mysqli_connect(): MySQL server has gone away

由于 AWS worker 实例正在使用 Web 服务器处理请求,因此设置与为网站提供服务的普通实例基本相同。我们在多个项目中使用相同的class,但在没有一个网站中甚至出现过一次此错误。

为了了解这些警告的来源,我们尝试在发生连接错误时打印堆栈跟踪,但是 - 现在尴尬的事情开始出现 - 没有连接错误。请看一下整个连接函数:

private function connect ( $host )
{
    $this->connectRegistry[ $host ][ 'connect' ] = mysqli_connect(
        "p:" . $host ,
        $this->hostCredentials[ $host ][ 'username' ] ,
        $this->hostCredentials[ $host ][ 'password' ]
    );
    $error = mysqli_connect_error();
    if( $error ) {
        $this->raiseError( "Connect (" . mysqli_connect_errno() . ") " . $error );
        return false;
    }
    return true;
}

方法 raiseError 使用堆栈跟踪等构建完整的错误消息,然后调用 trigger_error。但是,如果触发上述警告,则不会调用此方法。

我们的首要目标是了解在哪些 cronjobs 中触发了这些警告 - 可能有一些性能不佳的查询。

我在使用 php 守护程序时遇到过此类问题:当您启动守护程序时,会建立 php 连接,如果一段时间内没有查询,数据库连接实际上就会终止。

过去我找到了两个解决方案

  1. 为了保持连接,每 n 秒进行一次简单的快速查询
  2. 在运行时创建连接,不是在守护程序启动时而是在守护程序执行工作时创建连接。

我建议第二个选择。

“持久”连接并不意味着连接将永远存在,如果使用相同的用户名、密码等 (doc),它只会被重复使用,如果您使用方法 2,这会有所帮助)

如果得到

就不会出现任何连接错误

mysqli_connect(): MySQL server has gone away

此消息表示 现有 连接不再可用。一定是出了什么事,MySQL 服务器关闭了连接。这可能有很多原因。最常见的是在代码中的其他地方调用 mysqli_close(),但由于您在此处使用持久连接,根本原因可能完全不同。您需要调试导致连接断开的原因。

但是,我强烈建议完全停止使用持久连接。您不太可能有正当的技术理由来使用它们并且调试它们可能会非常有问题。