代码之家  ›  专栏  ›  技术社区  ›  Jhonny D. Cano -Leftware-

PDO未缓冲查询

  •  14
  • Jhonny D. Cano -Leftware-  · 技术社区  · 16 年前

    我想了解一下PDO的细节。所以我把它编码了:

    $cn = getConnection();
    
    // get table sequence
    $comando = "call p_generate_seq('bitacora')";
    $id = getValue($cn, $comando);
    
    //$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (?, ?, ?)';
    $comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (:id, :estado, :fch_creacion)';
    $parametros = array (
        ':id'=> (int)$id,
        ':estado'=>1,
        ':fch_creacion'=>date('Y-m-d H:i:s')
    );
    execWithParameters($cn, $comando, $parametros);
    

    我的getValue函数工作正常,我得到表的下一个序列。但是当我进入execWithParameters时,我得到了这个异常:

    pdoexception:sqlstate[hy000]:常规错误:2014无法在其他未缓冲查询处于活动状态时执行查询。考虑使用pDoStatement::FetchAll()。或者,如果您的代码只针对MySQL运行,则可以通过设置pdo::mysql_attr_use_buffered_query属性来启用查询缓冲。在第77行的d:\servidor\xampp_1_7_1\htdocs\bitacora\func_db.php中

    我试图修改连接属性,但它不起作用。

    以下是我的核心数据库功能:

    function getConnection() {
        try {
            $cn = new PDO("mysql:host=$host;dbname=$bd", $usuario, $clave, array(
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                ));
    
            $cn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
            return $cn;
        } catch (PDOException $e) {
            print "Error!: " . $e->getMessage() . "<br/>";
            die();
        }
    }
    function getValue($cn, $comando) {
        $resul = $cn->query($comando);
            if (!$resul) return null;
            while($res = $resul->fetch()) {
                $retorno = $res[0][0];
                break;
            }
            return $retorno;
    }
    function execWithParameters($cn, $comando, $parametros) {
        $q = $cn->prepare($comando);
        $q->execute($parametros);
        if ($q->errorInfo() != null) {
            $e = $q->errorInfo();
            echo $e[0].':'.$e[1].':'.$e[2];
        }
    }
    

    有人能为此发光吗?警察局。请不要建议做自动编号ID,因为我正在从另一个系统移植。

    6 回复  |  直到 11 年前
        1
  •  21
  •   Wez Furlong    16 年前

    问题是MySQL在给定的时间只允许有一个未完成的光标。通过使用fetch()方法而不使用所有挂起的数据,您将使光标保持打开状态。

    建议的方法是使用fetchall()方法使用所有数据。 另一种方法是使用closeCursor()方法。

    如果你改变这个功能,我认为你会更快乐:

    <?php
    function getValue($cn, $comando) {
        $resul = $cn->query($comando);
        if (!$resul) return null;
        foreach ($resul->fetchAll() as $res) {
                $retorno = $res[0];
                break;
        }
        return $retorno;
    }
    ?>
    
        2
  •  16
  •   Jonathon Hill    14 年前

    我认为,如果不执行返回数据的查询(即更新、插入等),pdoStatement::closeCursor()将不起作用。

    更好的解决方案是在调用pdoState::Execute()之后,简单地取消设置pdoStatement对象:

    $stmt = $pdo->prepare('UPDATE users SET active = 1');
    $stmt->execute();
    unset($stmt);
    
        3
  •  8
  •   Tordek    16 年前

    问题似乎是——我不太熟悉PDO——在您的getValue调用返回之后,查询仍然绑定到连接(您只需要请求第一个值,但是连接返回几个值,或者期望这样做)。

    也许getValue可以通过添加

    $resul->closeCursor();
    

    在返回之前。

    否则,如果对getValue的查询总是返回单个(或足够少的)值,则似乎首选使用fetchall。

        4
  •  3
  •   Henrik    11 年前

    我只花了15分钟的时间在互联网上搜索,查看了至少5个不同的stackoverflow问题,其中一些人声称我的bug显然是由错误的PHP版本、错误的mysql库版本或任何其他神奇的黑盒东西引起的…

    我把所有的代码都改为使用“fetchall”,甚至在每次查询之后都在查询对象上调用closecursor()和unset()。我真的很绝望!我还尝试了mysql_attr_use_buffered_query标志,但它不起作用。

    终于 我把所有东西都扔到了窗口外,查看了PHP错误,并跟踪了发生错误的代码行。

    SELECT AVG((original_bytes-new_bytes)/original_bytes) as saving 
        FROM (SELECT original_bytes, new_bytes FROM jobs ORDER BY id DESC LIMIT 100) AS t1
    

    不管怎样,问题的发生是因为我 原始字节 新字节 这两个都是无符号的bigints,这意味着如果我曾经有过一个新的\字节实际上比原来的\字节大的作业,那么我会有一个讨厌的mysql“超出范围”的错误。这只是在运行我的缩小服务一段时间后随机发生的。

    为什么我得到了这个奇怪的MySQL错误而不是简单的错误,这是我无法理解的!当我运行原始查询时,它实际上出现在sqlbuddy(轻量级phpmyadmin)中。 我在上有PDO异常,所以它应该只是给了我mysql错误。

    没关系,底线是:

    如果你遇到这个错误,一定要检查你的原始MySQL是否正确并且仍然工作!!!

        5
  •  0
  •   VolkerK    16 年前

    我的一个朋友在XAMPP1.7.1构建中遇到了很多相同的问题。在用5.2.9-2php.net版本替换xampp/php/*并将所有必需的文件复制到xampp/apache/bin之后,它工作得很好。

        6
  •  0
  •   rorrohprog    15 年前

    如果您使用的是XAMPP 1.7.1,则只需升级到1.7.2即可。

    推荐文章