相关文章推荐

Yii2实现数据库断线重连

在工作中,有时候一些后台脚本需要长时间的运行,同时可能在连接数据库后,长时间不与数据库服务端交互。此时,服务器可能会断开与客户端的连接。从而客户端再次交互时就会出现"MySQL server has gone away"连接丢失。
此次修改达到的效果:断线重连机制对应用层完全透明,无需自己重复发送请求。
一、重写\yii\db\Command类中的execute 与 queryInternal方法
namespace common\components; use Yii; * 新增加执行sql时断开重连 * 数据库连接断开异常 * errorInfo = [''HY000',2006,'错误信息'] * Class Command * @package common\components class Command 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 = null); }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) //OR $e->errorInfo[0] != 'HY000' OR $e->errorInfo[1] != 2006) return false; $this->trigger(static::EVENT_DISCONNECT); //将pdo设置从null $this->pdoStatement = NULL; $this->db->resetPdo(); //$this->db->close(); return true;
二、\yii\db\Connection类中新增加方法 resetPdo
* 重置连接信息 public function resetPdo() $this->_master = false; $this->_slave = false; $this->pdo = NULL; return [ 'components' => [ 'db' => [ 'class' => 'yii\db\Connection', 'commandClass' => 'common\components\Command', 'username' => 'XXX', 'password' => 'XXX', 'dsn' => 'mysql:host=XXX;dbname=XXX;port=3306',

修改中遇到的问题:

眼尖的同学可能已经看到了在上面的"handleException"函数中有段注释了的代码"OR $e->errorInfo[0] != 'HY000' OR $e->errorInfo[1] != 2006""$offset = stripos($e->getMessage(),'MySQL server has gone away');" 代替了。那是因为在断线的情况下,客户端首次请求时会产生一个"Error"与一个"PDOException"。由于Yii2在底层实现了一个错误处理函数。在捕获到错误后会转换成一个"ErrorException"导致"PDOException"被覆盖了。同时在"PDOException"中的错误状态码也获取不到了。如果你有更好的方案也希望您能在下面的留言中一起交流
        
                

3 条回复

 
推荐文章