我有一个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
- Oro平台3.1
Doctrine 配置:
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 缓存设置。
最佳答案
因此,一种解决方案是重新打开自动提交 $this->connection->setAutoCommit(true);
,尽管在 Symfony 上使用相同的代码时情况绝对不是这样2.8 和之前版本的 Doctrine。
此外,“SELECT NEXT_NUMBER(:key);”
实际上返回了递增的数字,而不是某些“缓存”版本,但在递增后没有将其提交到数据库表。
我不知道这是如何发生的,因为 $this->connection->commit();
已明确执行并且不会引发任何错误。也许 MySQL/PHP/Doctrine 正在以某种方式为操作创建单独的事务。然而,到目前为止,自动提交似乎没有遇到任何问题,因此问题本身可能已经解决,尽管任何对行为的输入和描述都将不胜感激。
关于php - 通过 Doctrine 连接直接调用 MySQL 函数返回 'cached' 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56560488/