【问题标题】:Error 2014: Commands Out of Sync (Happens in one server but not another)错误 2014:命令不同步(发生在一台服务器上,但不在另一台服务器上)
【发布时间】:2013-08-24 14:41:29
【问题描述】:

编辑:

好的,所以,我做了更多的测试,发现是存储过程搞砸了一切。但我不知道为什么 存储过程会搞砸。有关详细信息,请参阅我在此帖子下的第一条评论。

/编辑

好的,我已经完成了这个学校项目,我一直在使用我的笔记本电脑作为服务器。但是,如果不将其放在学校的服务器上,我就无法提交。我的讲师终于允许我访问它,我终于能够开始在那里迁移我的项目。

在修复了大量较小的问题(如默认字符集不匹配和区分大小写问题)后,这个特殊问题出现了,让我很困惑。我花了几个小时运行我的代码,查看 PHP 文档并修改我的代码以打印出调试文本墙,最后用尽可能少的代码重新生成了错误。

这是 PHP 代码:

<?php
    define("HOST", "someHost");
    define("USER", "someUser");
    define("PASS", "somePass");
    define("DB"  , "someDB");
    $conn = mysqli_connect(HOST, USER, PASS, DB);

    $stmt1 = $conn->stmt_init();
    if (!$stmt1->prepare("CALL P_Topics_Get(33);")) {//If I uncomment this, I get an error when trying to prepare $stmt2
    //if (!$stmt1->prepare("SELECT * FROM Topics WHERE id = 33;")) { //If I uncomment this, I DON'T get an error anywhere
    //if (!$stmt1->prepare("SELECT 0, 'name', 1, 2, 3;")) {//If I uncomment this, I DON'T get an error anywhere
        echo "Failed to prepare 1: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    if (!$stmt1->execute()) {
        echo "Failed to execute 1: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    if (!$stmt1->store_result()) {
        echo "Failed to store 1: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    $stmt1->bind_result($id, $name, $step, $decAmt, $maxAmt);
    if (!$stmt1->fetch()) {
        echo "Failed to fetch 1: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    echo "$id, $name, $step, $decAmt, $maxAmt<br>";
    $stmt1->free_result();
    $stmt1->close();

    $stmt2 = $conn->stmt_init();
    if (!$stmt2->prepare("SELECT 2;")) {
        echo "Failed to prepare 2: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    if (!$stmt2->execute()) {
        echo "Failed to execute 2: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    if (!$stmt2->store_result()) {
        echo "Failed to store 2: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    $stmt2->bind_result($val2);
    if (!$stmt2->fetch()) {
        echo "Failed to fetch 2: " . $conn->errno . ", " . $conn->error;
        exit;
    }
    echo "Val 2: " . $val2 . "<br>";
    $stmt2->free_result();
    $stmt2->close();

    echo "success";
?>

P_Topics_Get() 是一个简单的从表中选择语句:

SELECT
  *
FROM
  Topics t
WHERE
  t.id = topicId;

所以.. 是的。这适用于我的本地主机,没有错误,但会在学校的机器上搞砸一切。这是我第一次遇到 2014 年的错误。而且只是 2013 年! (/笑话)

有人知道怎么回事吗?

【问题讨论】:

  • 我在测试中添加了这个 if 语句:if (!$stmt1-&gt;prepare("SELECT * FROM Topics WHERE id = 33;")) { //If I uncomment this, I DON'T get an error anywhere,有了这个 if 语句(基本上是存储过程),它不会在任何地方崩溃或显示错误。我可以得出结论,问题出在存储过程上。不知何故。我现在才确定为什么。

标签: php stored-procedures mysqli prepared-statement


【解决方案1】:

好的,我找到了解决方法。 如果你有一个 dbconfig.php 文件,添加一个简单的函数到它:

function reconnect () {
    global $conn;
    $conn->close();
    $conn = mysqli_connect(HOST, USER, PASS, DB);
}

我的 dbconfig.php 文件如下所示:

<?php
    //Configurables
    define("HOST", "someHost");
    define("USER", "someUser");
    define("PASS", "somePass");
    define("DB"  , "someDB");
    //End Configurables
    $conn = mysqli_connect(HOST, USER, PASS, DB);

    if (mysqli_connect_errno()) {
        echo "Server error: Please try again later.";
        //printf("Connect failed: %s\n", mysqli_connect_error());
        exit();
    }

    function reconnect () {
        global $conn;
        $conn->close();
        $conn = mysqli_connect(HOST, USER, PASS, DB);
    }
?>

然后,每次调用存储过程后,调用reconnect()

$stmt = $conn->stmt_init(); //Old $conn
$stmt->prepare("CALL SomeProcedure();");
$stmt->execute();
$stmt->store_result();
$stmt->bind_result();
$stmt->fetch();
$stmt->close();
reconnect(); //$conn is closed and re-opened

//$conn is a new connection

问题是,在我的例子中,如果你调用一个存储函数,你不必reconnect()。 例如,SELECT F_SomeFunction(); 不需要 reconnect(),而 CALL P_SomeProcedure(); 需要。

【讨论】:

    【解决方案2】:

    您可能需要清除更多结果,和/或关闭光标。

    见:Python, "commands out of sync; you can't run this command now"

    http://php.net/manual/en/pdostatement.closecursor.php

    对不起,我不是 PHP 开发人员,所以没有费心去尝试。

    【讨论】:

    • 我没有使用 PDO,我使用的是旧的 mysqli。另外,我确实调用了 free_result() 和 close(),它们的效果与 closeCursor() 相同。另外,我的存储过程只返回一行,所以不可能还有行要获取。谢谢你的尝试,虽然 =x
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多