如何使用doctrine2锁定symfony2中的整个表?

时间:2012-06-29 04:43:35

标签: mysql symfony locking doctrine-orm

我需要使用doctrine锁定整个表(不是单行),如果可能的话,我希望在没有本机查询的情况下执行此操作。

pessimistic locking的文档仅介绍了如何通过以下方法锁定特定实体:

  • 的EntityManager#找到
  • 的EntityManager#锁
  • 查询#setLockMode

我有一个事务需要插入一行,其值取决于表中其余行的值,因此我需要阻止在该表上同时执行两个事务。

我正在使用显式事务划分,这应该适用于锁定(根据上面的文档)。

注意:在这种情况下,乐观锁定不够好,我负担不起重试交易。此外,查询不应该很慢,因此性能不是问题。

编辑:我举个例子。想象一下,你想手工构建一个auto_increment,你必须从表中选择max()来获取前一个结果才能插入下一个结果。您必须确保没有两个事务尝试插入相同的值,以防他们同时选择max()。

当auto_increment不好时,我正在寻找这个问题的一般解决方案,例如使用字符串,或多列,哈希或您必须在前一行集上进行的任何计算。

锁定是一个可靠的解决方案,与乐观锁定不同,您不必重试错误。

那么,有没有办法在学说中使用表锁定?

3 个答案:

答案 0 :(得分:2)

可能由Doctrine2 ORM select for update

重复

以下是一些相关代码:

try {
    $entity = $em->find('User', $theEntityId, LockMode::OPTIMISTIC, $expectedVersion);

    // do the work

    $em->flush();
} catch(OptimisticLockException $e) { 
    echo "Sorry, but someone else has already changed this entity. Please apply the changes again!";
}

LockMode :: OPTIMISTIC参数可能提供您所需的功能。

答案 1 :(得分:2)

到目前为止,根据建议,我尝试了这个:

$em->getConnection()->exec('LOCK TABLES table_name WRITE;'); //lock for write access

// calculate $new_number...

// persist $new_number on table_name...
$table_name->setCalculatedNumber($new_number);
$em->persist($table_name);
$em->flush();

$em->getConnection()->exec('UNLOCK TABLES;');

我用JMeter测试了它,并且锁定不能用于重负载(16个请求/秒)。跟踪显示其他实例在明确放弃之前获得了锁定。问题(由Jens建议)是flush()隐式地以START TRANSACTION开头,它会丢弃表锁。 使用本机更新为我解决了问题:

$em->getConnection()->exec('LOCK TABLES table_name WRITE;'); //lock for write access

// calculate $new_number...

// persist $new_number on table_name...
$em->getConnection()->executeUpdate("UPDATE table_name set ...;");    

$em->getConnection()->exec('UNLOCK TABLES;');
$em->refresh($table_name);

需要尾随刷新()以使后续查询结果中的计算数字可用

答案 2 :(得分:1)

通过查看Doctrine 2.x中的文档,我认为没有一种支持的锁定整个表的方法。你当然可以尝试通过Doctrine单独锁定所有记录,但这很麻烦,并不是一个好主意。

相反,我会使用Doctrine实体管理器在数据库上执行原始SQL ...

$em->getConnection()->exec('LOCK TABLES table_name WRITE;'); //lock for write access

然后在完成更新后......

$em->getConnection()->exec('UNLOCK TABLES;');

编辑:

从表格锁MySQL documentation开始......

  
      
  • 持有锁的会话可以读写表。

  •   
  • 只有持有锁的会话才能访问该表。在解除锁定之前,没有其他会话可以访问它。

  •   
  • 在保持WRITE锁定的情况下,锁定其他会话阻止对该表的请求。

  •   

我认为这里的第二点是关键,只有你的会话才能读/写该表。