【问题标题】:PHP how to check if a MySQLi query needs to be closed?PHP如何检查MySQLi查询是否需要关闭?
【发布时间】:2010-12-28 06:41:15
【问题描述】:

我为我正在处理的项目创建了一个简单的 MySQLi 类,以使从数据库中提取和推送到数据库变得更容易和更流线化。 (也是为了更熟悉 PHP 中的 OOP

我一直遇到的一个问题是努力使其尽可能高效。我尝试关闭/释放每个查询/语句/结果集。在这样做时,我经常收到以下错误:

Warning: mysqli_result::close(): Couldn't fetch mysqli_result

我想我得到了上面的信息,因为它试图连续两次关闭查询。

目前我的班级可以做出准备好的和未准备好的陈述。所以我尝试在 2 个地方关闭查询/语句。我在准备一个语句时检查我是否已经准备了一个语句,如果是,我需要在创建新语句之前关闭旧语句,最后在类的析构函数中。

我意识到我可以在提取并存储结果后关闭查询/语句,但这似乎很混乱,原因有几个。一方面,它消除了重复使用准备好的语句的可能性。以及不允许我在查询运行后提取有关查询的一些信息,例如受影响的行等。

我知道我可以只为每个查询存储此信息,但似乎解决此问题的正确方法是在我需要创建另一个查询/语句时关闭/释放查询/语句,然后再次在脚本的末尾。

我曾尝试环顾四周并阅读有关如何正确处理此任务的信息,但我无法提出任何建议。

所以我的问题是,是否有办法测试查询或语句是否需要关闭或释放?或者有没有更好的方法我应该尝试解决这个问题?

感谢任何人提供的任何帮助或见解。

【问题讨论】:

    标签: php mysql mysqli prepared-statement


    【解决方案1】:

    我认为如果结果集中没有剩余行,应该自动关闭。因此,如果您遍历整个结果集,则无需调用mysqli_result。但是,如果您仅从包含大约 100 行的结果集中获取第一行,则应该关闭它。

    【讨论】:

    • Hrm 这似乎是真的。我正在搞乱一些测试代码,在执行后执行var_dump,在获取后执行另一个。他们打印同样的东西。在关闭后执行var_dump 时,虽然您得到Property access is not allowed yet,但显然它在做一些不同的事情。尽管问题是否有任何不同的效率?此外,当我将查询限制为 1 行(例如LIMIT 0, 1)时,自己调用 $stmt->fetch() 不会关闭语句。虽然如果我执行while 循环和echo 来确认只有一行它会关闭它。有什么想法吗?
    【解决方案2】:

    您可以在关闭它后将其设置为null,并在将其关闭之前在析构函数中检查null。

    显然,当您确定已完成使用准备好的语句时,您只想将其设为空。

    【讨论】:

    • 这和关闭一个语句一样吗?我真的没有问题,就这么说吧。我不会下定决心确保它无缘无故关闭。我只是觉得关闭语句并释放结果集是明智地处理事情的正确方法。我知道对于小事来说,这可能不是最大的交易,尽管如果您的项目看到大量流量并扩展,这很重要。如果你在这样的条件下工作,那么每一点效率都很重要,那么应该怎么做?
    【解决方案3】:

    您可以使用RAII 或工厂类+引用计数来管理语句。这样你就不需要明确检查什么时候关闭任何东西。如果不了解您如何使用包装器的详细信息,则很难详细说明。 Objective-C 的访问器模式也可能有用,它看起来像:

    private function unsetStatement() {
        if (isset($this->_stmt)) {
            $this->_stmt->close();
            unset($this->_stmt);
        }
    }
    function getStatement() {
        return $this->_stmt;
    }
    function setStatement($stmt) {
        $this->unsetStatement();
        $this->_stmt = $stmt;
    }
    

    您只能通过上述函数访问语句成员字段,即使在类中也是如此。实际上,它看起来更像:

    -(Statement *)statement {
        return stmt_;
    }
    -(void)setStatement:(Statement *)stmt {
        [stmt_ release];
        stmt = [stmt retain];
    }
    

    【讨论】:

      【解决方案4】:

      这是我使用的。如果语句中有任何结果,我知道我需要释放结果:

      if($stmt->num_rows() != 0)
      {
          $stmt->free_result();
      
          return FALSE;
      }
      

      【讨论】:

        【解决方案5】:

        如果mysqli查询结果已经是null,你会在PHP 5中得到如下警告:

         Warning: myfunction(): Property access is not allowed yet in ....
        

        原则上,可以使用自定义错误处理程序来处理这些情况,或者简单地抑制警告/错误,即is_object($mysqliqresult) && @$mysqliqresult->free()

        或者通过prepare方法使用mysqli-statements,而不是直接运行mysqlidblink->查询,如下:

        $query = "SELECT heptagon,hexagon FROM pentagon ORDER BY hexagon";
        $stmt = $dblink->prepare($query);
        $stmt->execute();
        !$stmt->field_count() && $stmt->free_result();
        

        贾斯汀的建议也不错。

        【讨论】:

          【解决方案6】:

          我找到的最安全的方式:

          try { 
              $result->close(); 
          } 
          catch (Exception $exception){}
          

          【讨论】:

            猜你喜欢
            • 2023-03-31
            • 2011-02-21
            • 2011-07-13
            • 2012-10-11
            • 2013-04-25
            • 2017-12-21
            • 1970-01-01
            • 2017-07-09
            相关资源
            最近更新 更多