2

私は Symfony 2.2 アプリケーションを持っています。このアプリケーションには、DB 内のエンティティを処理するために子をフォークするコマンドがあります。分岐した各子プロセスで Doctrine を強制的に再接続させる適切な方法を見つけるのに苦労しています。

最終的に 1 つのソリューションが機能するようになりました (各子の dev.log で新しい DB 接続を確認できます) が、それが最善の方法であるかどうかはわかりません。コンテナーを各子に渡し、子は新しい接続を作成し、その接続で default_connection サービスを設定します。しかし、これは少し厄介なようです。これについて他に考えはありますか?

$conn = $this->container->get('doctrine')->getConnection();
$conn2 = \Doctrine\DBAL\DriverManager::getConnection($conn->getParams(), $conn->getConfiguration(), $conn->getEventManager());
$this->container->set('doctrine.dbal.default_connection', $conn2);
$this->doctrine = $this->container->get('doctrine');
$this->doctrine->resetManager();

これは子プロセスで行われ、親には影響しませんが、default_connection を変更するという考えは好きではありません。不潔に見えるだけです。

4

2 に答える 2

4

いくつかの調査の後、私は自分でこれを理解しました。

上記の私のアプローチは完全には機能せず、必要以上に複雑です。注意すべき主なことは、子が終了したときにデータベース接続に何が起こるかです。

ほとんどの開発者は、プロセスを fork すると、DB 接続などのリソースを含むすべてのコピーを子プロセスが取得することを知っておく必要があります。ただし、難しいのは、フォークされた子が終了すると、それらのリソースが閉じられることです。これは、子が親から共有した同じ DB 接続を閉じることを意味します。

子が終了すると、親はすぐに無効な DB 接続を持ち、親でクエリを実行しようとすると「Mysql server has gone away」のようなエラーが発生します。

この問題を回避する 1 つの解決策は、親が子をフォークした直後に常に DB に再接続するようにすることです。つまり、100 人の子をフォークすると、親は 100 回再接続する必要があります。子と親がすべて DB とやり取りする必要がある場合、これは避けられないオーバーヘッドです。

したがって、私のコードでは、現在、子をフォークした直後に次のようなことを行っています。

$conn = $this->getContainer()->get('doctrine')->getConnection();
$conn->close();
$conn->connect();

mysql クライアントで「show processlist」を実行すると、フォークされた子ごとに 1 つずつ、複数の接続が表示されるようになります。

親に結果を返すことができる多くのワーカー プロセスを作成するための使いやすい API を提供する githubのProcessPoolライブラリも作成しました。

于 2013-06-04T15:04:53.897 に答える
1

私のシェル スクリプトでは、フォークする前にこれを使用して、すべての接続が閉じていることを確認しました。

// Close connections
$connections = $this->getContainer()
    ->get('doctrine')
    ->getConnections();
foreach($connections as $conn) {
    $this->logger->debug("Closing connection");
    $conn->close();
}
于 2013-07-18T13:14:51.483 に答える