代码之家  ›  专栏  ›  技术社区  ›  Luke Cousins

mysqli::查询未返回FALSE或mysqli_result-PHP错误?

  •  2
  • Luke Cousins  · 技术社区  · 12 年前

    我不确定这是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 manual 对于 SHOW 我们应该始终返回 错误的 或 mysqli_result 对象,但我们也得不到。这行代码每天运行超过100000次,每周失败一次。

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

    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 回复  |  直到 12 年前
        1
  •  1
  •   xdazz    12 年前

    在您的代码中,如果 $q 是 false ,它仍将成为以下条件的if条件:

        if (!$q instanceof mysqli_result) {
    

    也许你需要 else if 相反