关于数据库断线重连的一点点思考

最近在写数据库连接池,一个不可逃避的问题就是数据库断线重连。 查了不少资料,由于公司有不少项目用了 TP5 因而也去看了它的源码。php

tp5的实现其实很简单,配置了一些数据库链接相关的错误信息关键词(句),而后在执行语句时 catch 异常信息进行比对:mysql

// 服务器断线标识字符
    protected $breakMatchStr = [
        'server has gone away',
        'no connection to the server',
        'Lost connection',
        'is dead or not enabled',
        'Error while sending',
        'decryption failed or bad record mac',
        'server closed the connection unexpectedly',
        'SSL connection has been closed unexpectedly',
        'Error writing data to the connection',
        'Resource deadlock avoided',
        'failed with errno',
    ];
catch (\PDOException $e) {
            if ($this->isBreak($e)) {
                return $this->close()->query($sql, $bind, $master, $pdo);
            }
            throw new PDOException($e, $this->config, $this->getLastsql());
        }
protected function isBreak($e): bool
    {
        if (!$this->config['break_reconnect']) {
            return false;
        }
        $error = $e->getMessage();
        foreach ($this->breakMatchStr as $msg) {
            if (false !== stripos($error, $msg)) {
                return true;
            }
        }
        return false;
    }

(噢 忽然发现5.2已经开始使用 php7新特性了)sql

感受用 errMessage 没有 errCode 靠谱吧,可是用 errCode 也很头疼啊,我要搜集各类数据库的链接相关的错误码,tp5自带的那些错误信息也只是 mysql 的吧,至少没看见sqlserver 的“TCP Provider: Error code 0x2746”,个人链接池是想支持多种数据库的。。。数据库

正在头疼的时候,忽然灵光一现:服务器

从链接池取出db链接对象时,先执行一句相似“select 1”这样的很是简单、不会有语法错误、与业务无关(表无关、字段无关。。。) 的语句,若是报错则理论上证实即便不是链接问题 它也已经不能正常执行业务SQL了,再加一个重连次数限制,防止特殊状况下有可能发生的死循环。。。应该就完美了。。。php7

/**
     * 检查 db链接对象 是否可用, 主要针对断线重连
     * @param $dbKey
     * @return bool
     */
    static private function _check($dbKey)
    {
        try {
            self::$dbUsing[$dbKey]->check();
        } catch (\Exception $e) {
            return false;
        }
        return true;
    }
function check(){
        $this->prepare('select 1');
        return $this->execute();
    }

还有一种思路是作“心跳”检查,定时把链接池里的对象“请”出来“遛”一下,使其保持“活力”。。。可是这个和断线重连并不冲突,能够叠加使用,效果更好。。。ide


另:在测试中发现,mysql 好像能够自动重连具体表现为:在一个断开的 pdo链接对象执行第一句sql 时 catch 了异常并让代码继续执行,则后面的 sql 就能够执行成功。sqlserver

我在网上没有查到这一行为相关资料,因此不肯定它与 pdo 有关或是 mysql 的功能 又是否跟mysql版本有关。。。测试

相关文章
相关标签/搜索