牛骨文教育服务平台(让学习变的简单)
博文笔记

php yii2跑数出现mysql-gone-away-2006解决

创建时间:2017-10-13 投稿人: 浏览次数:518

问题描述:

Error Info:

Array
(
    [0] => HY000
    [1] => 2006
    [2] => MySQL server has gone away
)

"用php跑数据 任务时间过长,每次都会出现这个,能帮忙把这个超时时间设置到最大吗,下周我们仔细看看这个是啥问题,之前用JDBC跑数 不会出现这个问题,应该是php,yii2一直拿connection没有释放"

JDBC中!=null 就close  这种事我觉得应该是框架做的 

上述可知用JDBC无此问题,用yii2频繁出现,定位是yii2的问题,gone-away意思是连接不见了,断掉了,那么有没有colse和open的方法呢,断掉了我们手动去open一下

查了一下open和close的写法为

Yii::$app->db->open();
Yii::$app->db->close();

思路是在

try{

//code

}catch(Exception $e){

//去判断 $e是不是2006,然后去open一下,然后再colse一下

}

每个方法都去写一个这样的try{}catch{}不是很科学,通常的做法是在顶级父类的afterAction或入口去拦截这样的错误

最终选取的做法,重载yiidbCommand的execute和queryInternal方法

阅读yiidbCommand源码可知

execute()--->所有的增删改操作的入口

queryInternal()---->所以的查询操作的入口

最终书写一个Command去继承yiidbCommand,然后在数据库db配置中把默认的command Class 改成我们自己写的子类command

scm 修改示例

"db => [
        "class"       => "yiidbConnection",
        "dsn"         => $scm_config["db.dsn"],
        "username"    => $scm_config["db.username"],
        "password"    => $scm_config["db.password"],
        "charset"     => "utf8",
        "tablePrefix" => "tb_",
        "commandClass" => "appcomponentsCommand"  //自己写的子类Command
    ],


<?php
/**
 * Created by PhpStorm.
 * User: liuyifan
 * Date: 16/09/17
 * Time: 下午 04:24
 */

namespace appcomponents;


use yiidbException;
use yiidbCommand as YiiCommand;

/**
 * Class Command
 * @package appcomponents
 * 解决mysql-gone-away 2006,2013的问题
 */
class Command extends YiiCommand
{
    const SLEEP_TIME = 60;

    /***
     * @return int
     * @throws Exception
     * 所有[增删改]操作调用
     */
    public function execute()
    {
        try {
            return parent::execute();
        } catch (Exception $e) {
            if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
                echo "[Mysql-".$e->errorInfo[1]."] problem handler with appcomponentsCommand execute()...".PHP_EOL;
                $this->db->close();
                $this->db->open();
                $this->pdoStatement = null ;
                sleep(self::SLEEP_TIME);
                return parent::execute();
            }else{
                throw $e;
            }
        }
    }


    /***
     * @param string $method
     * @param null $fetchMode
     * @return mixed
     * @throws Exception
     * 所有[查操作]都会调用queryInternal方法
     */
    protected function queryInternal($method, $fetchMode = null){
        try {
            return parent::queryInternal($method, $fetchMode);
        } catch (Exception $e) {
            if ($e->errorInfo[1] == 2006 || $e->errorInfo[1] == 2013) {
                echo "[Mysql-".$e->errorInfo[1]."] problem handler with appcomponentsCommand queryInternal()...".PHP_EOL;
                $this->db->close();
                $this->db->open();
                $this->pdoStatement = null ;

                sleep(self::SLEEP_TIME);
                return parent::queryInternal($method, $fetchMode);
            }else{
                throw $e;
            }
        }
    }

}


附上测试类

//php yii test/my-sql-gone-away-2006
    public function actionMySqlGoneAway2006() {
        $this->print_f("MySql_Gone_Away_2006  test......");



        $seconds = 20;
        $hours = $seconds/3600;
        $minutes = $seconds/60;

        $this->setMysqlInteractiveTimeout($seconds-10);
        $this->setMysqlWaitTimeout($seconds-10);

        Yii::$app->db->createCommand("select * from test")->queryAll();
        $this->print_f("sleep start ....");
        $this->print_f("sleep time {$hours}h={$minutes}m={$seconds}s ....");
        sleep($seconds);
        $this->print_f("sleep end ....");

        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("liuyifan",40)")->execute();
        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("xiuyuding",3)")->execute();
        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("wangyong",28)")->execute();
        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("guandongdong",26)")->execute();
        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("changhuanhuan",-1)")->execute();
        Yii::$app->db->createCommand("insert into test(name,age) VALUES ("wangdandan",-1)")->execute();

    }

    public function setMysqlInteractiveTimeout($seconds) {
        $sql = "set interactive_timeout=$seconds";
        Yii::$app->db->createCommand($sql)->execute();
    }

    public function setMysqlWaitTimeout($seconds) {
        $sql = "set wait_timeout=$seconds";
        Yii::$app->db->createCommand($sql)->execute();
    }


附造成mysql-gone-away-2006总结


声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。