mysqli :: query没有返回FALSE或mysqli_result - PHP bug?

时间:2014-09-05 09:05:20

标签: php mysql mysqli galera

我不确定这是否是PHP,MySQL或我是一个愚蠢的错误但很偶然(而且非常罕见)我们致电mysqli::query并且没有得到FALSE或者反对mysqli_result

我们正在运行:

  • PHP 5.5.9-1ubuntu4.3
  • MySQL Ver 15.1 Distrib 5.5.38-MariaDB,debian-linux-gnu(x86_64)使用readline 5.1(使用Galera)

查询运行时为SHOW STATUS LIKE "Questions"

根据the manualSHOW查询,我们应该始终返回FALSEmysqli_result个对象,但我们也没有。这行代码每天运行超过100,000次,每周大约失败一次。

以下是我们的数据库包装器的代码片段(该函数仅用于读取查询):

public function read($query, $cache = 0) {
    $total_time_start = microtime(1);

    $deadlock_retries_done = 0;
    $deadlock_retries_max = 10;
    $other_error_retries_done = 0;
    $other_error_retries_max = 10;

    $return = array(); // Keeps IDEs happy!

    while (true) {
        $start = microtime(1);
        $return = array();
        $q = $this->connection->query($query, MYSQLI_STORE_RESULT);
        $this->debug_last_query = $query;

        // Was there an error?
        if ($q === false) {
            $error = $this->connection->error;
            switch ($error) {
                case 'Deadlock found when trying to get lock; try restarting transaction':
                case 'Lock wait timeout exceeded; try restarting transaction':
                    $deadlock_retries_done++;
                    if ($deadlock_retries_done == $deadlock_retries_max) {
                        throw new SQLException($error . '. Re-tried with deadlock ' . $deadlock_retries_done . ' times. Query: ' . $query);
                    } else {
                        continue; // Try again
                    }
                    break;

                case 'WSREP has not yet prepared node for application use':
                    $other_error_retries_done++;
                    if ($other_error_retries_done == $other_error_retries_max) {
                        throw new SQLException($error . '. Re-tried with error ' . $other_error_retries_done . ' times. Query: ' . $query);
                    } else {
                        if ($this->in_transaction) {
                            throw new SQLException($error . '. Re-tried with error ' . $other_error_retries_done . ' times. Cannot reconnect as in transaction. Query: ' . $query);
                        } else {
                            $this->close_and_establish_new_database_connection();
                            continue; // Try again
                        }
                    }
                    break;

                default:
                    throw new SQLException($error . '. Query: ' . $query);
                    break;
            }
        }

        // Check we have got a result
        if (!$q instanceof mysqli_result) {
            throw new SQLException('Seemed to have a result but it is not a mysqli_result object. Query: ' . $query);
        }

        // All worked ok, deal with the result
        while (($row = $q->fetch_assoc())) {
            $return[] = $row;
        }
        $end = microtime(1);

        $this->debugData($start, $end, $query, 'DB', '', $total_time_start, $cache);

        $this->last_affected_rows = $q->num_rows;
        $q->free_result();
        break;
    }

    return $return;
}

显然,它会调用一些未包含在代码段中的函数,但您应该明白这一点。

抛出的异常是:

SQLException: Seemed to have a result but it is not a mysqli_result object. Query: SHOW STATUS LIKE "Questions"

我将在我们的异常消息中添加一些内容来输出$q实际上是什么并等待它再次发生。

有没有其他人都经历过这样的事情,你有什么建议吗?我非常感谢你的帮助。感谢


修改

我们刚刚在一个非常简单的SELECT cols FROM table WHERE key = x LIMIT 1;类型查询中发生过(出于安全原因,未显示真正的查询,但它是关于您可能拥有的最简单的查询)。这发生在我的额外记录生效之前。当我得到另一个希望更多的细节时,我会再次在这里更新。

1 个答案:

答案 0 :(得分:1)

在您的代码中,如果$qfalse,则仍会进入if条件:

    if (!$q instanceof mysqli_result) {

也许你需要else if