使用PDO :: ATTR_PERSISTENT = true时PDO :: exec和PDO :: query之间是否有区别?

问题描述 投票:3回答:2

[具有PDO::exec时,PDO::queryPDO::ATTR_PERSISTENT = true之间似乎有所不同。使用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在这种情况下有什么区别?也许这是一个错误?

完整工作(泊坞窗)示例位于https://github.com/Mattie112/mysqltest

php mysql pdo
2个回答
3
投票

如果您将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]:常规错误:2014当其他无缓冲查询处于活动状态时,无法执行查询。考虑使用PDOStatement :: fetchAll()。另外,如果您的代码只针对mysql运行,则可以通过设置PDO :: MYSQL_ATTR_USE_BUFFERED_QUERY属性来启用查询缓冲。在第16行的C:\ wamp64 \ www \ test \ index.php中]

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

tl; dr:请勿将exec()用于产生结果的查询。请改用准备好的语句。


0
投票

您设法在这里混淆了一切

© www.soinside.com 2019 - 2024. All rights reserved.