Doctrine如何处理多个请求?

时间:2016-06-11 19:22:41

标签: php mysql symfony doctrine-orm

我们说我有一个脚本可以将行插入数据库,它看起来像这样:

/* $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();

现在想象一下还没有对象(表格清晰),一个用户以start = 0进入网站。该脚本需要2秒钟才能完成。在完成之前 - 另一个用户以start = 50进入该站点。

我不确定在这种情况下究竟会发生什么,但我认为:

  1. 第一个用户输入 - $ ids数组为空,脚本生成ID为0-99的对象。

  2. 第二个用户输入 - $ em-&gt; flush表单第一个入口尚未调用,这意味着$ ids数组仍为空(我猜?)。该脚本生成id为50-149

  3. 的对象
  4. 第一个$ em-&gt; flush()调用来自第一个用户入口。它将对象0-99插入数据库。

  5. 第二个$ em-&gt; flush()调用来自第二个用户入口。它尝试将对象50-149插入数据库。它失败,因为数据库中已存在id = 50的对象。因此,它实际上并没有在数据库中插入任何内容。

  6. 那真的会发生什么?如果是这样 - 如何防止它以及只插入缺少数据库的那些对象的最佳方法是什么?

    @edit:这只是一个例子,但在真实的脚本中,id实际上是3列(x,y,z),对象是地图上的一个字段。这个脚本的目的是我希望有一个巨大的地图,一次生成它需要花费太多时间。所以我想只生成一点,然后只有当一些用户试图访问它们时才创建缺少的部分。在某些时候,将创建整个地图,但过程将是错开的。

1 个答案:

答案 0 :(得分:1)

这里有2个不良做法:

  1. 当用户进入您的站点时,您应该避免INSERT或UPDATE操作(因为它们很慢/成本很高),特别是如果它是在这个脚本中添加许多对象到数据库。它应该以某种cron脚本运行,独立于您的网站用户。
  2. 您不应事先将ID分配给对象。保留为null,Doctrine将为您处理。为什么需要提前设置ID?
  3. 要回答您的问题 - 如果您为具有预先分配的ID的对象调用$ em-&gt; persist(),并且如果数据库中存在具有相同ID的另一个对象,则不会发生INSERT。相反,现有对象将使用来自较新对象的数据进行更新(之后调用em-&gt; flush()时)。因此,不是2个对象(如预期的那样),数据库中只有1个。所以这就是为什么我真的怀疑你是否需要提前预先分配ID。你应该告诉我更多关于这个的目的:)