gpt4 book ai didi

php - 教义异常 : Deadlock found when trying to get lock

转载 作者:可可西里 更新时间:2023-11-01 08:59:56 28 4
gpt4 key购买 nike

我有一个 Symfony 应用程序,它公开了移动应用程序使用的一组 JSON 网络服务。
在过去的几天里,我们有 许多并发用户 使用该应用程序(每天约 5000 次访问),并且 Doctrine 错误开始“随机”出现在我的日志中。它每天大约出现 2-3 次,这是错误:

Uncaught PHP Exception Doctrine\DBAL\Exception\DriverException: "An exception occurred while executing 'UPDATE fos_user_user SET current_crystals = ?, max_crystals = ?, updated_at = ? WHERE id = ?' with params [31, 34, "2017-12-19 09:31:18", 807]:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction" at /var/www/html/rollinz_cms/releases/98/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 115

更新用户表时似乎无法获得锁。 Controller 代码如下:

/**
* @Rest\Post("/api/badges/{id}/achieve", name="api_achieve_badge")
*/
public function achieveAction(Badge $badge = null)
{
if (!$badge) {
throw new NotFoundHttpException('Badge not found.');
}

$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$userBadge = $em->getRepository('AppBundle:UserBadge')->findBy(array(
'user' => $user,
'badge' => $badge,
));

if ($userBadge) {
throw new BadRequestHttpException('Badge already achieved.');
}

$userBadge = new UserBadge();
$userBadge
->setUser($user)
->setBadge($badge)
->setAchievedAt(new \DateTime())
;
$em->persist($userBadge);

// sets the rewards
$user->addCrystals($badge->getCrystals());

$em->flush();

return new ApiResponse(ApiResponse::STATUS_SUCCESS, array(
'current_crystals' => $user->getCurrentCrystals(),
'max_crystals' => $user->getMaxCrystals(),
));
}

我调查了 MySQL和 Doctrine 文档,但我找不到可靠的解决方案。 Doctrine 建议重试交易,但没有显示实际示例:

https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlock-example.html

try {
// process stuff
} catch (\Doctrine\DBAL\Exception\RetryableException $e) {
// retry the processing
}

This posts建议重试交易。我该怎么做?

会不会是服务器问题(访问太多),我必须提升服务器,或者代码有误,我必须明确处理代码中的死锁?

最佳答案

这是一个 MySQL 问题。多个并发事务阻塞相同的资源。

检查您是否有可能长时间阻塞记录的 cronjobs。

否则只是并发请求更新相同的数据,您可能更了解这些数据在哪里更新。

在 php 中重试的肮脏尝试:

$retry=0;
while (true) {
try {
// some more code
$em->flush();
return new ApiResponse(ApiResponse::STATUS_SUCCESS, array(
'current_crystals' => $user->getCurrentCrystals(),
'max_crystals' => $user->getMaxCrystals(),
));
} catch (DriverException $e) {
$retry++;
if($retry>3) { throw $e; }
sleep(1); //optional
}
}

关于php - 教义异常 : Deadlock found when trying to get lock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47885232/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com