【发布时间】:2015-09-02 22:30:18
【问题描述】:
这件事昨晚发生在我身上。我对错误的性质非常熟悉,但我仍然无法弄清楚是什么原因造成的。我可能有预感,但我不确定。我将从一些基本的应用信息开始:
我的应用有 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,另一方面是system_pages 和base_pages 共享ID,我认为这很容易导致:
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
这个理论有两个问题:
- 交易。这就是我最初使用它们的原因
- 在出错时,其他用户在应用上没有其他活动
重要提示:等待一分钟后,重新提交通过OK。
这可能是一些奇怪的MySQL 事务隔离错误吗?任何提示将不胜感激......
编辑:
部分数据库架构:
请忽略塞尔维亚语的列名
【问题讨论】:
-
试图保持多个表的主键同步总是有点不确定。我无法准确解释发生了什么,除非您在创建基本页面和其他页面之间有某种重定向,但生命很短。为每个表提供自己的自增主键,并使用常规外键链接两者。
-
关于这个的一些问题:哪个条目导致了这个错误,Systempage?如果出现错误,您是否有某种回滚?如果每个循环只填充一个实体,为什么要使用事务而不是刷新?最后,您能否确保这是当时唯一的请求,即使来自同一个用户(通过双击或类似的方式进行双重提交)?
-
Cerad,是的,它肯定是不确定的 :) 问题是,表
base_pages、text_pages和system_pages已经设置了它们的AUTO_INCREMENT字段。这实际上可能是问题的根本原因。我可以尝试调试问题并查看首先执行哪个查询(base_pages或system_pages),然后在后面的查询中删除自动增量。但是完全随机发生(到目前为止只有一次)确实让人很难确信它修复了任何东西:) -
CiTNOH,我相信
rollback是出现错误时的默认行为。否则,不会手动发出rollback调用。事务的想法是确保无法创建Loan而SystemPage不是。一个实体没有另一个实体不应该是有效的。至于双重提交,我可以看到这可能是一个问题,但如果一个已经处于活动状态,执行是否应该在beginTransaction()上停止?
标签: php mysql symfony doctrine-orm transactions