如果Doctrine中不存在,则尝试创建相同实体的并发请求

时间:2015-04-15 08:00:57

标签: php mysql symfony doctrine-orm

我有一个看起来像这样的函数:

function findByAndCreateIfNotExists($criteria){

    $entity = $this->findBy(['criteria'=>$criteria]);

    // this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.

    if (! $entity) {
        $entity = $this->createEntity($criteria);
    }

    return $entity;
}

此功能被各种请求使用,我发现并发请求有时会尝试创建同一个实体,引发DBALException抱怨唯一密钥的重复条目。

我已经考虑过这里提到的LOCK TABLESHow to lock a whole table in symfony2 with doctrine2?

但是考虑到在Doctrine中没有这样做的功能,我猜测它并不是首选的方法。我的问题是,如何防止尝试创建同一实体的并发请求并始终返回正确的请求?

2 个答案:

答案 0 :(得分:1)

随着想法创建自己的锁定系统:

类似的东西:

function findByAndCreateIfNotExists($criteria){

    $entity = $this->findBy(['criteria'=>$criteria]);

    // this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.
    $lockPath ='/tmp/'.md5($criteria).'.lock';

    if (! $entity && !file_exists($lockPath)) {
        $fh = fopen($lockPath, 'w') or die("Can't create file");
        $entity = $this->createEntity($criteria);
        unlink(($lockPath);
    }

    return $entity;
}

答案 1 :(得分:0)

但是根据你的说法,我认为你的方向是错误的,最好稍微重建app架构并将RabbitMQ队列作为中间点来满足你的要求