You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中遇"MySQL Server has gone away"错误及Socket服务连接问题

解决PHP Socket Server中「MySQL Server has gone away」错误

我之前在维护长运行的Socket服务时也踩过这个坑,结合你的场景,咱们一步步拆解问题、解决问题:

核心原因分析

你提到每次处理消息都会开启、关闭连接,但间隔5-10分钟就报错,大概率是以下两种情况:

  • MySQL主动断开闲置连接:MySQL默认会断开超过wait_timeout时长的闲置连接,很多服务器会把这个值改得比默认的8小时短,如果你的环境里这个值小于5-10分钟,就会触发错误。
  • PHP连接逻辑未处理失效场景:即便你调用了关闭连接的函数,也可能因为代码分支问题(比如报错后跳过关闭步骤)导致连接资源没被正确释放,下次尝试复用就会出问题。

具体解决方案

1. 检查并调整MySQL超时配置

先确认MySQL的闲置连接超时设置:

  • 登录MySQL终端,执行命令查看参数:
    SHOW VARIABLES LIKE '%timeout%';
    
    重点关注wait_timeout和interactive_timeout(单位为秒),如果它们的数值小于300(5分钟)或600(10分钟),就是问题根源。
  • 修改MySQL配置文件(my.cnf或my.ini,根据操作系统而定),调整参数:
    wait_timeout = 3600
    interactive_timeout = 3600
    
    修改后重启MySQL服务,让配置生效。

2. 优化PHP数据库连接逻辑

确保连接代码能自动处理失效场景,比如连接前检查有效性,失败时重试:

function getValidDbConnection() {
    $host = '你的数据库地址';
    $user = '数据库用户名';
    $pass = '数据库密码';
    $dbName = '目标数据库名';

    // 首次尝试连接
    $conn = mysqli_connect($host, $user, $pass, $dbName);

    if ($conn) {
        // 用ping检查连接是否存活
        if (!mysqli_ping($conn)) {
            // 连接已失效,关闭旧连接后重新建立
            mysqli_close($conn);
            $conn = mysqli_connect($host, $user, $pass, $dbName);
        }
    }

    // 记录连接失败日志
    if (!$conn) {
        error_log('MySQL连接失败: ' . mysqli_connect_error());
        return false;
    }

    return $conn;
}

然后在Socket消息处理逻辑中这样使用:

// 收到消息后的处理流程
$dbConn = getValidDbConnection();
if ($dbConn) {
    try {
        // 注意:这里一定要做SQL注入防护
        $safeContent = mysqli_real_escape_string($dbConn, $messageContent);
        $sql = "INSERT INTO your_table (content) VALUES ('{$safeContent}')";
        
        $result = mysqli_query($dbConn, $sql);
        if (!$result) {
            throw new Exception('数据库查询失败: ' . mysqli_error($dbConn));
        }
    } catch (Exception $e) {
        error_log($e->getMessage());
    } finally {
        // 无论成功失败,确保连接被关闭
        mysqli_close($dbConn);
    }
}

3. 禁用持久连接

如果你之前用了mysqli_pconnect(持久连接),立刻换成mysqli_connect。持久连接不会真正关闭,而是放回PHP连接池,当MySQL断开池中的连接后,下次取出使用就会触发「has gone away」错误。

4. 确保所有代码路径都关闭连接

避免因为报错跳转导致连接未关闭,用try...finally结构强制保证连接释放,就像上面代码示例里那样,不管查询成功还是失败,finally块都会执行关闭操作。

总结

先从MySQL超时配置入手排查,再优化PHP的连接逻辑,确保每次使用的都是有效连接,并且在所有场景下都能正确释放连接。按照这个步骤操作,应该就能解决你的问题了。

内容的提问来源于stack exchange,提问作者Razgriz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:22:53