这件事昨晚发生在我身上。我对错误的本质非常熟悉,但我仍然无法弄清楚可能导致错误的原因。我可能有预感,但我不确定。我将从一些基本的应用信息开始:
我的应用有3个实体:Loan
,SystemPage
和TextPage
。每当有人添加贷款时,都会向数据库添加一个或多个系统页面。基本上,它是这样的:
if ( $form->isValid()){
$this->em->getConnection()->beginTransation();
$this->em->persist($loan);
$this->em->flush();
while ($someCondition){
$page = new SystemPage();
//... Fill the necessary data into page
$page->setObject($loan);
$this->em->persist($page);
}
$this->em->flush();
$this->em->getConnection()->commit();
}
请忽略潜在的拼写错误,我通过记住
来写字面意思实体Loan
映射到表loans
,SystemPage
映射(通过继承映射)到system_pages
和base_pages
。后两者都有id
字段,设置为AUTO_INCREMENT
。
我的预感:还有另一张名为text_pages
的桌子。鉴于另一方面text_pages
和base_pages
以及另一方<{>> ID 上的system_pages
和base_pages
,我认为这很容易导致这种情况:
User1: Create BasePage, acquire autoincrement ID (value = 1)
User2: Create BasePage, acquire autoincrement ID (value = 1)
User1: Create TextPage, use the ID from step 1
User2: Create SystemPage, use the ID from step 2
这个理论存在两个问题:
重要提示:等待一分钟后,重新提交确认。
这可能是一些奇怪的MySQL
事务隔离错误吗?任何提示都将不胜感激......
DB Schema的一部分:
请忽略塞尔维亚语中的列名
答案 0 :(得分:1)
flush()操作刷新一个事务中的所有更改,因此这里有冗余代码......
您没有声明是否可以重现此错误,并且如果您可以提供数据库架构将会很方便。
答案 1 :(得分:1)
似乎这个问题没有正确答案,只有猜测,所以我会根据自己的经验提出一些故障排除方法,如下:
你提到应用程序上没有其他活动,但我会通过查看查询日志来检查它。必须存在重复执行的查询。
表格可能是两次意外提交的。用户双击提交按钮,或者如果UI没有响应,则再次单击。您可以通过在同一时间戳上查看表单上的POST请求的Apache日志文件来检查这个想法。您可能需要实施一些JavaScript代码,以防止双击您的表单页面提交按钮。
你的预感可能非常接近正确,因为存在某种竞争条件。使用事务不会阻止竞争条件,但它们确实提供了优雅回滚的方法。将代码包装在try / catch块中,以便捕获Mysql异常并向用户显示友好错误和重试选项。