php - 使用 PDO::ATTR_PERSISTENT = true 时,PDO::exec 和 PDO::query 之间有区别吗?

标签 php mysql pdo

PDO::ATTR_PERSISTENT = true 时,PDO::execPDO::query 之间似乎存在差异。当使用PDO::exec时,连接将不会被重用,并最终导致MySQL出现“连接数过多”错误,因为它们似乎没有被关闭(或重用)。

例如,请参阅这个小代码片段:

<?php

$pdo_attr = [
    PDO::ATTR_PERSISTENT => true,
];

$pdo = new PDO("mysql:host=mysql;dbname=empty", "root", "iamreallysecure", $pdo_attr);

// The following will give a to many connections error after a few browser refreshes (connection limit is set to 10)
var_dump($pdo->exec("SELECT 1"));

// While the following does NOT leave >10 connections open and continues to work
//var_dump($pdo->query("SELECT 1")->fetchAll());

exec 会将“休眠”MySQL 查询留在系统上(通过 SHOW PROCESSLIST 观察),而 query 不会触发此操作。

这是预期的吗?在这种情况下,exec 和 query 有什么区别?或者这可能是一个错误?

完全工作的(docker)示例位于 https://github.com/Mattie112/mysqltest

最佳答案

如果您使用 exec() 来执行 SELECT,那么您就已经做错了。此函数 ( as is mentioned in the manual ) 不会从数据库获取结果。它只能用于不产生结果集且没有变量输入的查询。如果查询产生结果,那么您需要使用相同的连接从 MySQL 获取该结果。

如果持久连接仍在使用中,则无法重复使用。发生这种情况的原因有很多,其中之一是未获取结果。 MySQL 将保持连接打开,等待客户端对结果集执行某些操作。从 MySQL 服务器获取完整结果后,它就可以接受新的查询。

这不仅是持久连接的问题,因为如果您在正常连接下一个接一个地使用 exec(),未获取的结果集也可能是一个问题。

$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
$pdo = new PDO("mysql:host=localhost;dbname=test;port=3307", "root", "", $options);

// The following will give:
// SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
var_dump($pdo->exec("SELECT 1"));
var_dump($pdo->exec("SELECT 1"));

PDOException: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in C:\wamp64\www\test\index.php on line 16

从标题中回答你的问题:是的。使用持久连接时使用 exec()query() 之间存在差异,但在不使用持久连接时也存在这种差异。

tl;dr:不要使用 exec() 进行查询,这会产生结果。请改用准备好的语句。

关于php - 使用 PDO::ATTR_PERSISTENT = true 时,PDO::exec 和 PDO::query 之间有区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59974191/

相关文章:

php - 如何验证数据库中的答案并显示正确答案?

php - 解析用于与 API 交互的 HTTP 状态代码

mysql - 在 mysql 中查找后继列或前列之间具有异常差异的列

PHP:DOMDocument loadHTML 在使用 HTML5 标签时返回错误

php - 如何单独显示SQL结果

php - 缓存大数据、替代查询或其他索引?

php - 这个 PHP 7 查询脚本有什么问题?

php - MySQL - 将许多小查询转换为大查询

php - 为什么我无法使用准备函数通过 PDO 更新行?

PHP 变量未通过 MySQL 更新查询加载