背景
nsq消费进程中长时间消费不到数据,mysql设置的自动断开时间超过后,mysql自动断线,服务端报mysql gone away,这时需要捕获异常重连并重试。或者将长连接改为短连接也可以解决该问题。
解决
配置项新增
'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,
],
新增类
namespace common\components;
use Yii;
/**
* 新增加执行sql时断开重连
* 数据库连接断开异常
* errorInfo = [''HY000',2006,'错误信息']
* Class DbCommand
* @package common\components
*/
class DbCommand extends \yii\db\Command
{
const EVENT_DISCONNECT = 'disconnect';
/**
* 处理修改类型sql的断线重连问题
* @return int
* @throws \Exception
* @throws \yii\db\Exception
*/
public function execute()
{
try{
return parent::execute();
}catch(\Exception $e){
if($this->handleException($e))
return parent::execute();
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){
if($this->handleException($e))
return parent::queryInternal($method, $fetchMode);
throw $e;
}
}
/**
* 处理执行sql时捕获的异常信息
* 并且根据异常信息来决定是否需要重新连接数据库
* @param \Exception $e
* @return bool true: 需要重新执行sql false: 不需要重新执行sql
*/
private function handleException(\Exception $e)
{
//如果不是yii\db\Exception异常抛出该异常或者不是MySQL server has gone away
$offset = stripos($e->getMessage(),'MySQL server has gone away');
if(($e instanceof \yii\db\Exception) == false OR $offset === false)
return false;
$this->trigger(static::EVENT_DISCONNECT);
//将pdo设置从null
$this->pdoStatement = NULL;
$this->db->close();
return true;
}
}