2017-11-25 2 views
0

エンティティXにはYエンティティのコレクションが含まれています。 YエンティティはエンティティXによって「私的に所有」されています。つまり、Yエンティティがコレクションから削除されると、データベースから完全に削除する必要があります。Doctrine 2:プリフラッシュイベントでエンティティを削除してフラッシュするときにメモリリークが発生する

これは通常orphanRemovalを使用して実現できますが、標準のフラッシュ順序(コレクションの削除前にコレクションを更新する前にコレクションを挿入する)のため、Yエンティティのユニーク制約は、新しいアイテムまたは更新されたアイテムに削除されたアイテムと同じ値。この問題に取り組むために

、私は手動で(orphanRemovalを使用せずに)別の配列に格納することで、コレクションから削除さY実体を追跡:

public function removeY(Y $y) : X 
{ 
    $y->setX(null); 
    $this->removedYItems[] = $y; 
    $this->yCollection->removeElement($y); 
    return $this; 
} 

flush操作が呼び出されると、私は手動でコミット私は明示的にOの更新前に、データベースから削除されたアイテムを確実にするためにflushを呼び出して終わり

/** 
* @ORM\PreFlush 
*/ 
public function onPreFlush(PreFlushEventArgs $eventArgs) : void 
{ 
    if (count($this->removedYItems) === 0) 
    { 
     return; 
    } 

    $entityManager = $eventArgs->getEntityManager(); 

    foreach ($this->removedYItems as $removedYItem) 
    { 
     $entityManager->remove($removedYItem); 
    } 

    $entityManager->flush(); 
} 

preFlushイベントで削除された項目r挿入。

ただし、Webページのフラッシュ操作を呼び出した後にハングアップするようだと、私は私のサーバーのログを見ると、PHPは(1GiB)、メモリが不足しているようだ:

[Sat Nov 25 00:32:14.016294 2017] [php7:error] [pid 22212] [client 192.168.0.1:59174] PHP Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 262144 bytes) in Unknown on line 0 

は、これは(知られています)Doctrineのバグがメモリリークを引き起こしていますか?または、preFlushイベントでflushに電話しないといけないのですか?(そうでないとドキュメントには:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preflush)?

私はDoctrine 2.5.9でFreeBSD 11.0 STABLEでPHP 7.1.11を実行しています。私はできるだけ早く別のマシンでこれをテストしようとします。

答えて

0

いくつかのテストを実行した後、preFlushイベントが(@ geolim4でヒントされているように)無限回帰ループでスタックしているようです。 GitHubのDoctrineリポジトリに問題を作成して、説明を求めましたが、これはドキュメントの誤りであると私に言った:https://github.com/doctrine/doctrine2/issues/6857

0

プロファイラを有効にして作業している場合は、Doctrineをオフにします。 する方法を参照してくださいhere。 Sfプロファイラは、大量のエンティティを扱う際に非常にメモリが欲しいと知られています。

+0

この問題は、フラッシュする前にスケジュールされたエンティティが1つのみであっても発生します(https://pastebin.com/raw/d9YCK11L)。ロギングを有効にしても、何もログに記録されず、メモリが制御不能になってしまいます。 –

+0

ああ私はそれを得ると思います。無限の再帰呼び出しがあります。 onPreFlush()は、onPreFlush()イベントなどを呼び出す$ entityManager-> flush()を呼び出しています。 – Geolim4

+0

これは実際の場合かもしれません。しかし、ドキュメンテーションは 'preflush'の中で' flush'を呼び出すことは安全だと明言しています(私の元の質問のリンクを参照)。おそらくこれはバグやドキュメントのエラーですか? –

関連する問題