Doctrine2:找不到具有findById的并发持久化实体



我有当前设置:

一个常规的Symfony2 web请求可以创建并持久化Job实体,该实体还创建了一个Gearman作业,比如说这发生在process 1中。Gearman作业由Gearman Worker执行,该Worker被传递给Job实体的ID

我还使用Symfony创建了一个Gearman Worker,它作为一个PHP CLI进程运行,让我们调用这个process 2

对于那些不熟悉Gearman的人来说,worker代码的操作方式如下:

for loop 5 times
get job from gearman (blocking method call)
get job entity from database
do stuff

从本质上讲,这段代码让一个Symfony2实例在工人死亡之前运行,以处理5个作业。

我的问题是:在工作人员处理的第一个作业上,Doctrine2能够使用以下代码从数据库中检索创建的作业而不会出现问题:

$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById($job->workload()); // workload is the job id

然而,一旦此作业完成,for循环增加以等待第二个作业,比如说,这是从process 3上的另一个Symfony2 web请求到达的,该请求使用ID2创建Job,则对Doctrine2存储库的调用返回null,即使实体肯定在数据库中。

重新启动worker解决了这个问题,所以当它执行第一个循环时,它可以选择Job2。

有人知道为什么会发生这种事吗?getRepositoryfindOneById的第一次调用是否从MySQL进行了某种表缓存,从而不允许它看到随后添加的Job2?

MySQL是否只显示给定连接的数据库快照,只要它处于打开状态?

在对findOneBy进行第二次调用之前,我也尝试过重置entityManager,但没有成功。

谢谢你提前给我的任何建议,这真的让我很困惑。

更新:

我创建了一个单独的流程测试用例来排除是否是并发导致了问题,并且测试用例按预期执行。存储库似乎唯一一次找不到作业2是在另一个进程中将其添加到数据库中时。

// Job 1 already exists
$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById(1);
$job->getId(); // this is fine.
$em->persist(new Job()); // creates job 2
$em->flush();
$job = $this->doctrine
->getRepository('AcmeJobBundle:Job')
->findOneById(2);
$job->getId(); // this is fine too, no exception.

也许一个进程试图在实体被第二个进程保存之前加载它。

Doctrine根据实体的id缓存加载的实体,这样当您收到对同一对象的第二个请求时,它就加载了,而无需对数据库进行另一次查询。你可以在这里阅读更多关于条令识别图

最新更新