【问题标题】:PHP Mysqli not closing TCP connectionsPHP Mysqli 没有关闭 TCP 连接
【发布时间】:2013-02-25 14:47:03
【问题描述】:

我正在更新我的脚本以从 ext/mysql 移动到 ext/mysqli。它引入了一些问题。

在 ext/mysqli 下,脚本终止时不会释放连接。

脚本都是从命令行运行的。没有 Apache 或其他 HTTP 参与。

出于业务原因,我有时需要进行大量的单数据库交互。它们不是同时活动的,每个操作(插入、更新、选择、删除)在下一个开始之前完成。 在某些情况下,我能够构建大型的单个查询(例如 UPDATE...SET...CASE...WHEN 等),这些都不是问题,因为它们使用的连接当然更少,但是在某些情况下我不能使用这个选项。

每次数据库操作后我都有一个$mysqli->close(),但 (TCP) 连接没有关闭。脚本终止后,连接将保持打开状态,直到超时(如“netstat -an”所示)。

对我的实际影响是我的 TCP 连接用完了。

这些脚本与 ext/mysql 完美结合。

这曾被报告为一个错误 (http://bugs.mysql.com/bug.php?id=38107),但解决方案是升级到 PHP 5.3。我正在使用 5.3.8。

例子:

$mysqli = new mysqli(DB_SERVER, DB_SERVER_USERNAME,DB_SERVER_PASSWORD, DB_DATABASE)         or die ("Unable to connect: " . $mysqli->error());
$result = $mysqli->query($query) or die ("Query failed: " . $mysqli->error . " Actual query: " . $query);
// Do domething interesting with $result
$mysqli->close();
/** TCP connection remains open until it times out at an OS level /**

有没有人遇到过这个问题并找到了解决方案?谢谢。

注意:Stackoverflow 上还有其他类似但不一样的问题。请不要将此作为重复项关闭。

更新:我可能找错了树。我认为这是一个连接问题的原因是因为我收到了这个错误: mysqli::mysqli(): [2002] Only one usage of each socket address (protocol/network address/port) is normally permitted. 我在这里找到的解释 (http://www.online-it-support.co.uk/?p=652) 表明 TCP 端口耗尽是原因。 我可以对我的开发环境进行更改,因为它在我的控制范围内。生产环境不是。 我假设——也许是不明智的——这是不正确的行为。这是基于 ext/mysql 不会出现问题的事实。 也许我的问题应该是“如何让 ext/mysqli 表现得像 ext/mysql?”。

【问题讨论】:

  • 抱歉,尝试将示例格式化为代码,但失败了。
  • 从技术上讲,您不应该在每次操作后关闭连接。除非您与不同的数据库/服务器有多个具有不同凭据的连接,否则可以并且应该重新使用数据库连接。 ->close() 只有在你知道你完成了数据库操作时才应该调用。
  • 这不会让事情变得更糟吗?或者至少没有更好。
  • netstat 报告的连接处于什么状态? “用完 TCP 连接”是什么意思?你的本地端口用完了吗?还是数据库软件的连接限制?还是什么?
  • 我不是说你永远不应该关闭,我只是说重复打开/做某事/关闭/打开/做某事/关闭通常是没有意义和浪费的。打开/做事/做事/做事/关闭是更典型的模式

标签: php tcp mysqli connection


【解决方案1】:

TIME_WAIT 状态下的连接关闭。没有错误或问题。如果您在短时间内创建和关闭大量 TCP 连接,您将最终获得大量处于TIME_WAIT 状态的 TCP 连接。

您要么需要重新使用连接而不是关闭它们,要么找出导致问题的原因并进行修复。例如,增加本地端口的范围可能会有所帮助。

建立和断开 TCP 连接的成本很高。如果你试图在一秒钟内这样做几十次,那你就大错特错了。

【讨论】:

  • 谢谢。您能否详细说明“重用您的连接”?
  • @SimonRoberts:不要关闭连接,因为这会迫使您打开一个新连接。相反,在脚本完成之前保持连接打开,这样它就可以被重用。为每个请求建立和拆除 TCP 连接是不明智的。 在每次操作后关闭。你在问题中这么说。这就是为什么你有这么多关闭的连接。
  • 谢谢。我已经按照你的建议重新编写了,问题已经解决了。所以是我的错误脚本导致了这个问题。我猜想 ext/mysql 一定更容错。我明白为什么我的逻辑把我带到了它的位置,但你的诊断和解决方案是正确的。
【解决方案2】:

你应该使用MySQLi中的持久连接

通过 p 前置主机:打开一个持久连接。 mysqli_change_user() 在打开的连接上自动调用 来自连接池。

这应该使连接保持打开状态,处于可用状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 2020-05-11
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    相关资源
    最近更新 更多