当通过Doctrine连接直接调用时,MySQL函数返回“缓存”结果

时间:2019-06-12 10:55:08

标签: php mysql symfony doctrine

我有一个MySQL函数,用于对提交的文档进行编号。它直接在MySQL服务器中实现(避免死锁,并发和类似的好处)。表存储了特定文档密钥的上次使用编号,函数使用该编号,将其递增,然后返回到Symfony应用程序,该应用程序将该编号分配给文档。

DELIMITER $$
FUNCTION `NEXT_NUMBER`(requested_key VARCHAR(255)) RETURNS int(11)
BEGIN
    DECLARE nextNumber INT;

    INSERT INTO `document_numbers` (key, last_number) VALUES (requested_key, 1)
        ON DUPLICATE KEY UPDATE last_number = last_number+1;
        SELECT last_number INTO nextNumber FROM `document_numbers` WHERE key = requested_key

   RETURN nextNumber;
END$$
DELIMITER ;

在应用程序中,此函数在单独的Doctrine连接中调用,该连接不用于标准实体和数据库操作。

public function getNewNumber(string $key) : int
{
    $this->connection->setAutoCommit(false);

    try {
        $this->connection->beginTransaction();
        $statement = $this->connection->prepare("SELECT NEXT_NUMBER(:key);");
        $statement->bindValue('series', $key);
        $statement->execute();
        $this->connection->commit();

        $number = (int) $statement->fetchColumn();

        $this->connection->close();
    } catch (\Throwable $e) {
        $this->connection->rollBack();
        $this->connection->close();
        throw $e;
    }

    return $number;
}

现在有问题的部分是

$number = (int) $statement->fetchColumn();

在多个HTTP请求中返回相同的值。与结果值将被缓存几乎完全相同。此行为不会重复100%的时间。我试图将SQL_NO_CACHE添加到SELECT查询中。

设置:

  • MySQL 5.7
  • Symfony 3.4
  • PHP 7.1
  • Doctrine / DBAL 2.7
  • OroPlatform 3.1

文档配置:

doctrine:
    dbal:
        default_connection:   default
        connections:
            default:
                server_version: '5.7'
                driver:       "%database_driver%"
                host:         "%database_host%"
                port:         "%database_port%"
                dbname:       "%database_name%"
                user:         "%database_user%"
                password:     "%database_password%"
                charset:      UTF8MB4
                mapping_types:
                    bit: boolean
                    json: string
            secondary: # this one is used for $this->connection->prepare("SELECT NEXT_NUMBER(:key);");
                server_version: '5.7'
                driver:       "%database_driver%"
                host:         "%database_host_secondary%" # this is simply pointing to 127.0.1.1
                port:         "%database_port%"
                dbname:       "%database_name%"
                user:         "%database_user%"
                password:     "%database_password%"
                charset:      UTF8MB4

不存在MySQL / Doctrine缓存设置。

1 个答案:

答案 0 :(得分:0)

因此,一种解决方案是重新启用$this->connection->setAutoCommit(true);上的自动提交功能,尽管在Symfony 2.8和早期版本的Doctrine上使用相同的代码绝对不是这种情况。

此外,"SELECT NEXT_NUMBER(:key);"实际上正在返回递增的数字,而不是某些“缓存”版本,但是在递增之后没有将其提交到数据库表中。

我不知道这是怎么发生的,因为$this->connection->commit();被清楚地执行并且不会引发任何错误。也许MySQL / PHP / Doctrine以某种方式为该操作创建了独立的事务。但是,到目前为止,自动提交功能似乎还没有遇到任何问题,因此尽管可以对行为进行任何输入和描述,但问题本身也可能得到解决。