yii2 + swoole 的模式下因为使用swoole做的常驻内存服务, 那么之前的设计思路会有一点偏差, 不是第一眼能看到的就是 mysql has gone away的问题

目前解决思路就是当sql命令报错mysql has gone away的时候就断开重连再重新执行一次

参考 Yii2实现mysql断线重连

重写一个command类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php
    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);
            }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;
        }
    }

在配置文件中关于db的配置给加上指定的class

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
    return [
        'components' => [
            'db' => [
                'class'   => 'yii\db\Connection',
                'commandClass' => 'common\components\Command',// 加上这个
                'username' => 'XXX',
                'password' => 'XXX',
                'dsn' => 'mysql:host=XXX;dbname=XXX;port=3306',
            ],
        ],
    ];

相关文章: Yii2实现mysql断线重连 在mysql中connection设置和wait-timeout的设置 查看mysql连接情况,以及连接超时时间设置 源码剖析Yii错误 Invalid parameter number: no parameters were bound Yii 数据库重连告别General error: 2006 MySQL server has gone away