Я боролся с этим уже довольно давно, и до такой степени, что мне нужно обратиться за помощью, потому что даже после всех исследований, которые я провел, я не могу понять, почему это происходит.
Неустранимая ошибка: необработанное исключение «PDOException» с сообщением «SQLSTATE [HY000] [1040] Слишком много соединений»
Это происходит при загрузке одной страницы (index.php
), и я единственный пользователь (dev). Как вы можете видеть здесь, предел подключения MySQL установлен @ 50, но я немного превышаю его. Это улучшение по сравнению со 100 соединениями, которые создавались до того, как я реорганизовал код.
Вот статистика после однократной загрузки страницы.
Я сузил проблему до нескольких причин:
- Я не совсем понимаю, как работают соединения 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, затем внедряю его в классы, которые в нем нуждаются. Делая это таким образом, я надеялся создать только один объект и одно соединение, однако, очевидно, это не то, что происходит. Внутри класса 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;
}
}
Я также пытался создать экземпляр DbConnect()
класса на index.php
и внедрить его вместо DataAccess()
, но результат был тот же.
EDIT:
Я также хочу добавить, что этот сервер MySQL имеет две базы данных, prod и dev. Я предполагаю, что лимит соединения распределяется между обоими. Однако база данных prod получает очень мало трафика, и я не вижу там этой ошибки. Когда я обновил статистику, к базе данных prod не было подключений.