数据库断线重连

数据库断线重连是指,在服务器出现某些原因导致数据库连接中断,需要启动重新连接数据库,并重新执行中断的数据库操作。

Thinkphp5.0 是支持数据库断线重连的,代码很值得学习。它支持查询 query(包括select查询等读取操作),执行 execute (包括insert、update等写入操作)和 事务 startTrans() 的断线重连 这三种类型的数据库断线重连操作。

下面就拿 query 来看看如何处理。

/**
 * 执行查询 返回数据集
 * @access public
 * @param string        $sql sql指令
 * @param array         $bind 参数绑定
 * @param bool          $master 是否在主服务器读操作
 * @param bool          $pdo 是否返回PDO对象
 * @return mixed
 * @throws BindParamException
 * @throws PDOException
 */
public function query($sql, $bind = [], $master = false, $pdo = false)
{
    $this->initConnect($master);
    if (!$this->linkID) {
        return false;
    }

    // 记录SQL语句
    $this->queryStr = $sql;
    if ($bind) {
        $this->bind = $bind;
    }

    // 释放前次的查询结果
    if (!empty($this->PDOStatement)) {
        $this->free();
    }

    Db::$queryTimes++;
    try {
        // 调试开始
        $this->debug(true);
        // 预处理
        if (empty($this->PDOStatement)) {
            $this->PDOStatement = $this->linkID->prepare($sql);
        }
        // 是否为存储过程调用
        $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
        // 参数绑定
        if ($procedure) {
            $this->bindParam($bind);
        } else {
            $this->bindValue($bind);
        }
        // 执行查询
        $this->PDOStatement->execute();
        // 调试结束
        $this->debug(false);
        // 返回结果集
        return $this->getResult($pdo, $procedure);
    } catch (\PDOException $e) {
        if ($this->isBreak($e)) {
            return $this->close()->query($sql, $bind, $master, $pdo);
        }
        throw new PDOException($e, $this->config, $this->getLastsql());
    } catch (\ErrorException $e) {
        if ($this->isBreak($e)) {
            return $this->close()->query($sql, $bind, $master, $pdo);
        }
        throw $e;
    }
}

代码不难看,数据库接口使用PDO,可以很方便的使用各种数据库。
上面在执行到下面的时候,

$this->PDOStatement->execute();
//或者
$this->getResult($pdo, $procedure);

如果出现数据库断线,会抛出 PDOException 或 ErrorException 的异常。
通过 $this->isBreak($e) 来判断是否是数据库断线的情况,是的话就会关闭已打开的无效数据库资源,重新进行初始化和查询操作:

$this->close()->query($sql, $bind, $master, $pdo);



如何判断数据库断线?

关键代码贴上:

/**
 * 是否断线
 * @access protected
 * @param \PDOException  $e 异常对象
 * @return bool
 */
protected function isBreak($e)
{
    if (!$this->config['break_reconnect']) {
        return false;
    }

    $info = [
        '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',
    ];

    $error = $e->getMessage();

    foreach ($info as $msg) {
        if (false !== stripos($error, $msg)) {
            return true;
        }
    }
    return false;
}

断线的情况有这么多。。。(看 $info 数组)。

这个断线的判断是可配置的,需要将 config['break_reconnect'] 的值设置为 true, 才会执行断线判断。



-end-

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
发表日期:2017年6月6日
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值