当前位置: 首页 > 知识库问答 >
问题:

MySQL错误的原因2014无法在其他未缓冲查询处于活动状态时执行查询

陶飞英
2023-03-14

我的服务器运行CentOS 6.4和MySQL 5.1。69使用yum、CentOS的repos和PHP 5.4安装。16使用yum和ius的repos安装。Edit3升级到MySQL服务器版本:5.5。31由IUS社区项目分发,错误仍然存在。然后将库更改为mysqlnd,似乎消除了错误。尽管如此,我们仍然需要知道为什么这个错误只是偶尔出现。

当使用PDO并使用PDO创建PDO对象时::ATTR_EMULATE_PREPARES=

Table Name - zipcodes
Error in query:
SELECT id FROM cities WHERE name=? AND states_id=?
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.
File Name: /var/www/initial_install/build_database.php
Line: 547
Time of Error: Tuesday July 2, 2013, 5:52:48 PDT

第547行是最后一行:

$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(); //This will fix the error
$stmt_check_city->execute(array($data[3],$data[4]));

几年前我也遇到过类似的问题,但是从PHP 5.1升级到PHP 5.3(MySQL可能也更新了),这个问题奇迹般地消失了,现在我有了PHP 5.5。

为什么它只有在PDO::ATTR\u EMULATE\u准备就绪时才会显示出来=

我还发现closeCursor()也会修复错误。在不使用fetchAll()的每个SELECT查询之后,是否应始终执行此操作?请注意,即使查询类似于只返回一个值的selectcount(col2),仍然会发生错误。

顺便说一下,这是我创建连接的方式。我最近才添加了MYSQL\u ATTR\u USE\u BUFFERED\u查询=

function sql_error($e,$sql=NULL){return('<h1>Error in query:</h1><p>'.$sql.'</p><p>'.$e->getMessage().'</p><p>File Name: '.$e->getFile().' Line: '.$e->getLine().'</p>');}

class db {
    private static $instance = NULL;
    private function __construct() {}   //Make private
    private function __clone(){}   //Make private
    public static function db() //Get instance of 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('done');

共有3个答案

桓修能
2023-03-14

我几乎有同样的问题。连接到db后的第一次查询返回空结果并删除此错误。启用缓冲区没有帮助。

我的连接代码是:

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

我的解决方案是删除初始命令:

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不是被迫的。它被设置为默认值。

令狐昂雄
2023-03-14

我希望得到比下面更好的答案。虽然其中一些解决方案可能“修复”了问题,但它们并没有回答关于是什么导致了此错误的原始问题。

  1. 设置PDO::ATTR\u仿真=

龙永逸
2023-03-14

MySQL客户端协议不允许多个查询“正在进行”也就是说,您已经执行了一个查询,并且获得了一些结果,但不是全部——然后您尝试执行第二个查询。如果第一个查询仍有行要返回,则第二个查询会出错。

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

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

不使用finchAll()的主要原因是结果可能太大,无法放入PHPmemory_limit。但是查询结果似乎只有一行,所以这应该不成问题。

在获取最后一行之前,可以关闭游标()以“放弃”结果。MySQL服务器收到通知,它可以在服务器端放弃该结果,然后您可以执行另一个查询。在获取给定的结果集之前,不应关闭cursor()。

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

因此,我建议您这样编写代码:

$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兼容。

 类似资料:
  • 问题内容: 我的服务器运行CentOS 6.4,并使用yum和CentOS的存储库安装MySQL 5.1.69,以及使用yum和ius的存储库安装的PHP 5.4.16。 Edit3 升级到MySQL服务器版本:5.5.31由IUS社区项目分发,并且错误仍然存​​在。然后将库更改为mysqlnd,似乎消除了该错误。仍然要反复进行此操作,以了解为什么有时仅出现此错误。 使用PDO并使用创建PDO对象

  • 我们正在将应用程序从JBoss EAP 6.4迁移到WildFly 14。我们遇到了Hibernate和Infinispan的问题。 该应用程序被配置为使用Hibernate的二级缓存(也称为2LC)和Wildfly提供的Infinispan。 在启用2LC缓存但禁用查询缓存的情况下,应用程序启动并似乎正常工作。 但是当我们尝试再次启用查询缓存(属性hibernate.cache.use_quer

  • 问题内容: 是否有可能使MySQL中的行处于非活动状态?因此,该行不再用于查询结果吗?我的客户希望保留删除的成员在数据库中的存在,但是我不想编辑所有查询以检查该成员是否被删除。 还是有一种简单的方法将整个行数据移动到另一个“非活动”表中? 问题答案: 您可以重命名当前表,在其中创建“ deleted”列,然后创建一个与当前表同名的视图,并选择“ deleted = 0”。这样,您不必更改所有查询。

  • 问题内容: 简单的说,我总是对PHP / MySQL缓冲查询和非缓冲查询之间的区别是,缓冲(默认)将所有数据加载到结果集变量中, 然后 您可以开始使用它们,而无缓冲则在以下位置加载行:一个时间。 假设您先运行然后进行了,它将包含所有行和补充信息,例如行数。因此,如果您在100MB的数据库上执行此操作,那么如果那里没有索引,则可能会占用约100MB的空间)。 但是,我遇到了这样的SO溢出问题,其中一

  • 问题内容: 在MySQL以外的任何事物中,它感觉都非常简单。 基本上,我需要根据一个特定术语返回多少结果来切换我正在使用的索引类型以及其他一些条件。 效果: MySQL语句中可能吗? 编辑: 查询A: 查询B: 查询切换的原因是,根据“术语”的流行程度,我得到的结果时间截然不同。 问题答案: 编辑: 我下面说的关于要求存储过程的说法是不正确的。尝试这个: 确实,这是一个case表达式,在存储的pr

  • 问题内容: 我已经升级了系统,并为正在使用的Web应用程序安装了带有PHP的MySql 5.7.9。我有一个动态创建的查询,当在旧版本的MySql中运行时,它运行良好。自升级到5.7以来,出现此错误: SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列’support_desk.mod_users_groups.group_id’,该列在功能上不依赖于GROUP BY子句中