symfony2 doctrine表锁

时间:2012-12-11 13:24:36

标签: database symfony doctrine locking serial-number

我不确定这是首选方法,但我想提出我的解决方案,看看symfony2向导是否对此有启发性的评论。

我正在表中注册金融交易,每个用户都有自己的一系列序列号(即每个用户的交易表将以1开头)。

我知道这必须由代码处理,然后我冒着为用户提供重复条目的风险,如果让我们说两个人会登录到注册事务的同一个用户帐户,或者用户触发多个事务写入同时,在第一次写火之前,Doctrine要在两个操作中做SELECT ...

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

            $results = $em->createQuery("SELECT MAX(t.serial) FROM ekonomiKassabokBundle:Transaction t WHERE t.user = $userId")->getResult();
            $temp = $results[0];
            $max_serial = $temp[1];
            $new_serial = $max_serial + 1;

            $entity->setSerial($new_serial);

            $em->persist($entity);
            $em->flush();

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

上面的代码给了我......

SQLSTATE[HY000]: General error: 1100 Table 't0_' was not locked with LOCK TABLES

或者这可能甚至有点过头了,我应该跳过表锁吗?

1 个答案:

答案 0 :(得分:3)

我最终找到了解决方案,嗯...... 一个解决方案。

实际上根据我的理解它是非常愚蠢的:当你锁定表时,MySQL期望你将使用所有表,直到解锁被锁定,这必须在一个LOCK TABLES语句中发生。

现在Doctrine将系统地使用表别名,无论出于何种原因,MySQL显然无法弄清楚别名是否指向锁定表...所以你必须专门锁定将自己使用的所有别名!

尝试:

$em->getConnection()->exec('LOCK TABLES transaction as t0_ WRITE;');

如果此后还有其他错误(如果在表被锁定时进行多次查询,则会发生错误),只需继续向其他别名添加锁定,例如:

$em->getConnection()->exec('LOCK TABLES transaction as t0_ WRITE, transaction as t0 WRITE, transaction as t1 WRITE;');

幸运的是,似乎主义总是使用相同的表别名,所以一旦你把它弄下来就应该继续工作!