yii2 mysql重连机制

在工作中,有时候一些后台脚本需要长时间的运行,同时可能在连接数据库后,长时间不与数据库服务端交互。此时,服务器可能会断开与客户端的连接。从而客户端再次交互时就会出现"MySQL server has gone away"连接丢失。 此次修改达到的效果:断线重连机制对应用层完全透明,无需自己重复发送请求。

消费进程中长时间消费不到数据,mysql设置的自动断开时间超过后,mysql自动断线,服务端报mysql gone away,这时需要捕获异常重连并重试。或者将长连接改为短连接也可以解决该问题。

解决

1 配置项新增

'db' => [

'class' => 'QttLib\Yii\Tracing\DBConnection',

'commandClass' => 'common\components\DbCommand',// 加上这一条配置,Yii2 解决2006 MySQL server has gone away问题

'dsn' => 'mysql:host=xxx;dbname=xx',

'username' => 'xx',

'password' => 'xxx',

'charset' => 'utf8',

'enableLogging' => true,

],

2 DbCommand.php文件内容:

php 复制代码
<?php
namespace app\models\common;

use app\components\China;

/**
 * 新增加执行sql时断开重连
 * 数据库连接断开异常
 * errorInfo = [''HY000',2006,'错误信息']
 * Class Command
 */
class Command extends \yii\db\Command
{
    public $retry;

    /**
     * 处理修改类型sql的断线重连问题
     * @return int
     * @throws \Exception
     * @throws \yii\db\Exception
     */
    public function execute()
    {
        try{
            return parent::execute();
        }catch(\Exception $e){
            China::logger($e->getMessage().'|'.$e->errorInfo,['prefix' => 'script_time_out_execute']);
            if($this->retryBecauseGongAway($e)) {
                return parent::execute();
            } else {
                throw $e;
            }
        }
    }

    /**
     * 处理查询类sql断线重连问题
     * @param string $method
     * @param null $fetchMode
     * @return mixed
     * @throws \Exception
     * @throws \yii\db\Exception
     */
    protected function queryInternal($method, $fetchMode = null)
    {
        try{
            return parent::queryInternal($method, $fetchMode);
        }catch(\Exception $e){
            China::logger($e->getMessage().'|'.json_encode($e->errorInfo,JSON_UNESCAPED_UNICODE),['prefix' => 'script_time_out_queryInternal']);
            //Error while sending QUERY packet. PID=30822
            if($this->retryBecauseGongAway($e)) {
                return parent::queryInternal($method, $fetchMode);
            } else {
                throw $e;
            }
        }
    }

    /**
     * 处理执行sql时捕获的异常信息
     * 并且根据异常信息来决定是否需要重新连接数据库
     * @param \Exception $e
     * @return bool true: 需要重新执行sql false: 不需要重新执行sql
     */
    private function retryBecauseGongAway(\Exception $e)
    {
        $condition1 = ($e instanceof \yii\db\Exception) && $e->errorInfo[0] == 'HY000' && $e->errorInfo[1] == '2006';
        $condition2 = strpos($e->getMessage(),'Error while sending QUERY packet') !== false;

        if ($condition1 || $condition2) {
            $this->retry = true;
            $this->pdoStatement = null;
            $this->db->close();
            $this->db->open();

            return true;
        }
        return false;
    }
    /**
     * 利用$this->retry属性,标记当前是否是数据库重连
     * 重写bindPendingParams方法,当当前是数据库重连之后重试的时候
     * 调用bindValues方法重新绑定一次参数.
     */
    protected function bindPendingParams()
    {
        if ($this->retry) {
            $this->retry = false;
            $this->bindValues($this->params);
        }
        parent::bindPendingParams();
    }
}
相关推荐
一只鹿鹿鹿3 小时前
政务外网整体设计方案(PPT)
大数据·数据库·web安全·系统安全·流程图·政务
2603_965148113 小时前
社区与学习资源:从入门到精通的API选品学习路径
数据库·人工智能·python·学习·数据挖掘
for_ever_love__3 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
AI砖家3 小时前
安全进入 Agent Loop:2027 年 Coding Agent 的决胜点
数据库·安全·codex·vibecoding
wangqiaowq4 小时前
SQL server C盘空间占满的处理
数据库·sql
文人sec4 小时前
SQL基础入门笔记 | 从零基础到掌握核心查询语句
数据库·笔记·sql
数字新视界4 小时前
机房动环监控提升运维效率
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
SelectDB技术团队4 小时前
冷热分层从建到验:Storage Policy 创建、表级与分区级绑定、SHOW TABLETS 验证的完整命令
大数据·数据库·elasticsearch·搜索引擎·数据分析·apache doris·冷热分层
lambo mercy6 小时前
Day3:结构化输出
java·数据库·oracle
派小心.6 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析