TP5.0断线重连时内存溢出问题

http://www.ymfeb.cn/articles/65

在用多进程处理对账单时,我发现了一个问题,在子进程关闭后,主进程再次连接数据库时会报MySql server has gone away错误,这是由于在创建子进程时,linux会在父进程的基础上直接拷贝一个子进程,所以这里也会复制出一份数据库连接的socket的文件描述符,父进程和子进程中的socket文件描述符都指向内核中的同一个socket文件(ps:这个地方参考趣说网络协议第十三讲:套接字socket中的内容会更加明白一点),所以当子进程关闭时,也直接把这个socket连接给关闭,导致主进程失去了数据库连接。

所以在这个地方我使用了tp5的断线重连机制,当执行sql时如果检查到数据库返回的是MySql server has gone away,将重新建立一个数据库链接。然后问题出现了,当往数据库进行写操作时,这里陷入了死循环,达到设置的内存上线然后被kill掉。

然后我去看了一下源码,在Connection.php文件的447,抓取到了数据库的异常,然后判断是丢失了连接,所以调用了close方法并再次执行了execute:

} catch (\PDOException $e) {
if ($this->isBreak($e)) {
return $this->close()->execute($sql, $bind);
}
throw new PDOException($e, $this->config, $this->getLastsql());
}

然而在close方法中,并没有释放查询结果:

/**
* 关闭数据库(或者重新连接)
* @access public
* @return $this
*/
public function close()
{
$this->linkID = null;
$this->linkWrite = null;
$this->linkRead = null;
$this->links = [];
return $this;
}

导致在419行,这里$this->PDOStatement->queryString和$sql是相等,从而也不会去释放上一次的PDOStatemen,从而一直使用这个已经失去了连接的PDOStatemen去执行写操作,导致陷入了死循环:

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

所以解决办法就是在close方法中,将上一次的查询结果释放就行了,看了一下,最新版的tp框架中已经解决了这个问题了:

/**
* 关闭数据库(或者重新连接)
* @access public
* @return $this
*/
public function close()
{
$this->linkID = null;
$this->linkWrite = null;
$this->linkRead = null;
$this->links = [];
// 释放查询
$this->free();
return $this;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值