2016-06-11 5 views
1

のは、私はデータベースに行を挿入するスクリプトを持っており、それは次のようになりましょう:Doctrineは複数のリクエストをどのように処理しますか?

/* $start is some GET parameter. Any number between 0 and 9900 */ 

/* Select all objects with ids between $start and $start+99 
and put their ids into $ids array */ 
$qb->select('object'); 
$qb->from('AppBundle:Object','object'); 
$qb->where("object.id >= $start"); 
$qb->andWhere("object.id < $start+100"); 
$objects = $qb->getQuery()->getResult(); 

$ids = array(); 
foreach($objects AS $object) { 
    $ids[] = $object->getId(); 
} 

/* Create missing objects and insert them into database */ 
for($id=$start; $id<$start+100; ++$id) { 
    if(in_array($id, $ids)) continue; 
    /* Some calculations */ 
    $createdObject = new Object($id, $some, $data); 
    $em->persist($createdObject); 
} 
$em->flush(); 

今そこにまだオブジェクトではない(表がクリアされている)と1人のユーザーが= 0を開始して、サイトに入り、想像。スクリプトの実行には2秒かかります。終了する前に、別のユーザーがstart = 50でサイトに入ります。

私はまさにこのようなシナリオでは何が起こるかわからないんだけど、私はあることpersume:

  1. まず、ユーザが入力する - $ IDS配列が空の場合、スクリプトはID 0-99でオブジェクトを生成しています。

  2. 2人目のユーザーが入ります - 最初の入り口がまだ呼び出されていない$ em-> flush形式です。これは$ ids配列がまだ空であることを意味します(私は思いますか?)。このスクリプトはidを持つオブジェクトを生成しています。50-149

  3. 最初のユーザー入口から$ em-> flush()呼び出しがあります。オブジェクト0-99をデータベースに挿入します。

  4. 2番目のユーザー入力から2番目の$ em-> flush()呼び出しがあります。オブジェクト50-149をデータベースに挿入しようとします。 id = 50のオブジェクトがすでにデータベースに存在するため、失敗します。その結果、実際には何もデータベースに挿入されません。

本当に起こるのでしょうか?もしそうなら、それを防ぐ方法と、データベースに欠けているオブジェクトだけを挿入する最良の方法は何ですか?

@edit:これは単なるexmapleコードですが、実際のスクリプトではidは実際には3つの列(x、y、z)で、オブジェクトはマップ上のフィールドです。このスクリプトの目的は、巨大なマップを作成したいと同時に、すべてを一度に生成するには時間がかかりすぎるということです。だから私は少しだけ生成し、いくつかのユーザーがそれらにアクセスしようとするときに欠落部分を作成したいと思います。ある時点でマップ全体が作成されますが、プロセスはずらされます。

+0

http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html – ceejayoz

答えて

1

あなたはここ2つの、悪い習慣を持っている:

  1. (彼らは/遅い高価であるため)、ユーザーがサイトを入力するときは、それはのようにデータベースに多くのオブジェクトを追加することについてです場合は特に、INSERTまたはUPDATE操作を避けるsouldこのスクリプト。それはあなたのウェブサイトのユーザーから独立して、何らかの種類のcronスクリプトで動くべきです。
  2. 事前にオブジェクトにIDを割り当てるべきではありません。それをnullのままにしておけば、Doctrineがそれを処理します。 IDを事前に設定する必要があるのはなぜですか?

あなたの質問に答えるために - あなたは$ EM-呼び出す場合>(持続)事前に割り当てられたIDを持つオブジェクトのために、ケース内の別のオブジェクトは、同じIDを持つデータベースに存在する - INSERTは発生しません。代わりに、既存のオブジェクトは新しいオブジェクトのデータで更新されます(後でem-> flush()を呼び出すとき)。したがって、2つのオブジェクトの代わりに(期待どおり)、データベースには1つしかありません。ですから、IDを事前に事前に割り当てる必要があるかどうかは本当に疑問です。この目的の詳細について私に教えてください:)

+0

実際には、 。 '$ em-> persist()'はDB内の 'update'を行いません。 [ドキュメンテーション](http://doctrine-orm.readthedocs。io/projects/doctrine-orm/en/latest/reference/working-with-objects.html#persisting-entities)、 'Xが分離エンティティの場合、例外時に例外がスローされます。すでにDBに存在する場合、この新しいエンティティはDoctrineの観点から「分離」エンティティになります。 – djxak

+0

実際のスクリプトでは、idは実際には3つの列です:x、y、zはマップ上のフィールドの座標です。このスクリプトの目的は、巨大なマップを作成したいと同時に、すべてを一度に生成するには時間がかかりすぎるということです。だから私は少しだけ生成し、いくつかのユーザーがそれらにアクセスしようとするときに欠落部分を作成したいと思います。ある時点でマップ全体が作成されますが、プロセスはずらされます。 –

関連する問題