当两个用户同时投票时出现僵局

问题描述 投票:0回答:1

我在Symfony 3.4应用程序中遇到问题,在该应用程序中,用户可以对其他用户的条目进行投票。它使用FOSRestBundle用于API,使用Doctrine进行数据持久化。代码很简单:

public function voteEntryAction(Request $request, ChallengeEntry $challengeEntry)
{
    /** @var User */
    $user = $this->getUser();
    $em   = $this->getDoctrine()->getManager();

    $challengeVote = $em->getRepository(ChallengeVote::class)->findOneBy([
        'user'           => $user,
        'challengeEntry' => $challengeEntry,
    ]);

    if ($challengeVote) {
        throw new BadRequestHttpException('User has already voted for this challenge entry.');
    }

    $challengeVote = new ChallengeVote();
    $challengeVote
        ->setUser($user)
        ->setChallengeEntry($challengeEntry)
    ;

    $form = $this->createForm(ChallengeVoteType::class, $challengeVote);
    $form->submit($request->request->all());

    if ($form->isSubmitted() && $form->isValid()) {
        $em->persist($challengeVote);

        // updates the statistics
        $user->addGivenChallengeVote($challengeVote); // <=== here and the next line are the problematic lines

        $challengeEntry->getUser()->addReceivedChallengeVote($challengeVote); // <=== here and the previous line are the problematic lines

        // SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction
        $em->flush();

        return $user;
    }

    return $this->view($data, Response::HTTP_BAD_REQUEST);
}

有时我会收到此错误:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

我能够重现此错误,它发生在[[当两个用户同时投票时。这是因为每个用户都在更新彼此。我该如何解决?

我尝试了以下选项:

尝试解决方案1

我在另一个用户的更新之前添加了另一个$em->flush。并非最佳,但似乎可以工作:

// updates the statistics $user->addGivenChallengeVote($challengeVote); $em->flush(); // adds a different flush for the other user in order to avoid the following error: // SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction $challengeEntry->getUser()->addReceivedChallengeVote($challengeVote); $em->flush();

尝试解决方案2

我已经尝试捕获RetryableException并再次执行刷新,但收到错误The EntityManager is closed

尝试解决方案3

我尝试使用$em->resetManager()重置EntityManager,但随后所有实体都被分离,甚至用户也被认为是新用户。
symfony doctrine deadlock
1个回答
0
投票
您在正确的轨道上,但是错过了关键要素。重置实体管理器后,您需要再次选择您的实体,这还是更好的选择。

这里是一篇很棒的博客文章,例如:link

© www.soinside.com 2019 - 2024. All rights reserved.