gpt4 book ai didi

php - PDO 持久连接的连接太多?

转载 作者:行者123 更新时间:2023-11-29 03:18:26 24 4
gpt4 key购买 nike

我已经为此苦苦挣扎了很长一段时间,到了需要寻求帮助的地步,因为即使我进行了所有研究,我也无法理解为什么会发生这种情况。

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [1040] Too many connections'

这发生在加载单个页面 (index.php) 时,我是唯一的用户 (dev)。正如您在此处看到的,MySQL 连接限制设置为 @ 50,但我略微超过了它。这是对我重构代码之前创建的 100~ 个连接的改进。

MySQL connections before

这是页面加载一次后的统计信息。

MySQL connections after

我已将问题缩小为几个原因:

  • 我不完全理解 PDO/MySQL 连接是如何工作的。
  • 我在我的代码中创建了太多连接,尽管我试图只创建一个我可以共享的连接。
  • 我需要增加连接限制(似乎不太可能)。

我发现的大多数 SO 问题都告诉 OP 增加连接限制,但并不知道这是否是最佳解决方案,因此如果不需要,我会尽量避免这样做。一个页面加载 50 个连接似乎太多了。

这些是我在相关页面上实例化的类。

$DataAccess = new \App\Utility\DataAccess();
$DataCopyController = new App\Controllers\DataCopyController($DataAccess);
$DriveController = new App\Controllers\DriveController($DataAccess);
$Helper = new App\Utility\Helper();
$View = new App\Views\View();

我正在创建 DAL 对象,然后将其注入(inject)到需要它的类中。通过这种方式,我希望只创建一个对象和一个连接,但这显然不是正在发生的事情。在 DAL 类中,我还向每个查询方法添加了 $this->DbConnect->close()

这是 DataAccess() 类的构造函数。

public function __construct() {

$this->DbConnect = new \App\Services\DbConnect();
$this->db = $this->DbConnect->connect("read");
$this->dbmod = $this->DbConnect->connect("write");

$this->Helper = new Helper();
}

这是 DbConnect() 类。

类 DbConnect {

  private $db;
private $dbmod;

private function isConnected($connection) {
return ($connection) ? TRUE : FALSE;
}

public function connect($access) {

$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];

if ($access == "read") {
if ($this->isConnected($this->db)) {
return $this->db;
} else {
if (strpos($_SERVER['SERVER_NAME'], DBNAME_DEV) === false) {
$this->db = new PDO("mysql:host=127.0.0.1; dbname=".DBNAME,
DBUSER,
DBPASS,
$options
);
} else {
$this->db = new PDO("mysql:host=" . DBHOST_DEV ."; dbname=".DBNAME_DEV,
DBUSER,
DBPASS,
$options
);
}
return $this->db;
}
} elseif ($access == "write") {
if ($this->isConnected($this->dbmod)) {
return $this->dbmod;
} else {
if (strpos($_SERVER['SERVER_NAME'], DBNAME_DEV) === false) {
$this->dbmod = new PDO("mysql:host=127.0.0.1; dbname=".DBNAME,
DBUSER_MOD,
DBPASS,
$options
);
} else {
$this->dbmod = new PDO("mysql:host=" . DBHOST_DEV . "; dbname=".DBNAME_DEV,
DBUSER_MOD,
DBPASS,
$options
);
}
}
return $this->dbmod;
}
}

public function close() {
$this->db = null;
$this->dbmod = null;
}
}

我还尝试在 index.php 上实例化 DbConnect() 类并注入(inject)它而不是 DataAccess() 但结果是一样的。

编辑:我还想补充一点,这个MySQL服务器有两个数据库,prod和dev。我想连接限制在两者之间共享。但是,prod 数据库的流量非常小,我在那里没有看到这个错误。当我刷新统计信息时,没有与 prod 数据库的连接。

最佳答案

来自 PHP 手册 ~ http://php.net/manual/en/pdo.connections.php

Many web applications will benefit from making persistent connections to database servers. Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials.

所以我建议删除 DbConnection#close() 方法,因为您永远不想调用它。

同样来自手册...

Note:
If you wish to use persistent connections, you must set PDO::ATTR_PERSISTENT in the array of driver options passed to the PDO constructor. If setting this attribute with PDO::setAttribute() after instantiation of the object, the driver will not use persistent connections.

所以你会(至少)想要

new \PDO("mysql:host=127.0.0.1;dbname=" . DBNAME, DBUSER, DBPASS, [
PDO::ATTR_PERSISTENT => true
]);

您还可以在构造函数中设置其他连接属性。

关于php - PDO 持久连接的连接太多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50244163/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com