【问题标题】:How reconnect and retry a MySQL query in PHP when the database connection has been lost?当数据库连接丢失时,如何在 PHP 中重新连接并重试 MySQL 查询?
【发布时间】:2017-05-26 18:51:27
【问题描述】:

我有一个 PHP 文件,它有时执行时间很长,并且 MySQL 连接(一个 mysqli 对象)过时了。如果我检查与 mysqli_ping 的连接(如果mysqli_ping 返回false,则重新连接),那么我永远不会遇到问题。但是,pinging before every query seems highly inefficient,所以我只想在查询失败时执行 ping 检查(并重新连接)。我的问题是我似乎无法让我的代码在 mysqli_query 失败时引发异常以触发重新连接。

这是我的“基本”代码:

<?php

function query($query) {
   $connection = $GLOBALS['global_connection'];
   if(empty($connection) || mysqli_connect_errno()) $connection = connect();

   try {
        $result = mysqli_query($connection, $query);
   } catch(Exception $e) {
        if(!mysqli_ping($connection)) {
           $connection = connect(); // reestablish the connection
           $GLOBALS['global_connection'] = $connection; // update global connection value
           $result = mysqli_query($connection, $query); // requery using the new connection
        }
   }

   return $result;
}

问题是mysqli_query 中的错误连接不会导致引发异常,但会导致错误出现在我的错误日志中。

我在mysqli_query 之前尝试过mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); (as suggested in other questions),但它不会改变结果。我还在我的 PHP 配置中启用了mysqli.reconnect,但这似乎并没有阻止这一点。

所以我的问题是:

mysqli_query 失败(由于连接超时)时如何抛出异常?

如何高效地自动重新连接数据库?

【问题讨论】:

  • mysqli 函数不会抛出异常,它们只会在失败时返回FALSENULL。你需要用mysqli_errno()检查原因。
  • 文档说如果你有 MYSQLND 驱动程序,mysqli.reconnect 会被忽略。
  • 所以我真正需要做的就是:$result = mysqli_query($connection, $query); if(empty($result)) { if(!mysqli_ping($connection)) { $connection = connect(); // re-establish the connection $GLOBALS['global_connection'] = $connection; // update global connection value $result = mysqli_query($connection, $query); // re-query using the new connection } } ...那是我的愚蠢。我在想一个没有结果的搜索会因为某种原因返回 null/false...
  • 仅供参考,这是错误号 2006。
  • 您可以将超时更改为非常短的时间,然后运行一个脚本,该脚本使用sleep() 调用使其断开连接。

标签: php mysql mysqli


【解决方案1】:

根据Barmarthe comments 中的帮助,我意识到我所要做的就是:

<?php
$result = mysqli_query($connection, $query);
if(empty($result)) {
    if(!mysqli_ping($connection)) {
        $connection = connect(); // re-establish the connection 
        $GLOBALS['global_connection'] = $connection; // update global connection value
        $result = mysqli_query($connection, $query); // re-query using the new connection
    }
}

根本不需要try{}catch!干净简单。

【讨论】:

    【解决方案2】:

    您将需要管理(抛出)您自己的自定义异常,以使其也以您需要的方式工作。我会考虑制作一个数据库抽象类来帮助处理这个问题。数据库类将有一个成员变量,它是连接引用,并且可以使用 mysqli 内置的错误处理来引发与该 mysqli 连接对象实例相关的自定义异常。

    如果您只需要一个数据库连接,我可能会尝试单例模式。

    【讨论】:

      猜你喜欢
      • 2020-09-21
      • 1970-01-01
      • 2013-03-23
      • 2017-12-06
      • 1970-01-01
      • 2016-12-18
      • 2017-09-08
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多