php yii2跑数出现mysql-gone-away-2006解决
问题描述:
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总结
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。