我有一个使用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/

10-13 02:02