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

Yii2中MySQL服务器断开后如何实现原生重连?

Yii2 MySQL断线重连解决方案

原生实现说明

Yii2 从 2.0.36 版本开始,yii\db 组件原生支持 MySQL 断线自动重连能力,无需手动调用 close() 和 open() 方法。你之前手动调用未生效的核心原因是手动调用时机无法覆盖所有SQL执行前的节点,原生重连逻辑会在每次命令执行前自动检测连接有效性,失效则自动触发重连。

原生重连开启方式只需在数据库配置中添加 enableReconnect 参数即可,示例配置如下:

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=127.0.0.1;dbname=你的数据库名',
            'username' => '数据库账号',
            'password' => '数据库密码',
            'charset' => 'utf8mb4',
            // 开启原生断线自动重连
            'enableReconnect' => true,
            // 可选配置:设置连接超时时间,配合重连逻辑使用
            'attributes' => [
                PDO::ATTR_TIMEOUT => 10,
            ],
        ],
    ],
];

注意:原生重连仅会在SQL执行前检测到连接断开时触发,若SQL执行过程中连接断开不会重连,避免重复执行写操作引发数据一致性问题。

低版本兼容方案

如果你使用的Yii2版本低于2.0.36,没有内置enableReconnect参数,可以通过继承原生Connection类自定义重连逻辑:

  1. 新增自定义连接类
<?php
namespace common\components;

use PDOException;
use yii\db\Exception;

class ReconnectableConnection extends \yii\db\Connection
{
    // 最大重连次数,可根据业务调整
    public $maxReconnectAttempts = 3;

    public function open()
    {
        $currentAttempt = 0;
        while (true) {
            try {
                parent::open();
                break;
            } catch (PDOException $e) {
                $currentAttempt++;
                // 判定为连接断开类错误且未超过重试次数时,触发重连
                if (
                    $currentAttempt <= $this->maxReconnectAttempts
                    && (str_contains($e->getMessage(), 'MySQL server has gone away')
                        || str_contains($e->getMessage(), 'Lost connection to MySQL server'))
                ) {
                    $this->close();
                    // 等待100ms再重试,避免瞬间并发重试失败
                    usleep(100000);
                    continue;
                }
                // 非连接类错误或超过重试次数,抛出异常
                throw new Exception($e->getMessage(), $e->errorInfo, $e->getCode(), $e);
            }
        }
    }
}
  1. 修改数据库配置中的class参数为自定义类即可:
'db' => [
    'class' => 'common\components\ReconnectableConnection',
    // 其余原有数据库配置保持不变
],

常见失效场景说明

  • 常驻进程(如队列消费、Swoole服务)场景下不要开启PDO::ATTR_PERSISTENT持久连接参数,持久连接的状态Yii2无法正常识别,会导致重连逻辑失效
  • 手动事务执行过程中连接断开不会触发重连,事务上下文丢失后重连也无法恢复原有事务,此类场景需要自行捕获异常后手动回滚再重试
  • 主库连接池配置本身不包含断线检测逻辑,需要配合上述重连参数一同使用才会生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:15:02