MySQL错误2014的原因是,在其他未缓冲查询活动时无法执行查询。

14 浏览
0 Comments

MySQL错误2014的原因是,在其他未缓冲查询活动时无法执行查询。

我的服务器运行着CentOS 6.4操作系统,使用yum安装了MySQL 5.1.69,使用CentOS的仓库,以及使用yum安装了PHP 5.4.16,使用ius的仓库。 编辑3 升级到了MySQL服务器版本:5.5.31,由IUS社区项目提供分发,但错误仍然存在。然后将库更改为mysqlnd,并且似乎消除了错误。尽管如此,由于这种来回更改,需要知道为什么这个错误有时候才会出现。\n当使用PDO并使用PDO::ATTR_EMULATE_PREPARES=>false创建PDO对象时,有时会出现以下错误:\n

表名 - zipcodes
查询错误:
SELECT id FROM cities WHERE name=? AND states_id=?
SQLSTATE[HY000]: 一般错误:2014 无法在其他未缓冲查询处执行查询。请考虑使用PDOStatement::fetchAll()。或者,如果您的代码只会运行在mysql上,您可以通过设置PDO::MYSQL_ATTR_USE_BUFFERED_QUERY属性来启用查询缓冲。
文件名:/var/www/initial_install/build_database.php
行号:547
错误发生时间:2013年7月2日星期二,PDT时间5:52:48

\n第547行是以下代码的最后一行:\n

$stmt_check_county->execute(array($data[5],$data[4]));
if(!$county_id=$stmt_check_county->fetchColumn())
{
    $stmt_counties->execute(array($data[5]));
    $county_id=db::db()->lastInsertId();
}
//$stmt_check_county->closeCursor(); //这将修复错误
$stmt_check_city->execute(array($data[3],$data[4]));

\n我几年前遇到过类似的问题,但是从PHP 5.1升级到PHP 5.3(MySQL可能也更新了),问题神奇地消失了,现在我在PHP 5.5下又遇到了这个问题。\n为什么只有在PDO::ATTR_EMULATE_PREPARES=>false的情况下才会出现,并且只有在PHP的交替版本下才会出现?\n我还发现closeCursor()也可以修复这个错误。在每个不使用fetchAll()SELECT查询之后,是否应该始终执行此操作?请注意,即使查询只返回一个值,比如SELECT COUNT(col2),错误仍然会发生。\n编辑 顺便说一下,这是我创建连接的方式。我最近才添加了MYSQL_ATTR_USE_BUFFERED_QUERY=>true,然而,它并不能解决这个错误。 此外,以下脚本可以直接用来重现该错误。\n

function sql_error($e,$sql=NULL){return('

查询错误:

'.$sql.''.$e->getMessage().'文件名:'.$e->getFile().'行号:'.$e->getLine().'');} class db { private static $instance = NULL; private function __construct() {} //将构造函数设置为私有 private function __clone(){} //将克隆函数设置为私有 public static function db() //获取DB的实例 { if (!self::$instance) { //try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));} try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_EMULATE_PREPARES=>false,PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=>true,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));} //try{self::$instance = new PDO("mysql:host=localhost;dbname=myDB;charset=utf8",'myUsername','myPassword',array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC));} catch(PDOException $e){echo(sql_error($e));} } return self::$instance; } } $row=array( 'zipcodes_id'=>'55555', 'cities_id'=>123 ); $data=array($row,$row,$row,$row); $sql = 'CREATE TEMPORARY TABLE temp1(temp_id INT UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (temp_id) )'; db::db()->exec($sql); $sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes WHERE cities_id=? AND zipcodes_id=?'; $stmt1 = db::db()->prepare($sql); $sql ='SELECT temp_id FROM temp1'; $stmt2 = db::db()->prepare($sql); foreach($data AS $row) { try { $stmt1->execute(array($row['zipcodes_id'],$row['cities_id'])); $rs1 = $stmt1->fetch(PDO::FETCH_ASSOC); //$stmt1->closeCursor(); syslog(LOG_INFO,'$rs1: '.print_r($rs1,1).' '.rand()); $stmt2->execute(); $rs2 = $stmt2->fetch(PDO::FETCH_ASSOC); syslog(LOG_INFO,'$rs2: '.print_r($rs2,1).' '.rand()); } catch(PDOException $e){echo(sql_error($e));} } echo('完成');

0
0 Comments

MySQL error 2014 "Cannot execute queries while other unbuffered queries are active"出现的原因是在连接到数据库后执行第一个查询时返回了空结果,并出现了该错误。启用缓冲区也没有帮助。

问题的解决方法是移除初始命令PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET utf8; SET NAMES utf8"。正确的连接代码如下:

try { 
    $DBH = new PDO("mysql:host=$hostname;dbname=$db_name", $username, $password, 
    array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NUM));
} 
catch(PDOException $e) { echo $e->getMessage(); }

另外,不需要强制将MYSQL_ATTR_USE_BUFFERED_QUERY设置为true,因为它已经是默认设置。或者,你可以使用PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET utf8, NAMES utf8",使用逗号作为分隔符而不重复SET命令。

如果你真的想使用PDO::MYSQL_ATTR_INIT_COMMAND,则需要直接执行它并关闭游标。

0
0 Comments

MySQL错误2014“Cannot execute queries while other unbuffered queries are active”通常在使用PDO进行数据库查询时出现,可能由以下原因引起:

1. 设置PDO的ATTR_EMULATE_PREPARES参数为true,但不推荐此方法。

2. 设置PDO的MYSQL_ATTR_USE_BUFFERED_QUERY参数,但此方法可能不适用于所有情况。

3. 使用PDOStatement的fetchAll()方法,但这种方法不总是理想的。

4. 在每次使用$stmt->fetch()之后使用$stmt->closeCursor()方法,这种方法大多数情况下有效,但仍然可能有一些情况下无效。

5. 将PHP的MySQL库从php-mysql更改为php-mysqlnd,这可能是一个更好的解决方法。

此外,在使用PDO::exec()执行返回至少一行的查询时,无法关闭游标,任何后续的查询都会失败。推荐使用PDO::query()方法,并在之后使用$st->closeCursor()方法来关闭游标。

感谢评论中的建议,正是这个原因导致了我的问题!我在循环中使用exec()执行数据库更新操作,因为我不需要返回的数据(对于大多数查询来说,确实没有返回数据),但是有一些虚拟查询,比如SELECT DATABASE(),在执行下一个查询时会抛出异常,这使得这个问题非常难以找到和解决。

对于我来说,在每次使用$stmt->fetch()之后使用$stmt->closeCursor()方法解决了问题。

0
0 Comments

MySQL错误2014“无法在其他未缓冲查询处于活动状态时执行查询”的原因是MySQL客户端协议不允许同时进行多个查询。也就是说,当你执行一个查询并获取了部分结果(但不是全部),然后尝试执行第二个查询时,如果第一个查询仍有行需要返回,第二个查询就会出现错误。

客户端库通过在第一次获取时隐式地获取第一个查询的所有行,然后后续的获取只是在内部缓存的结果上迭代。这使得它们有机会关闭游标(就MySQL服务器而言)。这就是“缓冲查询”。这与使用fetchAll()的情况相同,因为这两种情况都必须在PHP客户端中分配足够的内存来容纳完整的结果集。

区别在于缓冲查询将结果保存在MySQL客户端库中,因此在按顺序获取每一行之前,PHP无法访问这些行。而fetchAll()立即为所有结果填充一个PHP数组,允许您访问任意行。

不使用fetchAll()的主要原因是结果可能太大,无法适应您的PHP内存限制。但是看起来您的查询结果只有一行,所以这不应该成为问题。

在您获取最后一行之前,可以使用closeCursor()“放弃”一个结果。MySQL服务器会被通知可以在服务器端丢弃该结果,然后您可以执行另一个查询。在完成给定的结果集的获取之前,不应该关闭游标。

另外:我注意到您在循环中一遍又一遍地执行$stmt2,但它每次都会返回相同的结果。根据将循环不变代码移出循环的原则,您应该在循环开始之前执行一次此操作,并将结果保存在PHP变量中。因此,无论是使用缓冲查询还是fetchAll(),您都不需要嵌套查询。

所以我建议您以以下方式编写代码:

$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
$stmt2->execute();
$rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$stmt2->closeCursor();
$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes 
      WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
$stmt1 = db::db()->prepare($sql);
foreach($data AS $row)
{
    try
    {
        $stmt1->execute($row);
        $rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
        $stmt1->closeCursor();
        syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
        syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
    }
    catch(PDOException $e){echo(sql_error($e));}            
}

注意我还使用了命名参数而不是位置参数,这样可以更简单地将$row作为参数值的数组传递。如果数组的键与参数名匹配,您只需要传递数组。在较旧版本的PHP中,您必须在数组键中包含冒号前缀,但现在不再需要。

最好使用mysqlnd。它具有更多功能,更节省内存,并且其许可证与PHP兼容。

$stmt1->closeCursor();$stmt2->closeCursor();是否多余,因为您使用了fetchAll()

我认为closeCursor()不是多余的。fetchAll()函数不会关闭游标,因此不会释放服务器端资源。

尽管我使用了fetchAll,但是如果没有closeCursor,它就无法工作,所以我赞同它们不是多余的。

我遇到了几乎相同的问题。如果您有空,请看看这个问题。

0