20

Redis の作業キューから作業を取得し、orm を使用してそれらのジョブとデータベースへの書き込みを実行する長時間実行デーモン (Symfony2 コマンド) があります。

作業を待っているアイドリング時に MySQL への接続がタイムアウトしたために、ワーカーが停止する傾向があることに気付きました。

具体的には、ログに次のように表示されます。MySQL Server has gone away.

とにかく教義を自動的に再接続させることはできますか? または、手動で例外をキャッチして教義 orm を再接続する方法はありますか?

ありがとう

4

5 に答える 5

29

私はsymfony2のbeanstalkdデーモンのコマンドワーカーでこれを使用しています:

$em = $this->getContainer()->get('doctrine')->getManager();
if ($em->getConnection()->ping() === false) {
    $em->getConnection()->close();
    $em->getConnection()->connect();
}
于 2014-11-06T23:15:12.947 に答える
12

DoctrineのEntityManagerでエラー/例外が発生すると、接続が閉じられ、EntityManagerが停止しているように見えます。

通常、すべてがトランザクションにラップされ、そのトランザクションは$ entityManager-> flush()が呼び出されたときに実行されるため、例外をキャッチして再実行またはあきらめることができます。

PDOExceptionか何か他のものかどうかにかかわらず、タイプのより具体的なキャッチを使用して、例外の正確な性質を調べることをお勧めします。

MySQLにGoneAway例外がある場合は、EntityManagerをリセットして再接続を試みることができます。

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

これにより、$emが再び使用可能になります。この$emは新しいため、すべてを再度永続化する必要があることに注意してください。

于 2013-01-02T17:32:41.963 に答える
9

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 にコミットされない可能性があります。

つまり、この方法を使用する場合は、必ずトランザクションをコミット/ロールバックしてください。

于 2013-08-02T13:54:39.253 に答える
5

これは、このラッパーで私にとってはうまくいきました:

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

于 2013-04-21T13:33:21.340 に答える