问题
I have a function that looks like this:
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;
}
This function is used by various requests, and I've found that concurrent requests will sometimes try to create the same entity, throwing a DBALException complaining about duplicate entries for the unique key.
I've thought about LOCK TABLES as mentioned here:
How to lock a whole table in symfony2 with doctrine2?
But just given the fact there is no function to do this in Doctrine, I'm guessing it's not the preferred method. My question is, how can I prevent concurrent requests attempting to create the same entity and always return the correct one?
回答1:
As idea create own locking system:
something like:
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;
}
回答2:
But from what you told I think you are doing in wrong direction and it is better to rebuild app architecture little bit and put RabbitMQ queue as intermediate point to serve your requests
来源:https://stackoverflow.com/questions/29644717/concurrent-requests-trying-to-create-the-same-entity-if-not-exists-in-doctrine