[英]Too many connections with PDO persistent connection?
我已經為此苦苦掙扎了很長時間了,這是我需要尋求幫助的地步,因為即使進行了所有研究,我仍然無法理解為什么會發生這種情況。
致命錯誤:消息為“ SQLSTATE [HY000] [1040]的連接過多,未捕獲的異常” PDOException”
這是在加載單個頁面( index.php
)時發生的,並且我是唯一的用戶(dev)。 正如您在此處看到的那樣,MySQL連接限制設置為50,但我幾乎超過了該限制。 這是對重構代碼之前創建的100個連接的改進。
頁面加載一次后的統計信息如下。
我已將問題縮小為幾個原因:
我發現的大多數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對象,然后將其注入需要它的類中。 通過這種方式,我希望只創建一個對象和一個連接,但是這顯然沒有發生。 在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()
類,然后注入該類而不是DataAccess()
但是結果是相同的。
編輯:我還想補充一點,這個MySQL服務器有兩個數據庫,prod和dev。 我想兩者之間共享連接限制。 但是,prod數據庫的流量非常小,並且在那里我沒有看到此錯誤。 當我刷新統計信息時,沒有與prod數據庫的連接。
從PHP手冊〜http://php.net/manual/zh/pdo.connections.php
與Web服務器建立持久連接將使許多Web應用程序受益。 持久連接不會在腳本結尾處關閉,而是在另一個腳本使用相同憑據請求連接時被緩存並重新使用。
因此,我建議刪除DbConnection#close()
方法,因為您永遠都不想調用它。
也是從手冊...
注意:
如果希望使用持久連接,則必須在傳遞給PDO
構造函數的驅動程序選項數組中設置PDO::ATTR_PERSISTENT
。 如果在實例化對象后使用PDO::setAttribute()
設置此屬性,則驅動程序將不使用持久連接。
所以你會想要(至少)
new \PDO("mysql:host=127.0.0.1;dbname=" . DBNAME, DBUSER, DBPASS, [
PDO::ATTR_PERSISTENT => true
]);
您還可以在構造函數中設置其他連接屬性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.