我有一个使用Doctrine2框架在php + mysql平台上运行的应用程序。我需要在一个HTTP请求期间执行3个数据库查询:第一个INSERT,第二个SELECT,第三个UPDATE。 UPDATE取决于SELECT查询的结果。并发http请求的可能性很高。如果发生这种情况,并且DB查询混合在一起(例如INS1,INS2,SEL1,SEL2,UPD1,UPD2),将导致数据不一致。如何确保INS-SEL-UPD操作的原子性?我需要使用某种类型的锁,还是交易就足够了?
最佳答案
@YaK的答案实际上是一个很好的答案。您应该知道一般如何处理锁。
专门针对Doctrine2,您的代码应如下所示:
$em->getConnection()->beginTransaction();
try {
$toUpdate = $em->find('Entity\WhichWillBeUpdated', $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE);
// this will append FOR UPDATE http://docs.doctrine-project.org/en/2.0.x/reference/transactions-and-concurrency.html
$em->persist($anInsertedOne);
// you can flush here as well, to obtain the ID after insert if needed
$toUpdate->changeValue('new value');
$em->persist($toUpdate);
$em->flush();
$em->getConnection()->commit();
} catch (\Exception $e) {
$em->getConnection()->rollback();
throw $e;
}
随后的每个获取更新的请求将等待,直到该事务完成了获取了锁的一个进程为止。事务成功或失败后,MySQL将自动释放锁定。默认情况下,innodb锁定超时为50秒。因此,如果您的进程在50秒内未完成交易,它将回滚并自动释放锁。您在实体上不需要任何其他字段。
关于php - 并发学说,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11053402/