我有一个Symfony应用程序,它公开了一个移动的应用程序使用的JSON Web服务集合。
在过去的几天里,我们有许多并发用户使用该应用程序(每天约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
字符串
更新用户表时似乎无法获取锁。控制器代码如下:
/**
* @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建议重试事务。我该怎么做?
可能是服务器的问题(访问太多),我必须提升服务器,或者代码错误,我必须在代码中显式处理死锁?
3条答案
按热度按时间jyztefdp1#
这是MySQL的问题。多个并发事务阻塞相同的资源。
检查您是否有可能长时间阻止记录的cronjobs。
否则,只是并发请求更新相同的数据,您可能会更好地了解这些数据在哪里更新。
在php中尝试一次错误的重试:
字符串
jtoj6r0c2#
Albert的解决方案是正确的,但您还必须使用ManagerRegistry的resetManager()在catch子句中重新创建一个新的EntityManager。如果您继续使用旧的EntityManager,您将获得异常,并且其行为将不可预测。也要注意对旧EntityManager的引用。
这个问题有望在学说3中得到纠正:See issue
在此之前,我的建议是妥善处理这个问题:Custom EntityManager的
7d7tgy0s3#
在@albert的基础上(thx)
1.将use添加到文件
use Doctrine\DBAL\Exception\DeadlockException;
的顶部1.将此函数添加到一个类(例如服务)
字符串
1.重新定义
型
1.就像
型