2

我不确定这是首选方法,但我想介绍我的解决方案,看看你们那里的 symfony2 向导是否对此有启发性的评论。

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

我知道这必须由代码处理,然后如果假设两个人将登录到同一个用户帐户注册交易,或者用户同时触发多个交易写入,我就会冒着为用户输入重复条目的风险time 和 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

或者这甚至可能是矫枉过正,我应该跳过表锁吗?

4

1 回答 1

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;');

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

于 2012-12-29T16:25:11.500 回答