【问题标题】:Is it possible that two requests at the same time double this code? (prevent double database entry)两个请求是否有可能同时加倍此代码? (防止双重数据库条目)
【发布时间】:2026-01-11 09:20:05
【问题描述】:

1) 控制器代码(Symfony2 框架):

    $em = $this->getDoctrine()->getEntityManager();

    // get latest toplist
    $last = $em->getRepository('RadioToplistBundle:Toplist')->findOneBy(
      array('number' => 'DESC')
    );

    // get current year and week of the year
    $week = date('W');
    $year = date('Y');

    // if:
    //   [case 1]: $last is null, meaning there are no toplists in the database
    //   [case 2]: $last->getYear() or $last->getWeek() do not match current
    //             year and week number, meaning that there are toplists in the
    //             database, but not for current week
    // then:
    //   create new toplist entity (for current week of current year)
    // else:
    //   do nothing (return)

    if($last && $last->getYear() == $year && $last->getWeek() == $week)
      return;
    else {
      $new = new Toplist();
      $new->setYear($year);
      $new->setWeek($week);
      $em->persist($new);
      $em->flush();
    }

此代码随每个请求执行以查看*列表结果(前端)或*列表列表(后端)。每当有人想要访问 toplist 时,我们首先检查是否应该创建一个新的 toplist 实体(用于新的一周)。

2) 问题是:

有没有可能:

  • 用户 A 于周一 00:00:01 访问 mydomain.com/toplist -> 代码应生成新实体
  • 服务器变慢了,他需要 3 秒来执行代码
  • 所以新的 toplist 实体会在周一 00:00:04 保存到数据库中
  • 用户 B 于周一 00:00:02 访问 mydomain.com/toplist
  • 在 00:00:02 时,toplist 尚未保存在数据库中,因此 UserB 的请求触发代码创建另一个 toplist 实体

所以.. 几秒钟后,我们有 2 个本周的*实体。

这可能吗?

我应该如何防止这种情况发生?

【问题讨论】:

    标签: database symfony request entity sametime


    【解决方案1】:

    是的,这是可能的。在执行基于 db 值(而不是存储在 db 中)的计算时,您应该使用锁。

    在教义的文档中阅读更多关于锁的信息:Locking support

    【讨论】:

    • 谢谢,现在我知道我必须重新考虑我的代码,我可能会使用锁定