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总结
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
