我有以下代码:
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare("SELECT 1");
$stmt->execute();
$result = $stmt->fetch();
$stmt->execute();
$result = $stmt->fetch();
$stmt = $dbh->prepare("SELECT 1");
$stmt->execute();
$result = $stmt->fetch();
但是,由于某种原因,在执行第二个准备好的语句时出现以下错误:
致命错误:未捕获的异常“PDOException”,带有消息“SQLSTATE [HY000]”:一般错误:2014 无法执行查询,而其他无缓冲查询处于活动状态。考虑使用 PDOStatement::fetchAll()。或者,如果您的代码只针对 mysql 运行,您可以通过设置 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 属性来启用查询缓冲。
我知道这个错误意味着什么以及如何修复它(要么做unset($stmt);
要么$stmt->closeCursor();
),所以我不是在寻找如何让它工作的解决方案。据我了解,这通常是由做fetch
而fetchAll
不是获取所有结果引起的。但是在这种情况下,只有一个结果并且正在被获取。另外,如果我只执行第一个准备好的语句一次,则不会发生错误。它仅在第一条语句执行两次时发生。它也只发生在PDO::ATTR_EMULATE_PREPARES
is时false
。
所以我的问题是,在这种情况下导致上述错误发生的原因是什么?它似乎与我执行过的任何其他查询没有任何不同。
我已经在两个 Ubuntu 13.10 服务器 Debian 和 CentOS 上对此进行了测试,并且都使用默认软件包产生了相同的错误。
编辑:
回答 Ryan Vincent 的评论,我是一个完整的 mysqli 菜鸟,但我相信我下面的内容大致相当于上面的例子。如果我错了,请纠正我。但是它不会产生错误,因此它似乎是一个 PDO-only 错误:
$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
die("Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error);
}
if (!($stmt = $mysqli->prepare("SELECT 1"))) {
die("Prepare 1 failed: (" . $mysqli->errno . ") " . $mysqli->error);
}
if (!$stmt->execute()) {
die("Execute 1 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();
if (!$stmt->execute()) {
die("Execute 2 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();
if (!($stmt = $mysqli->prepare("SELECT 1"))) {
// The following line is what fails in PDO
die("Prepare 2 failed: (" . $mysqli->errno . ") " . $mysqli->error);
}
if (!$stmt->execute()) {
die("Execute 3 failed: (" . $stmt->errno . ") " . $stmt->error);
}
$stmt->store_result();
$stmt->bind_result($col1);
$stmt->fetch();