我有一个长时间运行的守护程序(Symfony2 Command)可以在Redis中的工作队列中运行,并使用orm执行这些作业并写入数据库。
我注意到,当工人怠速等待工作时,由于与MySQL的连接超时,工人有死亡的倾向。
具体来说,我在日志中看到了这一点:MySQL服务器已经消失。
无论如何我可以让学说自动重新连接吗?或者有什么方法可以手动捕获异常并重新连接学说orm?
由于
答案 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)
这个包装器适用于我:
答案 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,你可能需要静态调用它。