守护进程中的Doctrine2连接超时

时间:2012-12-27 19:56:12

标签: php symfony doctrine doctrine-orm

我有一个长时间运行的守护程序(Symfony2 Command)可以在Redis中的工作队列中运行,并使用orm执行这些作业并写入数据库。

我注意到,当工人怠速等待工作时,由于与MySQL的连接超时,工人有死亡的倾向。

具体来说,我在日志中看到了这一点:MySQL服务器已经消失。

无论如何我可以让学说自动重新连接吗?或者有什么方法可以手动捕获异常并重新连接学说orm?

由于

5 个答案:

答案 0 :(得分:23)

我在我的symfony2 beanstalkd守护程序命令worker中使用它:

$em = $this->getContainer()->get('doctrine')->getManager();
if ($em->getConnection()->ping() === false) {
    $em->getConnection()->close();
    $em->getConnection()->connect();
}

答案 1 :(得分:12)

似乎每当EnttrManager在Doctrine中遇到任何错误/异常时,连接都会关闭,EntityManager就会死机。

由于通常所有事务都包含在事务中,并且在调用$ entityManager-> flush()时执行事务,因此您可以尝试捕获异常并尝试重新执行或放弃。

您可能希望通过更具体的类型捕获来检查异常的确切性质,无论是PDOException还是其他。

对于MySQL有Gone Away异常,您可以尝试通过重置EntityManager来重新连接。

$managerRegistry = $this->getContainer()->get('doctrine');
$em = $managerRegistry->getEntityManager();
$managerRegistry->resetEntityManager();

这应该使$ em再次可用。请注意,您必须再次重新保留所有内容,因为此$ em是新的。

答案 2 :(得分:8)

我遇到了与PHP Gearman工作者和Doctrine 2相同的问题。

我提出的最干净的解决方案是:关闭并重新打开每个工作的连接:

<?php
public function doWork($job){
   /* @var $em \Doctrine\ORM\EntityManager */
   $em = Zend_Registry::getInstance()->entitymanager;
   $em->getConnection()->close();
   $em->getConnection()->connect();
}

<强>更新

上述解决方案无法应对交易状态。这意味着Doctrine \ DBAL \ Connection :: close()方法不会重置$ _transactionNestingLevel值,因此如果您不提交事务,那么将导致Doctrine与底层DBMS的转换状态不同步。这可能导致Doctrine默默地忽略begin / commit / rollback语句,并最终导致数据未被提交给DBMS。

换句话说:如果使用此方法,请务必提交/回滚事务。

答案 3 :(得分:5)

这个包装器适用于我:

https://github.com/doctrine/dbal/issues/1454

答案 4 :(得分:2)

在您的守护程序中,您可以添加方法以在每次查询之前重新启动连接。我正面临着使用盖尔曼工人的类似问题:

我在zend注册表中保留了连接数据,所以它看起来像这样:

private function resetDoctrineConnection() {
    $doctrineManager = Doctrine_Manager::getInstance();
    $doctrineManager->reset();
    $dsn = Zend_Registry::get('dsn');
    $manager = Doctrine_Manager::getInstance();
    $manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
    Doctrine_Manager::connection($dsn, 'doctrine');
}

如果是damenon,你可能需要静态调用它。