У меня есть длинный демон (Symfony2 Command), который получает работу из рабочей очереди в Redis и выполняет эти задания и записывает в базу данных с помощью orm.
Я заметил, что когда есть тенденция к тому, что работник умрет, потому что связь с MySQL приурочена, когда рабочий работает на холостом ходу, ожидая работы.
В частности, я вижу это в журнале: MySQL Server ушел.
Есть ли в любом случае, что учение может автоматически подключаться? Или есть способ, которым я могу вручную поймать исключение и снова подключить доктрину orm?
благодаря
Я использую это в моем Symfony2 beanstalkd daemon Командный рабочий:
$em = $this->getContainer()->get('doctrine')->getManager(); if ($em->getConnection()->ping() === false) { $em->getConnection()->close(); $em->getConnection()->connect(); }
Похоже, что всякий раз, когда в Doctrine возникает ошибка / исключение, встречающееся в EntityManager, соединение закрывается и EntityManager мертв.
Поскольку, как правило, все заключено в транзакцию и транзакция выполняется, когда вызывается $ entityManager-> flush (), вы можете попытаться поймать исключение и попытаться повторно удалить или отказаться.
Вы можете изучить точный характер исключения с более конкретным уловом типа, будь то PDOException или что-то еще.
Для исключения MySQL Gone Away вы можете попытаться восстановить соединение, сбросив EntityManager.
$managerRegistry = $this->getContainer()->get('doctrine'); $em = $managerRegistry->getEntityManager(); $managerRegistry->resetEntityManager();
Это должно снова использовать $ em. Обратите внимание, что вам придется повторно сохранить все снова, так как это $ em является новым.
У меня была такая же проблема с работником 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 не будет синхронизироваться с статусом трансляции с базовыми СУБД , Это может привести к тому, что Doctrine молча игнорирует операторы start / commit / rollback и, в конечном итоге, данные, которые не передаются в СУБД.
Другими словами: не забудьте совершить транзакции / откат, если вы используете этот метод.
Это с этой оберткой это сработало для меня:
В вашем демоне вы можете добавить метод перезапуска соединения, возможно, перед каждым запросом. Я столкнулся с подобными проблемами с использованием рабочего gaerman:
Я сохраняю данные подключения в 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'); }
Если это проклятие, вам нужно, возможно, назвать его статически.